Compare commits

..

19 Commits

Author SHA1 Message Date
Evgeny Poberezkin 22c62d544c Merge branch 'ep/remove-mtl' into ab/ios-haskell-init 2024-03-31 12:26:52 +01:00
Evgeny Poberezkin fbe9a4da39 strict data, optimization 2024-03-31 11:54:58 +01:00
Alexander Bondarenko 2995a79041 update to deMTLd branches 2024-03-31 13:48:52 +03:00
Alexander Bondarenko da197a35a0 Merge remote-tracking branch 'origin/ep/remove-mtl' into ab/ios-haskell-init 2024-03-31 11:27:14 +03:00
Evgeny Poberezkin 6f8578d0f1 core: remove mtl typeclasses to reduce overhead 2024-03-30 23:49:50 +00:00
Alexander Bondarenko 73cabd3c69 add info tables 2024-03-30 16:35:46 +03:00
Alexander Bondarenko c30c181209 unify init_haskell to allow nse profiling 2024-03-30 15:47:48 +03:00
Alexander Bondarenko 701b4186b6 Merge remote-tracking branch 'origin/master' into ios-profiling 2024-03-30 15:47:29 +03:00
Evgeny Poberezkin 257e03f10a Merge branch 'master' into ios-profiling 2024-03-29 19:44:17 +00:00
Alexander Bondarenko 7b644c0dcf Merge remote-tracking branch 'origin/master' into ios-profiling 2024-03-28 20:10:35 +02:00
Alexander Bondarenko c3d9d9a7c3 Merge remote-tracking branch 'origin/master' into ios-profiling 2024-03-27 17:40:14 +02:00
Alexander Bondarenko 261767035e Merge remote-tracking branch 'origin/master' into ios-profiling 2024-03-20 11:22:48 +02:00
spaced4ndy c9b00b3054 Merge branch 'master' into ios-profiling 2024-03-13 11:50:17 +04:00
spaced4ndy 1697190189 remove print 2024-03-12 20:52:05 +04:00
spaced4ndy 24609a98c6 fix paths 2024-03-12 20:49:42 +04:00
Alexander Bondarenko 60752feb9c fix addr 2024-03-12 17:09:54 +02:00
Alexander Bondarenko ff5ef638cd add missing include 2024-03-12 17:09:54 +02:00
spaced4ndy df619d540b ios: save debug profile, event log buttons (#3899) 2024-03-12 19:06:25 +04:00
Alexander Bondarenko 53d8a85b8c add RTS tuning to haskell_init 2024-03-12 16:58:44 +02:00
41 changed files with 1069 additions and 875 deletions
+4 -2
View File
@@ -22,8 +22,10 @@ struct SimpleXApp: App {
init() {
DispatchQueue.global(qos: .background).sync {
haskell_init()
// hs_init(0, nil)
// we have to use debug profile file name without extension here because .hp extension is added by profiler
// haskell_init(0, nil, nil)
let dummyHpPath = getAppDebugProfilePrefixPath().path + "_dummy" // not used, but required to populate eventlog
haskell_init(0, getAppEventLogPath().path, dummyHpPath)
}
UserDefaults.standard.register(defaults: appDefaults)
setGroupDefaults()
@@ -70,14 +70,14 @@ struct CIImageView: View {
}
private func imageView(_ img: UIImage) -> some View {
let w = img.size.width <= img.size.height ? maxWidth * 0.75 : maxWidth
let w = img.size.width <= img.size.height ? maxWidth * 0.75 : img.imageData == nil ? .infinity : maxWidth
DispatchQueue.main.async { imgWidth = w }
return ZStack(alignment: .topTrailing) {
if img.imageData == nil {
Image(uiImage: img)
.resizable()
.scaledToFit()
.frame(width: w)
.frame(maxWidth: w)
} else {
SwiftyGif(image: img)
.frame(width: w, height: w * img.size.height / img.size.width)
@@ -243,13 +243,13 @@ struct CIVideoView: View {
}
private func imageView(_ img: UIImage) -> some View {
let w = img.size.width <= img.size.height ? maxWidth * 0.75 : maxWidth
let w = img.size.width <= img.size.height ? maxWidth * 0.75 : .infinity
DispatchQueue.main.async { videoWidth = w }
return ZStack(alignment: .topTrailing) {
Image(uiImage: img)
.resizable()
.scaledToFit()
.frame(width: w)
.frame(maxWidth: w)
loadingIndicator()
}
}
+1 -3
View File
@@ -514,7 +514,6 @@ struct ChatView: View {
chat: chat,
chatItem: ci,
maxWidth: maxWidth,
itemWidth: maxWidth,
composeState: $composeState,
selectedMember: $selectedMember,
chatView: self
@@ -527,7 +526,6 @@ struct ChatView: View {
@ObservedObject var chat: Chat
var chatItem: ChatItem
var maxWidth: CGFloat
@State var itemWidth: CGFloat
@Binding var composeState: ComposeState
@Binding var selectedMember: GMember?
var chatView: ChatView
@@ -656,7 +654,7 @@ struct ChatView: View {
playbackState: $playbackState,
playbackTime: $playbackTime
)
.uiKitContextMenu(hasImageOrVideo: ci.content.msgContent?.isImageOrVideo == true, maxWidth: maxWidth, itemWidth: $itemWidth, menu: uiMenu, allowMenu: $allowMenu)
.uiKitContextMenu(maxWidth: maxWidth, menu: uiMenu, allowMenu: $allowMenu)
.accessibilityLabel("")
if ci.content.msgContent != nil && (ci.meta.itemDeleted == nil || revealed) && ci.reactions.count > 0 {
chatItemReactions(ci)
@@ -11,20 +11,11 @@ import UIKit
import SwiftUI
extension View {
func uiKitContextMenu(hasImageOrVideo: Bool, maxWidth: CGFloat, itemWidth: Binding<CGFloat>, menu: Binding<UIMenu>, allowMenu: Binding<Bool>) -> some View {
func uiKitContextMenu(maxWidth: CGFloat, menu: Binding<UIMenu>, allowMenu: Binding<Bool>) -> some View {
Group {
if allowMenu.wrappedValue {
if hasImageOrVideo {
InteractionView(content:
self.environmentObject(ChatModel.shared)
.overlay(DetermineWidthImageVideoItem())
.onPreferenceChange(DetermineWidthImageVideoItem.Key.self) { itemWidth.wrappedValue = $0 == 0 ? maxWidth : $0 }
, maxWidth: maxWidth, itemWidth: itemWidth, menu: menu)
.frame(maxWidth: itemWidth.wrappedValue)
} else {
InteractionView(content: self.environmentObject(ChatModel.shared), maxWidth: maxWidth, itemWidth: itemWidth, menu: menu)
.fixedSize(horizontal: true, vertical: false)
}
InteractionView(content: self, maxWidth: maxWidth, menu: menu)
.fixedSize(horizontal: true, vertical: false)
} else {
self
}
@@ -40,14 +31,13 @@ private class HostingViewHolder: UIView {
struct InteractionView<Content: View>: UIViewRepresentable {
let content: Content
var maxWidth: CGFloat
var itemWidth: Binding<CGFloat>
@Binding var menu: UIMenu
func makeUIView(context: Context) -> UIView {
let view = HostingViewHolder()
view.contentSize = CGSizeMake(maxWidth, .infinity)
view.backgroundColor = .clear
let hostView = UIHostingController(rootView: content)
view.contentSize = hostView.view.intrinsicContentSize
hostView.view.translatesAutoresizingMaskIntoConstraints = false
let constraints = [
hostView.view.topAnchor.constraint(equalTo: view.topAnchor),
@@ -67,11 +57,7 @@ struct InteractionView<Content: View>: UIViewRepresentable {
}
func updateUIView(_ uiView: UIView, context: Context) {
let was = (uiView as! HostingViewHolder).contentSize
(uiView as! HostingViewHolder).contentSize = uiView.subviews[0].sizeThatFits(CGSizeMake(itemWidth.wrappedValue, .infinity))
if was != (uiView as! HostingViewHolder).contentSize {
uiView.invalidateIntrinsicContentSize()
}
(uiView as! HostingViewHolder).contentSize = uiView.subviews[0].sizeThatFits(CGSizeMake(maxWidth, .infinity))
}
func makeCoordinator() -> Coordinator {
@@ -21,19 +21,6 @@ struct DetermineWidth: View {
}
}
struct DetermineWidthImageVideoItem: View {
typealias Key = MaximumWidthImageVideoPreferenceKey
var body: some View {
GeometryReader { proxy in
Color.clear
.preference(
key: MaximumWidthImageVideoPreferenceKey.self,
value: proxy.size.width
)
}
}
}
struct MaximumWidthPreferenceKey: PreferenceKey {
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
@@ -41,13 +28,6 @@ struct MaximumWidthPreferenceKey: PreferenceKey {
}
}
struct MaximumWidthImageVideoPreferenceKey: PreferenceKey {
static var defaultValue: CGFloat = 0
static func reduce(value: inout CGFloat, nextValue: () -> CGFloat) {
value = max(value, nextValue())
}
}
struct DetermineWidth_Previews: PreviewProvider {
static var previews: some View {
DetermineWidth()
@@ -45,6 +45,11 @@ struct DeveloperView: View {
}
if developerTools {
Section {
exportDebugProfileButton()
exportEventLogButton()
}
Section {
settingsRow("key") {
Toggle("Post-quantum E2EE", isOn: $pqExperimentalEnabled)
@@ -62,6 +67,24 @@ struct DeveloperView: View {
}
}
@ViewBuilder private func exportDebugProfileButton() -> some View {
let url = getAppDebugProfilePath()
settingsRow("square.and.arrow.up") {
Button("Export debugging profile") {
showShareSheet(items: [url])
}
}.disabled(!FileManager.default.fileExists(atPath: url.path))
}
@ViewBuilder private func exportEventLogButton() -> some View {
let url = getAppEventLogPath()
settingsRow("square.and.arrow.up") {
Button("Export event log") {
showShareSheet(items: [url])
}
}.disabled(!FileManager.default.fileExists(atPath: url.path))
}
private func setPQExperimentalEnabled(_ enable: Bool) {
do {
try apiSetPQEncryption(enable)
+44 -53
View File
@@ -65,24 +65,20 @@ class NSEThreads {
}
func processNotification(_ id: ChatId, _ ntf: NSENotification) async -> Void {
var waitTime: Int64 = 5_000_000000
while waitTime > 0 {
if let (_, nse) = rcvEntityThread(id),
nse.shouldProcessNtf && nse.processReceivedNtf(ntf) {
var timeoutOfWaiting: Int64 = 5_000_000000
while timeoutOfWaiting > 0 {
let activeThread = NSEThreads.queue.sync {
activeThreads.first(where: { (_, nse) in nse.receiveEntityId == id })
}
if activeThread?.1.processReceivedNtf?(ntf) == true {
break
} else {
try? await Task.sleep(nanoseconds: 10_000000)
waitTime -= 10_000000
timeoutOfWaiting -= 10_000000
}
}
}
private func rcvEntityThread(_ id: ChatId) -> (UUID, NotificationService)? {
NSEThreads.queue.sync {
activeThreads.first(where: { (_, nse) in nse.receiveEntityId == id })
}
}
func endThread(_ t: UUID) -> Bool {
NSEThreads.queue.sync {
let tActive: UUID? = if let index = activeThreads.firstIndex(where: { $0.0 == t }) {
@@ -117,11 +113,9 @@ class NotificationService: UNNotificationServiceExtension {
// thread is added to allThreads here - if thread did not start chat,
// chat does not need to be suspended but NSE state still needs to be set to "suspended".
var threadId: UUID? = NSEThreads.shared.newThread()
var notificationInfo: NtfMessages?
var receiveEntityId: String?
var expectedMessages: Set<String> = []
// return true if the message is taken - it prevents sending it to another NotificationService instance for processing
var shouldProcessNtf = false
var processReceivedNtf: ((NSENotification) -> Bool)?
var appSubscriber: AppSubscriber?
var returnedSuspension = false
@@ -198,11 +192,39 @@ class NotificationService: UNNotificationServiceExtension {
? .nse(createConnectionEventNtf(ntfInfo.user, connEntity))
: .empty
)
if let id = connEntity.id, ntfInfo.msgTs != nil {
notificationInfo = ntfInfo
if let id = connEntity.id, let msgTs = ntfInfo.msgTs {
var expected = Set(ntfInfo.ntfMessages.map { $0.msgId })
processReceivedNtf = { ntf in
if !ntfInfo.user.showNotifications {
self.setBestAttemptNtf(.empty)
}
if case let .msgInfo(info) = ntf {
let found = expected.remove(info.msgId)
if found != nil {
logger.debug("NotificationService processNtf: msgInfo, last: \(expected.isEmpty)")
if expected.isEmpty {
self.deliverBestAttemptNtf()
}
return true
} else if info.msgTs > msgTs {
logger.debug("NotificationService processNtf: unexpected msgInfo, let other instance to process it, stopping this one")
self.deliverBestAttemptNtf()
return false
} else {
logger.debug("NotificationService processNtf: unknown message, let other instance to process it")
return false
}
} else if ntfInfo.user.showNotifications {
logger.debug("NotificationService processNtf: setting best attempt")
self.setBestAttemptNtf(ntf)
if ntf.isCallInvitation {
self.deliverBestAttemptNtf()
}
return true
}
return false
}
receiveEntityId = id
expectedMessages = Set(ntfInfo.ntfMessages.map { $0.msgId })
shouldProcessNtf = true
return
}
}
@@ -218,38 +240,6 @@ class NotificationService: UNNotificationServiceExtension {
deliverBestAttemptNtf(urgent: true)
}
func processReceivedNtf(_ ntf: NSENotification) -> Bool {
guard let ntfInfo = notificationInfo, let msgTs = ntfInfo.msgTs else { return false }
if !ntfInfo.user.showNotifications {
self.setBestAttemptNtf(.empty)
}
if case let .msgInfo(info) = ntf {
let found = expectedMessages.remove(info.msgId)
if found != nil {
logger.debug("NotificationService processNtf: msgInfo, last: \(self.expectedMessages.isEmpty)")
if expectedMessages.isEmpty {
self.deliverBestAttemptNtf()
}
return true
} else if info.msgTs > msgTs {
logger.debug("NotificationService processNtf: unexpected msgInfo, let other instance to process it, stopping this one")
self.deliverBestAttemptNtf()
return false
} else {
logger.debug("NotificationService processNtf: unknown message, let other instance to process it")
return false
}
} else if ntfInfo.user.showNotifications {
logger.debug("NotificationService processNtf: setting best attempt")
self.setBestAttemptNtf(ntf)
if ntf.isCallInvitation {
self.deliverBestAttemptNtf()
}
return true
}
return false
}
func setBadgeCount() {
badgeCount = ntfBadgeCountGroupDefault.get() + 1
ntfBadgeCountGroupDefault.set(badgeCount)
@@ -272,7 +262,7 @@ class NotificationService: UNNotificationServiceExtension {
private func deliverBestAttemptNtf(urgent: Bool = false) {
logger.debug("NotificationService.deliverBestAttemptNtf")
// stop processing other messages
shouldProcessNtf = false
processReceivedNtf = nil
let suspend: Bool
if let t = threadId {
@@ -406,7 +396,7 @@ func startChat() -> DBMigrationResult? {
startLock.wait()
defer { startLock.signal() }
if hasChatCtrl() {
return switch NSEChatState.shared.value {
case .created: doStartChat()
@@ -425,7 +415,8 @@ func startChat() -> DBMigrationResult? {
func doStartChat() -> DBMigrationResult? {
logger.debug("NotificationService: doStartChat")
haskell_init_nse()
haskell_init(1, nil, getAppDebugProfilePrefixPath().path)
// haskell_init(1, nil, nil)
let (_, dbStatus) = chatMigrateInit(confirmMigrations: defaultMigrationConfirmation(), backgroundMode: true)
logger.debug("NotificationService: doStartChat \(String(describing: dbStatus))")
if dbStatus != .ok {
+24 -64
View File
@@ -18,6 +18,11 @@
18415FEFE153C5920BFB7828 /* GroupWelcomeView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1841516F0CE5992B0EDFB377 /* GroupWelcomeView.swift */; };
3CDBCF4227FAE51000354CDD /* ComposeLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */; };
3CDBCF4827FF621E00354CDD /* CILinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3CDBCF4727FF621E00354CDD /* CILinkView.swift */; };
411D3A7C2BB9601D003D9A22 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 411D3A772BB9601D003D9A22 /* libgmp.a */; };
411D3A7D2BB9601D003D9A22 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 411D3A782BB9601D003D9A22 /* libffi.a */; };
411D3A7E2BB9601D003D9A22 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 411D3A792BB9601D003D9A22 /* libgmpxx.a */; };
411D3A7F2BB9601D003D9A22 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 411D3A7A2BB9601D003D9A22 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a */; };
411D3A802BB9601D003D9A22 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 411D3A7B2BB9601D003D9A22 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a */; };
5C00164428A26FBC0094D739 /* ContextMenu.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C00164328A26FBC0094D739 /* ContextMenu.swift */; };
5C00168128C4FE760094D739 /* KeyChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C00168028C4FE760094D739 /* KeyChain.swift */; };
5C029EA82837DBB3004A9677 /* CICallItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C029EA72837DBB3004A9677 /* CICallItemView.swift */; };
@@ -139,11 +144,6 @@
5CEACCED27DEA495000BD591 /* MsgContentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEACCEC27DEA495000BD591 /* MsgContentView.swift */; };
5CEBD7462A5C0A8F00665FE2 /* KeyboardPadding.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */; };
5CEBD7482A5F115D00665FE2 /* SetDeliveryReceiptsView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */; };
5CF898622BB984E400EE33B6 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF8985D2BB984E400EE33B6 /* libgmpxx.a */; };
5CF898632BB984E400EE33B6 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF8985E2BB984E400EE33B6 /* libffi.a */; };
5CF898642BB984E400EE33B6 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF8985F2BB984E400EE33B6 /* libgmp.a */; };
5CF898652BB984E400EE33B6 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF898602BB984E400EE33B6 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a */; };
5CF898662BB984E400EE33B6 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CF898612BB984E400EE33B6 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a */; };
5CF937202B24DE8C00E1D781 /* SharedFileSubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF9371F2B24DE8C00E1D781 /* SharedFileSubscriber.swift */; };
5CF937232B2503D000E1D781 /* NSESubscriber.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CF937212B25034A00E1D781 /* NSESubscriber.swift */; };
5CFA59C42860BC6200863A68 /* MigrateToAppGroupView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */; };
@@ -163,11 +163,6 @@
64466DC829FC2B3B00E3D48D /* CreateSimpleXAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64466DC729FC2B3B00E3D48D /* CreateSimpleXAddress.swift */; };
64466DCC29FFE3E800E3D48D /* MailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64466DCB29FFE3E800E3D48D /* MailView.swift */; };
6448BBB628FA9D56000D2AB9 /* GroupLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6448BBB528FA9D56000D2AB9 /* GroupLinkView.swift */; };
6449333A2AF8E51000AC506E /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 644933352AF8E51000AC506E /* libgmpxx.a */; };
6449333B2AF8E51000AC506E /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 644933362AF8E51000AC506E /* libgmp.a */; };
6449333C2AF8E51000AC506E /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 644933372AF8E51000AC506E /* libffi.a */; };
6449333D2AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 644933382AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8-ghc9.6.3.a */; };
6449333E2AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 644933392AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8.a */; };
644EFFDE292BCD9D00525D5B /* ComposeVoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 644EFFDD292BCD9D00525D5B /* ComposeVoiceView.swift */; };
644EFFE0292CFD7F00525D5B /* CIVoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 644EFFDF292CFD7F00525D5B /* CIVoiceView.swift */; };
644EFFE2292D089800525D5B /* FramedCIVoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 644EFFE1292D089800525D5B /* FramedCIVoiceView.swift */; };
@@ -268,6 +263,11 @@
18415FD2E36F13F596A45BB4 /* CIVideoView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CIVideoView.swift; sourceTree = "<group>"; };
3CDBCF4127FAE51000354CDD /* ComposeLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeLinkView.swift; sourceTree = "<group>"; };
3CDBCF4727FF621E00354CDD /* CILinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CILinkView.swift; sourceTree = "<group>"; };
411D3A772BB9601D003D9A22 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgmp.a; path = ios/libgmp.a; sourceTree = "<group>"; };
411D3A782BB9601D003D9A22 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libffi.a; path = ios/libffi.a; sourceTree = "<group>"; };
411D3A792BB9601D003D9A22 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = libgmpxx.a; path = ios/libgmpxx.a; sourceTree = "<group>"; };
411D3A7A2BB9601D003D9A22 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a"; path = "ios/libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a"; sourceTree = "<group>"; };
411D3A7B2BB9601D003D9A22 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; name = "libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a"; path = "ios/libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a"; sourceTree = "<group>"; };
5C00164328A26FBC0094D739 /* ContextMenu.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContextMenu.swift; sourceTree = "<group>"; };
5C00168028C4FE760094D739 /* KeyChain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyChain.swift; sourceTree = "<group>"; };
5C029EA72837DBB3004A9677 /* CICallItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CICallItemView.swift; sourceTree = "<group>"; };
@@ -436,11 +436,6 @@
5CEACCEC27DEA495000BD591 /* MsgContentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MsgContentView.swift; sourceTree = "<group>"; };
5CEBD7452A5C0A8F00665FE2 /* KeyboardPadding.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyboardPadding.swift; sourceTree = "<group>"; };
5CEBD7472A5F115D00665FE2 /* SetDeliveryReceiptsView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SetDeliveryReceiptsView.swift; sourceTree = "<group>"; };
5CF8985D2BB984E400EE33B6 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5CF8985E2BB984E400EE33B6 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5CF8985F2BB984E400EE33B6 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5CF898602BB984E400EE33B6 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a"; sourceTree = "<group>"; };
5CF898612BB984E400EE33B6 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a"; sourceTree = "<group>"; };
5CF9371F2B24DE8C00E1D781 /* SharedFileSubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SharedFileSubscriber.swift; sourceTree = "<group>"; };
5CF937212B25034A00E1D781 /* NSESubscriber.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NSESubscriber.swift; sourceTree = "<group>"; };
5CFA59C32860BC6200863A68 /* MigrateToAppGroupView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrateToAppGroupView.swift; sourceTree = "<group>"; };
@@ -459,11 +454,6 @@
64466DC729FC2B3B00E3D48D /* CreateSimpleXAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSimpleXAddress.swift; sourceTree = "<group>"; };
64466DCB29FFE3E800E3D48D /* MailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailView.swift; sourceTree = "<group>"; };
6448BBB528FA9D56000D2AB9 /* GroupLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupLinkView.swift; sourceTree = "<group>"; };
644933352AF8E51000AC506E /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
644933362AF8E51000AC506E /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
644933372AF8E51000AC506E /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
644933382AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8-ghc9.6.3.a"; sourceTree = "<group>"; };
644933392AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8.a"; sourceTree = "<group>"; };
644EFFDD292BCD9D00525D5B /* ComposeVoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeVoiceView.swift; sourceTree = "<group>"; };
644EFFDF292CFD7F00525D5B /* CIVoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIVoiceView.swift; sourceTree = "<group>"; };
644EFFE1292D089800525D5B /* FramedCIVoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FramedCIVoiceView.swift; sourceTree = "<group>"; };
@@ -531,13 +521,13 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5CF898652BB984E400EE33B6 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a in Frameworks */,
5CF898622BB984E400EE33B6 /* libgmpxx.a in Frameworks */,
5CF898642BB984E400EE33B6 /* libgmp.a in Frameworks */,
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
411D3A7E2BB9601D003D9A22 /* libgmpxx.a in Frameworks */,
411D3A7C2BB9601D003D9A22 /* libgmp.a in Frameworks */,
411D3A802BB9601D003D9A22 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a in Frameworks */,
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
5CF898632BB984E400EE33B6 /* libffi.a in Frameworks */,
5CF898662BB984E400EE33B6 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a in Frameworks */,
411D3A7F2BB9601D003D9A22 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a in Frameworks */,
411D3A7D2BB9601D003D9A22 /* libffi.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -600,11 +590,11 @@
5C764E5C279C70B7000C6508 /* Libraries */ = {
isa = PBXGroup;
children = (
5CF8985E2BB984E400EE33B6 /* libffi.a */,
5CF8985F2BB984E400EE33B6 /* libgmp.a */,
5CF8985D2BB984E400EE33B6 /* libgmpxx.a */,
5CF898612BB984E400EE33B6 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a */,
5CF898602BB984E400EE33B6 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a */,
411D3A782BB9601D003D9A22 /* libffi.a */,
411D3A772BB9601D003D9A22 /* libgmp.a */,
411D3A792BB9601D003D9A22 /* libgmpxx.a */,
411D3A7A2BB9601D003D9A22 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv-ghc9.6.3.a */,
411D3A7B2BB9601D003D9A22 /* libHSsimplex-chat-5.6.0.4-FOF2McwHkk1EIlP5UNozOv.a */,
);
path = Libraries;
sourceTree = "<group>";
@@ -1451,7 +1441,6 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
@@ -1513,7 +1502,6 @@
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
@@ -1542,16 +1530,12 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 204;
DEAD_CODE_STRIPPING = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
GCC_OPTIMIZATION_LEVEL = s;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "SimpleX--iOS--Info.plist";
INFOPLIST_KEY_NSCameraUsageDescription = "SimpleX needs camera access to scan QR codes to connect to other users and for video calls.";
@@ -1570,13 +1554,11 @@
"$(inherited)",
"@executable_path/Frameworks",
);
LLVM_LTO = YES_THIN;
MARKETING_VERSION = 5.6;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
@@ -1591,16 +1573,13 @@
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 204;
DEAD_CODE_STRIPPING = YES;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
ENABLE_PREVIEWS = NO;
ENABLE_PREVIEWS = YES;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "SimpleX--iOS--Info.plist";
INFOPLIST_KEY_NSCameraUsageDescription = "SimpleX needs camera access to scan QR codes to connect to other users and for video calls.";
@@ -1619,7 +1598,6 @@
"$(inherited)",
"@executable_path/Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 5.6;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
@@ -1676,15 +1654,12 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 204;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "SimpleX NSE/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = "SimpleX NSE";
@@ -1695,7 +1670,6 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 5.6;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1703,7 +1677,6 @@
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Osize";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
};
@@ -1713,15 +1686,13 @@
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ENABLE_MODULES = YES;
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 204;
DEBUG_INFORMATION_FORMAT = dwarf;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_FILE = "SimpleX NSE/Info.plist";
INFOPLIST_KEY_CFBundleDisplayName = "SimpleX NSE";
@@ -1732,7 +1703,6 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
LLVM_LTO = YES;
MARKETING_VERSION = 5.6;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
@@ -1740,7 +1710,6 @@
SDKROOT = iphoneos;
SKIP_INSTALL = YES;
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_OPTIMIZATION_LEVEL = "-Osize";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = 1;
VALIDATE_PRODUCT = YES;
@@ -1752,8 +1721,6 @@
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 204;
DEFINES_MODULE = YES;
@@ -1762,7 +1729,6 @@
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = NO;
GCC_OPTIMIZATION_LEVEL = s;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 SimpleX Chat. All rights reserved.";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@@ -1780,7 +1746,6 @@
"$(inherited)",
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
MARKETING_VERSION = 5.6;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
@@ -1790,7 +1755,6 @@
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_INCLUDE_PATHS = "";
SWIFT_OBJC_BRIDGING_HEADER = ./SimpleXChat/SimpleX.h;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VERSIONING_SYSTEM = "apple-generic";
@@ -1803,17 +1767,15 @@
buildSettings = {
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CLANG_TIDY_BUGPRONE_REDUNDANT_BRANCH_CONDITION = YES;
CLANG_TIDY_MISC_REDUNDANT_EXPRESSION = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 204;
DEBUG_INFORMATION_FORMAT = dwarf;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
ENABLE_BITCODE = NO;
ENABLE_CODE_COVERAGE = NO;
GENERATE_INFOPLIST_FILE = YES;
INFOPLIST_KEY_NSHumanReadableCopyright = "Copyright © 2022 SimpleX Chat. All rights reserved.";
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
@@ -1831,7 +1793,6 @@
"$(inherited)",
"$(PROJECT_DIR)/Libraries/sim",
);
LLVM_LTO = YES;
MARKETING_VERSION = 5.6;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
@@ -1841,7 +1802,6 @@
SWIFT_EMIT_LOC_STRINGS = YES;
SWIFT_INCLUDE_PATHS = "";
SWIFT_OBJC_BRIDGING_HEADER = ./SimpleXChat/SimpleX.h;
SWIFT_OPTIMIZATION_LEVEL = "-O";
SWIFT_VERSION = 5.0;
TARGETED_DEVICE_FAMILY = "1,2";
VALIDATE_PRODUCT = YES;
-8
View File
@@ -3209,14 +3209,6 @@ public enum MsgContent: Equatable {
}
}
public var isImageOrVideo: Bool {
switch self {
case .image: true
case .video: true
default: false
}
}
var cmdString: String {
"json \(encodeJSON(self))"
}
+16
View File
@@ -52,6 +52,10 @@ func getAppDirectory() -> URL {
let DB_FILE_PREFIX = "simplex_v1"
let DEBUG_PROFILE_PREFIX = "simplex_debug"
let DEBUG_PROFILE_EXTENSION = ".hp"
func getLegacyDatabasePath() -> URL {
getDocumentsDirectory().appendingPathComponent("mobile_v1", isDirectory: false)
}
@@ -62,6 +66,18 @@ public func getAppDatabasePath() -> URL {
: getLegacyDatabasePath()
}
public func getAppDebugProfilePrefixPath() -> URL {
getAppDirectory().appendingPathComponent(DEBUG_PROFILE_PREFIX, isDirectory: false)
}
public func getAppDebugProfilePath() -> URL {
getAppDirectory().appendingPathComponent(DEBUG_PROFILE_PREFIX + DEBUG_PROFILE_EXTENSION, isDirectory: false)
}
public func getAppEventLogPath() -> URL {
getAppDirectory().appendingPathComponent("simplex.eventlog", isDirectory: false)
}
func fileModificationDate(_ path: String) -> Date? {
do {
let attr = try FileManager.default.attributesOfItem(atPath: path)
+44 -10
View File
@@ -7,19 +7,53 @@
//
#include "hs_init.h"
#include <string.h>
extern void hs_init_with_rtsopts(int * argc, char **argv[]);
void haskell_init(void) {
int argc = 5;
char *argv[] = {
"simplex",
"+RTS", // requires `hs_init_with_rtsopts`
"-A64m", // chunk size for new allocations
"-H64m", // initial heap size
"-xn", // non-moving GC
0
};
void haskell_init(int nse, const char *eventlog, const char *heap_profile) {
// setup static arena for bump allocation and passing to RTS
char *argv[32] = {0,};
int argc = 0; // number of arguments used so far, always stands at the first NULL in argv
// common args
if (nse) {
argv[argc++] = "simplex-nse"; // fake program name
} else {
argv[argc++] = "simplex";
}
argv[argc++] = "+RTS"; // start adding RTS options
if (nse) {
argv[argc++] = "-S"; // spam stdout with GC stats
argv[argc++] = "-A1m"; // chunk size for new allocations (less frequent GC)
argv[argc++] = "-H2m"; // larger heap size on start (faster boot)
argv[argc++] = "-M12m"; // hard limit on heap
argv[argc++] = "-F0.5"; // heap growth triggering GC
argv[argc++] = "-Fd1"; // memory return
} else {
argv[argc++] = "-T"; // make GC counters available from inside the program
argv[argc++] = "-A64m"; // chunk size for new allocations (less frequent GC)
argv[argc++] = "-H64m"; // larger heap size on start (faster boot)
}
// argv[argc++] = "-M8G"; // keep memory usage under 8G, collecting more aggressively when approaching it (and crashing sooner rather than taking down the whole system)
if (eventlog) {
static char ol[1024] = "-ol";
(void)strncpy(&ol[3], eventlog, sizeof(ol) - 3);
argv[argc++] = ol;
argv[argc++] = "-l-agu"; // collect GC and user events
}
if (heap_profile) {
static char po[1024] = "-po";
(void)strncpy(&po[3], heap_profile, sizeof(po) - 3);
argv[argc++] = po; // adds ".hp" extension
argv[argc++] = "-hT"; // emit heap profile by closure type
}
if (nse) {
argv[argc++] = "-c"; // compacting garbage collector
} else {
int non_moving_gc = !heap_profile; // not compatible with heap profile
if (non_moving_gc) argv[argc++] = "-xn";
}
// wrap args as expected by RTS
char **pargv = argv;
hs_init_with_rtsopts(&argc, &pargv);
}
+1 -1
View File
@@ -9,7 +9,7 @@
#ifndef hs_init_h
#define hs_init_h
void haskell_init(void);
void haskell_init(int nse, const char *eventlog, const char *heap_profile);
void haskell_init_nse(void);
@@ -71,7 +71,7 @@ if(NOT APPLE)
else()
# Without direct linking it can't find hs_init in linking step
add_library( rts SHARED IMPORTED )
FILE(GLOB RTSLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/deps/libHSrts*_thr-*.${OS_LIB_EXT})
FILE(GLOB RTSLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libHSrts*_thr-*.${OS_LIB_EXT})
set_target_properties( rts PROPERTIES IMPORTED_LOCATION ${RTSLIB})
target_link_libraries(app-lib rts simplex)
@@ -1,44 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
width="120"
height="120"
viewBox="121 0 40 40"
fill="none"
version="1.1"
id="svg3"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="m 126.52238,11.425398 5.80302,5.716401 5.88962,-5.889626 2.8582,2.858201 L 135.1836,20 l 5.7164,5.716402 -2.94482,2.8582 -5.7164,-5.629789 -5.88962,5.803014 -2.8582,-2.858201 5.88962,-5.803014 -5.803,-5.716402 z"
fill="#030749"
id="path1"
style="stroke-width:0.866122" />
<path
fill-rule="evenodd"
clip-rule="evenodd"
d="m 137.86858,28.661214 2.94481,-2.944812 v 0 l 5.88963,-5.803014 -5.80302,-5.62979 v 0 l -2.8582,-2.8582 -5.7164,-5.7164023 2.94481,-2.9448129 5.7164,5.7164017 5.88963,-5.8030138 2.8582,2.8582008 -5.88962,5.8030145 5.7164,5.716401 5.88962,-5.803014 2.8582,2.858201 -5.88962,5.803014 5.803,5.716402 -2.9448,2.858201 -5.7164,-5.716402 -5.88963,5.803013 5.7164,5.716402 -2.8582,2.944813 -5.80301,-5.716402 -5.80302,5.803015 -2.8582,-2.858201 z"
fill="url(#paint0_linear_40_164)"
id="path2"
style="fill:url(#paint0_linear_40_164);stroke-width:0.866122" />
<defs
id="defs3">
<linearGradient
x1="135.948"
y1="-0.81632602"
x2="132.09599"
y2="36.985699"
gradientUnits="userSpaceOnUse"
id="paint0_linear_40_164"
gradientTransform="matrix(0.86612147,0,0,0.86612147,18.863485,2.6775707)">
<stop
stop-color="#01f1ff"
id="stop2" />
<stop
offset="1"
stop-color="#0197ff"
id="stop3" />
</linearGradient>
</defs>
</svg>

Before

Width:  |  Height:  |  Size: 1.7 KiB

@@ -21,7 +21,6 @@ import chat.simplex.common.ui.theme.SimpleXTheme
import chat.simplex.common.views.TerminalView
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.*
import java.awt.event.WindowEvent
@@ -104,7 +103,7 @@ private fun ApplicationScope.AppWindow(closedByError: MutableState<Boolean>) {
simplexWindowState.windowState = windowState
// Reload all strings in all @Composable's after language change at runtime
if (remember { ChatController.appPrefs.appLanguage.state }.value != "") {
Window(state = windowState, icon = painterResource(MR.images.ic_simplex), onCloseRequest = { closedByError.value = false; exitApplication() }, onKeyEvent = {
Window(state = windowState, onCloseRequest = { closedByError.value = false; exitApplication() }, onKeyEvent = {
if (it.key == Key.Escape && it.type == KeyEventType.KeyUp) {
simplexWindowState.backstack.lastOrNull()?.invoke() != null
} else {
@@ -7,8 +7,6 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalDensity
import androidx.compose.ui.unit.Dp
import chat.simplex.common.platform.*
import chat.simplex.common.simplexWindowState
import java.awt.Window
@Composable
actual fun PlayerView(player: VideoPlayer, width: Dp, onClick: () -> Unit, onLongClick: () -> Unit, stop: () -> Unit) {
@@ -25,15 +23,14 @@ actual fun PlayerView(player: VideoPlayer, width: Dp, onClick: () -> Unit, onLon
}
}
/*
* This function doesn't take into account multi-window environment. In case more windows will be used, modify the code
* */
@Composable
actual fun LocalWindowWidth(): Dp = with(LocalDensity.current) {
val windows = java.awt.Window.getWindows()
if (windows.size == 1) {
(windows.getOrNull(0)?.width ?: 0).toDp()
} else {
simplexWindowState.windowState.size.width
actual fun LocalWindowWidth(): Dp {
return with(LocalDensity.current) { (java.awt.Window.getWindows().find { it.isActive }?.width ?: 0).toDp() }
/*val density = LocalDensity.current
var width by remember { mutableStateOf(with(density) { (java.awt.Window.getWindows().find { it.isActive }?.width ?: 0).toDp() }) }
SideEffect {
if (width != with(density) { (java.awt.Window.getWindows().find { it.isActive }?.width ?: 0).toDp() })
width = with(density) { (java.awt.Window.getWindows().find { it.isActive }?.width ?: 0).toDp() }
}
return width.also { println("LALAL $it") }*/
}
+7 -1
View File
@@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package
type: git
location: https://github.com/simplex-chat/simplexmq.git
tag: 1e6268cc1dbba69639425f7d5a6c9a07995e0bb2
tag: 8b94264623eb8f32793a3b4129cb12770f54ef3a
source-repository-package
type: git
@@ -34,6 +34,12 @@ source-repository-package
location: https://github.com/simplex-chat/aeson.git
tag: aab7b5a14d6c5ea64c64dcaee418de1bb00dcc2b
-- old bs/text compat for 8.10
source-repository-package
type: git
location: https://github.com/simplex-chat/base64.git
tag: 2d77b6dbcaffc00570a70be8694049f3710e7c94
source-repository-package
type: git
location: https://github.com/simplex-chat/haskell-terminal.git
-72
View File
@@ -1,72 +0,0 @@
# Large public grups / channels
## Background
SimpleX Chat users participate in public groups that were created for small, fully connected p2p groups - working groups, teams, etc. The ability to join the groups via the links was added as an afterthought, without forward looking design, simply to accomodate the interest from the users to use SimpleX platform for public groups and communities. Overall, it's correct to say that the emergence of public groups was unexpected in the context of private messaging, and it shows that protecting participants and publishers identity, and having per-group identity is important for many people.
## Problems of the current p2p design
### It doesn't scale to large size
Current design assumes that each peer is connected to each peer and sends messages to all. It creates non-trivial cost of establishing the connections as the group grows, some abandoned connections when some members remain in "connecting" state and also linearly growing traffic to send each message.
Historically, there were p2p designs when peers connected not to all but some members, but they were mostly used by desktop clients with more persistent network connections, did not provide any asynchronous delivery and were trading lower traffic for latency and availability. Such designs were viable for file sharing across desktop devices, but it probably would not work well for dynamic real-time communities with active participation from a small share of members and the design of other members to observe the conversation as it happens.
### It doesn't account for participation asymmetry
Most members of large public groups do not send messages, so connecting them to all other members directly appears unnecessary and costly, and it also requires tracking when members became inactive to stop sending messages to them.
## Objectives for the new design
### Transcript integrity
This issue is covered in detail in [Group integrity](./2023-10-20-group-integrity.md).
### Asynchronous delivery to group
Asynchronous delivery is important to protect participants privacy from traffic observation. In addition to that, sending scheduled posts is quite often a convenient feature to schedule multiple updates for a longer period of time - for example, schedule daily updates for a week, doing it once a week.
### Ability to conceal members list
This is a rather common request for the current groups, and while it could be possible of course to hide it on the client level, this still makes data available via the database, and puts less technical users in unfair position, while not protecting users privacy from technically competent members.
### Support pre-moderation
As the group size grows, so does the activity of the bad actors. Some groups will benefit from switching all, some, most, or new members to pre-moderation - when each post needs to be approved by admin before it becomes visible to all members. It would slow down the conversations, but it would allow a better content quality and owners' control of the content.
## Channels based on super-peers
The proposal is to model the new UX design from Telegram channels, with optional subchannels, and granular participation rights for the members / followers.
Another consideration is to create democratically governed communities when creators don't own the community but only appoint the initial administrators, but as the community grows it can elect the new admins or moderators from the existing members, where voting power is somehow determined by the community score (which is necessary to compensate for anonymous participants who could subvert the vote if plain vote count was made). This is probably out of scope for the initial implementation, but this idea is very appealing and it doesn't exist in any other decentralised platforms.
Technologically, the channel or group would determine which super-peers would host the group or channel, with group content being a merkle tree with ability to remove some content creating holes - which seems to be very important quality, both to remove undesirable content and to protect participants privacy.
Super-peer would manage this merkle-tree state based on the messages from owners, admins and members, with the ability to make some destructive actions confirmed by more than one command. E.g., group/channel deletion may require at least 2 or 3 votes (respectively, for 3 and 5 owners), thus protecting both from accidental deletions and from attacks via owner - one of the owners being compromised won't result in group deletion if 2 votes are required. As the group size grows, owners can also modify rules (which in itself can also require m of n votes).
## Joining group
The current model when the link to join the group is, effectively, an address of one of the admins, is not censorship-resistant, reliable or convenient - the admin can be offline, be removed, etc. So we want to somehow include addresses of multiple super-peers to join the group. Without identity-layer, the addresses are quite large already, and including multiple addresses in one link, while possible, would make the qr code very hard to scan. Practically, without creating identity layer, we can use up to 2-3 super-peer addresses for the group, and increase it later. 2 addresses is likely to be satisfactory, as one of them could be super-peer hosted by SimpleX Chat, and another - by group owners.
The client then will be connecting to all super-peers in the address. Once connected, these super-peers could send the addresses of the additional super-peers, but this is probably unnecessary for the initial release.
## MVP
The challenge is to decide what should be in scope for the initial release, to make it a valuable upgrade and a viable starting point, without overloading it with the functions that can be added later.
MVP scope:
- Core functioning of the group - creation/deletion/choosing and changing super-peers. While a large scope, it appears essential.
- Message delivery via super-peers.
- Super-peer protocol extension. Most likely super-peer would receive ordinary chat messages, but some operations should be added and require additional protocol messages - adding/removing super-peers to groups.
- Protocol extensions for owner actions with approvals - we already had several accidental deletions or lost owner accounts. Possibly, it is out of MVP scope.
- Search and history navigation. Current decision to send 100 messages both creates unnecessary traffic spikes, and also doesn't provide access to older history and search functions. But, possibly, it should also be in follow up improvements, and only should be included as the initial protocol design.
- New format of the group address to include more than one super-peer.
- Granular permissions and management model. While the user interface can evolve, the protocol and the scenarios, and also rules models seems better to be added from the beginning.
Follow-up / improvements:
- More scalable client - we already observe scalability issues with directory service, so replacing SQLite with Postgres, if the group participation starts growing seems very important.
Out of scope:
- additional super-peers.
- smart-contacts. While very tempting to generalise permissions and management model via smart contracts, that would radically increase complexity and delivery time.
Generated
+227 -468
View File
@@ -16,21 +16,6 @@
"type": "github"
}
},
"blank": {
"locked": {
"lastModified": 1625557891,
"narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=",
"owner": "divnix",
"repo": "blank",
"rev": "5a5d2684073d9f563072ed07c871d577a6c614a8",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "blank",
"type": "github"
}
},
"cabal-32": {
"flake": false,
"locked": {
@@ -98,64 +83,6 @@
"type": "github"
}
},
"devshell": {
"inputs": {
"flake-utils": [
"haskellNix",
"tullia",
"std",
"flake-utils"
],
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1663445644,
"narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=",
"owner": "numtide",
"repo": "devshell",
"rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"dmerge": {
"inputs": {
"nixlib": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
],
"yants": [
"haskellNix",
"tullia",
"std",
"yants"
]
},
"locked": {
"lastModified": 1659548052,
"narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=",
"owner": "divnix",
"repo": "data-merge",
"rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "data-merge",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
@@ -173,74 +100,34 @@
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"lastModified": 1698579227,
"narHash": "sha256-KVWjFZky+gRuWennKsbo6cWyo7c/z/VgCte5pR9pEKg=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f76e870d64779109e41370848074ac4eaa1606ec",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1676283394,
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
"type": "github"
"inputs": {
"systems": "systems"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"locked": {
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_4": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
@@ -266,33 +153,51 @@
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"nixpkgs": "nixpkgs_2",
"utils": "utils"
},
"ghc98X": {
"flake": false,
"locked": {
"lastModified": 1655245309,
"narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=",
"owner": "tweag",
"repo": "gomod2nix",
"rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58",
"type": "github"
"lastModified": 1696643148,
"narHash": "sha256-E02DfgISH7EvvNAu0BHiPvl1E5FGMDi0pWdNZtIBC9I=",
"ref": "ghc-9.8",
"rev": "443e870d977b1ab6fc05f47a9a17bc49296adbd6",
"revCount": 61642,
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
},
"original": {
"owner": "tweag",
"repo": "gomod2nix",
"type": "github"
"ref": "ghc-9.8",
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
}
},
"ghc99": {
"flake": false,
"locked": {
"lastModified": 1697054644,
"narHash": "sha256-kKarOuXUaAH3QWv7ASx+gGFMHaHKe0pK5Zu37ky2AL4=",
"ref": "refs/heads/master",
"rev": "f383a242c76f90bcca8a4d7ee001dcb49c172a9a",
"revCount": 62040,
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
},
"original": {
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
}
},
"hackage": {
"flake": false,
"locked": {
"lastModified": 1702340598,
"narHash": "sha256-CC0HI+6iKPtH+8r/ZfcpW5v/OYvL7zMwpr0xfkXV1zU=",
"lastModified": 1702513363,
"narHash": "sha256-kloro9uEe8aYhPMoMjVNq2rfrXNgMOZhOPwVH5DH2K0=",
"owner": "input-output-hk",
"repo": "hackage.nix",
"rev": "24617c569995e38bf3b83b48eec6628a50fdb4fb",
"rev": "a9d931d0398da67846fa257922a924829233cb91",
"type": "github"
},
"original": {
@@ -309,33 +214,40 @@
"cabal-36": "cabal-36",
"cardano-shell": "cardano-shell",
"flake-compat": "flake-compat",
"flake-utils": "flake-utils_2",
"ghc-8.6.5-iohk": "ghc-8.6.5-iohk",
"ghc98X": "ghc98X",
"ghc99": "ghc99",
"hackage": [
"hackage"
],
"hls-1.10": "hls-1.10",
"hls-2.0": "hls-2.0",
"hls-2.2": "hls-2.2",
"hls-2.3": "hls-2.3",
"hls-2.4": "hls-2.4",
"hpc-coveralls": "hpc-coveralls",
"hydra": "hydra",
"iserv-proxy": "iserv-proxy",
"nixpkgs": [
"nixpkgs"
"haskellNix",
"nixpkgs-unstable"
],
"nixpkgs-2003": "nixpkgs-2003",
"nixpkgs-2105": "nixpkgs-2105",
"nixpkgs-2111": "nixpkgs-2111",
"nixpkgs-2205": "nixpkgs-2205",
"nixpkgs-2211": "nixpkgs-2211",
"nixpkgs-2305": "nixpkgs-2305",
"nixpkgs-unstable": "nixpkgs-unstable",
"old-ghc-nix": "old-ghc-nix",
"stackage": "stackage",
"tullia": "tullia"
"stackage": "stackage"
},
"locked": {
"lastModified": 1677975916,
"narHash": "sha256-dbe8lEEPyfzjdRwpePClv7J9p9lQg7BwbBqAMCw4RLw=",
"lastModified": 1701163700,
"narHash": "sha256-sOrewUS3LnzV09nGr7+3R6Q6zsgU4smJc61QsHq+4DE=",
"owner": "input-output-hk",
"repo": "haskell.nix",
"rev": "ab5efd87ce3fd8ade38a01d97693d29a4f1ae7e4",
"rev": "2808bfe3e62e9eb4ee8974cd623a00e1611f302b",
"type": "github"
},
"original": {
@@ -345,6 +257,91 @@
"type": "github"
}
},
"hls-1.10": {
"flake": false,
"locked": {
"lastModified": 1680000865,
"narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "1.10.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.0": {
"flake": false,
"locked": {
"lastModified": 1687698105,
"narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "783905f211ac63edf982dd1889c671653327e441",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.0.0.1",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.2": {
"flake": false,
"locked": {
"lastModified": 1693064058,
"narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.2.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.3": {
"flake": false,
"locked": {
"lastModified": 1695910642,
"narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.3.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.4": {
"flake": false,
"locked": {
"lastModified": 1696939266,
"narHash": "sha256-VOMf5+kyOeOmfXTHlv4LNFJuDGa7G3pDnOxtzYR40IU=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "362fdd1293efb4b82410b676ab1273479f6d17ee",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.4.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hpc-coveralls": {
"flake": false,
"locked": {
@@ -384,37 +381,14 @@
"type": "indirect"
}
},
"incl": {
"inputs": {
"nixlib": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1669263024,
"narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=",
"owner": "divnix",
"repo": "incl",
"rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "incl",
"type": "github"
}
},
"iserv-proxy": {
"flake": false,
"locked": {
"lastModified": 1670983692,
"narHash": "sha256-avLo34JnI9HNyOuauK5R69usJm+GfW3MlyGlYxZhTgY=",
"lastModified": 1691634696,
"narHash": "sha256-MZH2NznKC/gbgBu8NgIibtSUZeJ00HTLJ0PlWKCBHb0=",
"ref": "hkm/remote-iserv",
"rev": "50d0abb3317ac439a4e7495b185a64af9b7b9300",
"revCount": 10,
"rev": "43a979272d9addc29fbffc2e8542c5d96e993d73",
"revCount": 14,
"type": "git",
"url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git"
},
@@ -440,32 +414,22 @@
"type": "github"
}
},
"n2c": {
"mac2ios": {
"inputs": {
"flake-utils": [
"haskellNix",
"tullia",
"std",
"flake-utils"
],
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1665039323,
"narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=",
"owner": "nlewo",
"repo": "nix2container",
"rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a",
"lastModified": 1699767871,
"narHash": "sha256-kxeCUfwC/Vgh2FvVMlBUq0eVx1JvfHyN+5MPKUik9mE=",
"owner": "zw3rk",
"repo": "mobile-core-tools",
"rev": "4dcb77d5ea896d749381806dfab5358851b08951",
"type": "github"
},
"original": {
"owner": "nlewo",
"repo": "nix2container",
"owner": "zw3rk",
"repo": "mobile-core-tools",
"type": "github"
}
},
@@ -490,95 +454,6 @@
"type": "github"
}
},
"nix-nomad": {
"inputs": {
"flake-compat": "flake-compat_2",
"flake-utils": [
"haskellNix",
"tullia",
"nix2container",
"flake-utils"
],
"gomod2nix": "gomod2nix",
"nixpkgs": [
"haskellNix",
"tullia",
"nixpkgs"
],
"nixpkgs-lib": [
"haskellNix",
"tullia",
"nixpkgs"
]
},
"locked": {
"lastModified": 1658277770,
"narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=",
"owner": "tristanpemble",
"repo": "nix-nomad",
"rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70",
"type": "github"
},
"original": {
"owner": "tristanpemble",
"repo": "nix-nomad",
"type": "github"
}
},
"nix2container": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1658567952,
"narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=",
"owner": "nlewo",
"repo": "nix2container",
"rev": "60bb43d405991c1378baf15a40b5811a53e32ffa",
"type": "github"
},
"original": {
"owner": "nlewo",
"repo": "nix2container",
"type": "github"
}
},
"nixago": {
"inputs": {
"flake-utils": [
"haskellNix",
"tullia",
"std",
"flake-utils"
],
"nixago-exts": [
"haskellNix",
"tullia",
"std",
"blank"
],
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1661824785,
"narHash": "sha256-/PnwdWoO/JugJZHtDUioQp3uRiWeXHUdgvoyNbXesz8=",
"owner": "nix-community",
"repo": "nixago",
"rev": "8c1f9e5f1578d4b2ea989f618588d62a335083c3",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixago",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1657693803,
@@ -645,11 +520,11 @@
},
"nixpkgs-2205": {
"locked": {
"lastModified": 1672580127,
"narHash": "sha256-3lW3xZslREhJogoOkjeZtlBtvFMyxHku7I/9IVehhT8=",
"lastModified": 1685573264,
"narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0874168639713f547c05947c76124f78441ea46c",
"rev": "380be19fbd2d9079f677978361792cb25e8a3635",
"type": "github"
},
"original": {
@@ -661,11 +536,11 @@
},
"nixpkgs-2211": {
"locked": {
"lastModified": 1675730325,
"narHash": "sha256-uNvD7fzO5hNlltNQUAFBPlcEjNG5Gkbhl/ROiX+GZU4=",
"lastModified": 1688392541,
"narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b7ce17b1ebf600a72178f6302c77b6382d09323f",
"rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b",
"type": "github"
},
"original": {
@@ -675,6 +550,40 @@
"type": "github"
}
},
"nixpkgs-2305": {
"locked": {
"lastModified": 1695416179,
"narHash": "sha256-610o1+pwbSu+QuF3GE0NU5xQdTHM3t9wyYhB9l94Cd8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "715d72e967ec1dd5ecc71290ee072bcaf5181ed6",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-23.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1696019113,
"narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
@@ -693,11 +602,11 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1675758091,
"narHash": "sha256-7gFSQbSVAFUHtGCNHPF7mPc5CcqDk9M2+inlVPZSneg=",
"lastModified": 1695318763,
"narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "747927516efcb5e31ba03b7ff32f61f6d47e7d87",
"rev": "e12483116b3b51a185a33a272bf351e357ba9a99",
"type": "github"
},
"original": {
@@ -709,82 +618,20 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1653581809,
"narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=",
"lastModified": 1698434055,
"narHash": "sha256-Phxi5mUKSoL7A0IYUiYtkI9e8NcGaaV5PJEaJApU1Ko=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "83658b28fe638a170a19b8933aa008b30640fbd1",
"rev": "1a3c95e3b23b3cdb26750621c08cc2f1560cb883",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"ref": "nixos-23.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1654807842,
"narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "fc909087cc3386955f21b4665731dbdaceefb1d8",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1665087388,
"narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_5": {
"locked": {
"lastModified": 1676726892,
"narHash": "sha256-M7OYVR6dKmzmlebIjybFf3l18S2uur8lMyWWnHQooLY=",
"owner": "angerman",
"repo": "nixpkgs",
"rev": "729469087592bdea58b360de59dadf6d58714c42",
"type": "github"
},
"original": {
"owner": "angerman",
"ref": "release-22.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nosys": {
"locked": {
"lastModified": 1667881534,
"narHash": "sha256-FhwJ15uPLRsvaxtt/bNuqE/ykMpNAPF0upozFKhTtXM=",
"owner": "divnix",
"repo": "nosys",
"rev": "2d0d5207f6a230e9d0f660903f8db9807b54814f",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "nosys",
"type": "github"
}
},
"old-ghc-nix": {
"flake": false,
"locked": {
@@ -807,17 +654,21 @@
"flake-utils": "flake-utils",
"hackage": "hackage",
"haskellNix": "haskellNix",
"nixpkgs": "nixpkgs_5"
"mac2ios": "mac2ios",
"nixpkgs": [
"haskellNix",
"nixpkgs-2305"
]
}
},
"stackage": {
"flake": false,
"locked": {
"lastModified": 1677888571,
"narHash": "sha256-YkhRNOaN6QVagZo1cfykYV8KqkI8/q6r2F5+jypOma4=",
"lastModified": 1699834215,
"narHash": "sha256-g/JKy0BCvJaxPuYDl3QVc4OY8cFEomgG+hW/eEV470M=",
"owner": "input-output-hk",
"repo": "stackage.nix",
"rev": "cb50e6fabdfb2d7e655059039012ad0623f06a27",
"rev": "47aacd04abcce6bad57f43cbbbd133538380248e",
"type": "github"
},
"original": {
@@ -826,110 +677,18 @@
"type": "github"
}
},
"std": {
"inputs": {
"arion": [
"haskellNix",
"tullia",
"std",
"blank"
],
"blank": "blank",
"devshell": "devshell",
"dmerge": "dmerge",
"flake-utils": "flake-utils_4",
"incl": "incl",
"makes": [
"haskellNix",
"tullia",
"std",
"blank"
],
"microvm": [
"haskellNix",
"tullia",
"std",
"blank"
],
"n2c": "n2c",
"nixago": "nixago",
"nixpkgs": "nixpkgs_4",
"nosys": "nosys",
"yants": "yants"
},
"systems": {
"locked": {
"lastModified": 1674526466,
"narHash": "sha256-tMTaS0bqLx6VJ+K+ZT6xqsXNpzvSXJTmogkraBGzymg=",
"owner": "divnix",
"repo": "std",
"rev": "516387e3d8d059b50e742a2ff1909ed3c8f82826",
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "std",
"type": "github"
}
},
"tullia": {
"inputs": {
"nix-nomad": "nix-nomad",
"nix2container": "nix2container",
"nixpkgs": [
"haskellNix",
"nixpkgs"
],
"std": "std"
},
"locked": {
"lastModified": 1675695930,
"narHash": "sha256-B7rEZ/DBUMlK1AcJ9ajnAPPxqXY6zW2SBX+51bZV0Ac=",
"owner": "input-output-hk",
"repo": "tullia",
"rev": "621365f2c725608f381b3ad5b57afef389fd4c31",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "tullia",
"type": "github"
}
},
"utils": {
"locked": {
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"yants": {
"inputs": {
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1667096281,
"narHash": "sha256-wRRec6ze0gJHmGn6m57/zhz/Kdvp9HS4Nl5fkQ+uIuA=",
"owner": "divnix",
"repo": "yants",
"rev": "d18f356ec25cb94dc9c275870c3a7927a10f8c3c",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "yants",
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
+277 -24
View File
@@ -1,15 +1,15 @@
{
description = "nix flake for simplex-chat";
inputs.nixpkgs.url = "github:angerman/nixpkgs/release-22.11";
inputs.haskellNix.url = "github:input-output-hk/haskell.nix/armv7a";
inputs.haskellNix.inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "haskellNix/nixpkgs-2305";
inputs.mac2ios.url = "github:zw3rk/mobile-core-tools";
inputs.hackage = {
url = "github:input-output-hk/hackage.nix";
flake = false;
};
inputs.haskellNix.inputs.hackage.follows = "hackage";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, haskellNix, nixpkgs, flake-utils, ... }:
outputs = { self, haskellNix, nixpkgs, flake-utils, mac2ios, ... }:
let systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; in
flake-utils.lib.eachSystem systems (system:
# this android26 overlay makes the pkgsCross.{aarch64-android,armv7a-android-prebuilt} to set stdVer to 26 (Android 8).
@@ -30,7 +30,7 @@
# `appendOverlays` with a singleton is identical to `extend`.
let pkgs = haskellNix.legacyPackages.${system}.appendOverlays [android26]; in
let drv' = { extra-modules, pkgs', ... }: pkgs'.haskell-nix.project {
compiler-nix-name = "ghc8107";
compiler-nix-name = "ghc963";
index-state = "2023-12-12T00:00:00Z";
# We need this, to specify we want the cabal project.
# If the stack.yaml was dropped, this would not be necessary.
@@ -40,9 +40,12 @@
src = ./.;
};
sha256map = import ./scripts/nix/sha256map.nix;
modules = [{
modules = [
({ pkgs, lib, ...}: lib.mkIf (!pkgs.stdenv.hostPlatform.isWindows) {
# This patch adds `dl` as an extra-library to direct-sqlciper, which is needed
# on pretty much all unix platforms, but then blows up on windows m(
packages.direct-sqlcipher.patches = [ ./scripts/nix/direct-sqlcipher-2.3.27.patch ];
}
})
({ pkgs,lib, ... }: lib.mkIf (pkgs.stdenv.hostPlatform.isAndroid) {
packages.simplex-chat.components.library.ghcOptions = [ "-pie" ];
})] ++ extra-modules;
@@ -64,6 +67,9 @@
}); in
let iosPostInstall = bundleName: ''
${pkgs.tree}/bin/tree $out
mkdir tmp
find ./dist -name "libHS*-ghc*.a" -exec cp {} tmp \;
(cd tmp; ${pkgs.tree}/bin/tree .; ar x libHS*.a; for o in *.o; do if /usr/bin/otool -xv $o|grep ldadd ; then echo $o; fi; done; cd ..; rm -fR tmp)
mkdir -p $out/_pkg
# copy over includes, we might want those, but maybe not.
# cp -r $out/lib/*/*/include $out/_pkg/
@@ -74,6 +80,18 @@
find ${pkgs.gmp6.override { withStatic = true; }}/lib -name "*.a" -exec cp {} $out/_pkg \;
# There is no static libc
${pkgs.tree}/bin/tree $out/_pkg
for pkg in $out/_pkg/*.a; do
chmod +w $pkg
${mac2ios.packages.${system}.mac2ios}/bin/mac2ios $pkg
chmod -w $pkg
done
mkdir tmp
find $out/_pkg -name "libHS*-ghc*.a" -exec cp {} tmp \;
(cd tmp; ${pkgs.tree}/bin/tree .; ar x libHS*.a; for o in *.o; do if /usr/bin/otool -xv $o|grep ldadd ; then echo $o; fi; done; cd ..; rm -fR tmp)
sha256sum $out/_pkg/*.a
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/${bundleName}.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
@@ -119,13 +137,149 @@
hardeningDisable = [ "fortify" ];
}
);in {
# STATIC x86_64-linux
"${pkgs.pkgsCross.musl64.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.musl64).simplex-chat.components.exes.simplex-chat;
"${pkgs.pkgsCross.musl32.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.musl32).simplex-chat.components.exes.simplex-chat;
# STATIC i686-linux
"${pkgs.pkgsCross.musl32.hostPlatform.system}-static:exe:simplex-chat" = (drv' {
pkgs' = pkgs.pkgsCross.musl32;
extra-modules = [{
# 32 bit patches
packages.basement.patches = [
./scripts/nix/basement-pr-573.patch
];
packages.memory.patches = [
./scripts/nix/memory-pr-99.patch
];
}];
}).simplex-chat.components.exes.simplex-chat;
# WINDOWS x86_64-mingwW64
"${pkgs.pkgsCross.mingwW64.hostPlatform.system}:exe:simplex-chat" = (drv' {
pkgs' = pkgs.pkgsCross.mingwW64;
extra-modules = [{
packages.direct-sqlcipher.flags.openssl = true;
packages.bitvec.flags.simd = false;
packages.direct-sqlcipher.patches = [
./scripts/nix/direct-sqlcipher-2.3.27-win.patch
];
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(pkgs.pkgsCross.mingwW64.openssl) #.override) # { static = true; enableKTLS = false; })
];
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(pkgs.pkgsCross.mingwW64.openssl) #.override) # { static = true; enableKTLS = false; })
];
packages.unix-time.postPatch = ''
sed -i 's/mingwex//g' unix-time.cabal
'';
}];
}).simplex-chat.components.exes.simplex-chat.override {
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
mkdir -p $out/_pkg
cp $out/bin/* $out/_pkg
${pkgs.tree}/bin/tree $out/_pkg
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/${pkgs.pkgsCross.mingwW64.hostPlatform.system}-simplex-chat.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
"${pkgs.pkgsCross.mingwW64.hostPlatform.system}:lib:simplex-chat" = (drv' rec {
pkgs' = pkgs.pkgsCross.mingwW64;
extra-modules = [{
packages.direct-sqlcipher.flags.openssl = true;
# simd will try to read __cpu_model, which we don't expose
# from the rts (yet!).
packages.bitvec.flags.simd = false;
packages.direct-sqlcipher.patches = [
./scripts/nix/direct-sqlcipher-2.3.27-win.patch
];
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
pkgs.pkgsCross.mingwW64.openssl
];
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
pkgs.pkgsCross.mingwW64.openssl
];
packages.unix-time.postPatch = ''
sed -i 's/mingwex//g' unix-time.cabal
'';
}];
}).simplex-chat.components.library
.override (p: {
# enableShared = false;
setupBuildFlags = p.component.setupBuildFlags ++ map (x: "--ghc-option=${x}") [
"-shared"
"-threaded"
"-o" "libsimplex.dll"
# "-optl-lHSrts_thr"
"-optl-lffi"
# "-optl-static-libgcc"
# We can't do -optl-static-libstdc++ with gcc. g++ might
# but then we are chaning the compiler altogether.
"${./libsimplex.dll.def}"
];
postInstall = ''
set -x
function deps() {
${pkgs.binutils}/bin/strings "$1" | grep '.\.dll'|grep -v -E 'Winsock|ADVAPI32|dbghelp|KERNEL32|msvcrt|ntdll|ole32|RPCRT4|SHELL32|USER32|WINMM|WS2_32|kernel32|GDI32'|grep -v "$1"
}
${pkgs.tree}/bin/tree $out
mkdir -p $out/_pkg
cp libsimplex.dll $out/_pkg
cp libsimplex.dll.a $out/_pkg
mkdir $out/libs
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.openssl} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.libffi} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.gmp} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.stdenv.cc.cc} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.windows.mcfgthreads} -name "*.dll" -exec cp {} $out/libs \;
pushd $out/_pkg
function copyDeps() {
for dep in $(deps "$1"); do
if [ ! -f "$dep" ]; then
if [ ! -f ../libs/"$dep" ]; then
echo "WARN: $1 -> $dep not found!"
else
cp ../libs/"$dep" .
copyDeps "$dep"
fi
fi
done
}
copyDeps libsimplex.dll
popd
${pkgs.tree}/bin/tree $out/_pkg
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg-${pkgs.pkgsCross.mingwW64.hostPlatform.system}-libsimplex.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
});
# "${pkgs.pkgsCross.muslpi.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.muslpi).simplex-chat.components.exes.simplex-chat;
# STATIC aarch64-linux
"${pkgs.pkgsCross.aarch64-multiplatform-musl.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.aarch64-multiplatform-musl).simplex-chat.components.exes.simplex-chat;
"armv7a-android:lib:support" = (drv android32Pkgs).android-support.components.library.override {
smallAddressSpace = true; enableShared = false;
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsupport.so" ];
"armv7a-android:lib:support" = (drv android32Pkgs).android-support.components.library.override (p: {
smallAddressSpace = true;
# we won't want -dyamic (see aarch64-android:lib:simplex-chat)
enableShared = false;
# we also do not want to have any dependencies listed (especially no rts!)
enableStatic = false;
# This used to work with 8.10.7...
# setupBuildFlags = p.component.setupBuildFlags ++ map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsupport.so" ];
# ... but now with 9.6+
# we have to do the -shared thing by hand.
postBuild = ''
armv7a-unknown-linux-androideabi-ghc -shared -o libsupport.so \
-optl-Wl,-u,setLineBuffering \
-optl-Wl,-u,pipe_std_to_socket \
dist/build/*.a
'';
postInstall = ''
mkdir -p $out/_pkg
@@ -138,14 +292,29 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
"aarch64-android:lib:support" = (drv androidPkgs).android-support.components.library.override {
smallAddressSpace = true; enableShared = false;
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsupport.so" ];
});
# The android-support package is at
# https://github.com/simplex-chat/android-support
"aarch64-android:lib:support" = (drv androidPkgs).android-support.components.library.override (p: {
smallAddressSpace = true;
# no -dynamic
enableShared = false;
# but also no -staticlib
enableStatic = false;
# we have to do the -shared thing by hand.
postBuild = ''
aarch64-unknown-linux-android-ghc -shared -o libsupport.so \
-optl-Wl,-u,setLineBuffering \
-optl-Wl,-u,pipe_std_to_socket \
dist/build/*.a
'';
postInstall = ''
mkdir -p $out/_pkg
cp libsupport.so $out/_pkg
ls -lah $out/_pkg/*
${pkgs.patchelf}/bin/patchelf --remove-needed libunwind.so.1 $out/_pkg/libsupport.so
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg-aarch64-android-libsupport.zip *)
rm -fR $out/_pkg
@@ -154,10 +323,11 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
});
"armv7a-android:lib:simplex-chat" = (drv' {
pkgs' = android32Pkgs;
extra-modules = [{
packages.text.flags.simdutf = false;
packages.direct-sqlcipher.flags.openssl = true;
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(android32Pkgs.openssl.override { static = true; enableKTLS = false; })
@@ -168,13 +338,56 @@
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(android32Pkgs.openssl.override { static = true; enableKTLS = false; })
];
# 32 bit patches
packages.basement.patches = [
./scripts/nix/basement-pr-573.patch
];
packages.memory.patches = [
./scripts/nix/memory-pr-99.patch
];
}];
}).simplex-chat.components.library.override {
smallAddressSpace = true; enableShared = false;
}).simplex-chat.components.library.override (p: {
smallAddressSpace = true;
# we want -shared, but not -dyanmic, hence `enableShared = false`.
enableShared = false;
# we _do_ want rts, and other libs. Hence `enableStatic = true`.
enableStatic = true;
# for android we build a shared library, passing these arguments is a bit tricky, as
# we want only the threaded rts (HSrts_thr) and ffi to be linked, but not fed into iserv for
# template haskell cross compilation. Thus we just pass them as linker options (-optl).
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsimplex.so" "-optl-lHSrts_thr" "-optl-lffi"];
setupBuildFlags = p.component.setupBuildFlags
# flags to tell GHC we want to produce a -shared object, and we want to also link
# - the ffi library (ffi)
++ map (x: "--ghc-option=${x}") [
"-shared" "-o" "libsimplex.so"
"-threaded"
# "-debug"
"-optl-lffi"
]
# This is fairly idiotic. LLD will strip out foreign exported
# symbols (a GHC bug? Codegen bug?). So we need to pass `-u <sym>`
# to ensure they stay in the produced library. Having them
# _undefined_ and _lazy_ (lld will tell with -y <sym> that the
# symbol is lazy), makes them _defined_. m(
++ map (sym: "--ghc-option=-optl-Wl,-u,${sym}") [
"chat_close_store"
"chat_decrypt_file"
"chat_decrypt_media"
"chat_encrypt_file"
"chat_encrypt_media"
"chat_migrate_init"
"chat_parse_markdown"
"chat_parse_server"
"chat_password_hash"
"chat_read_file"
"chat_recv_msg"
"chat_recv_msg_wait"
"chat_send_cmd"
"chat_send_remote_cmd"
"chat_valid_name"
"chat_json_length"
"chat_write_file"
];
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
@@ -218,10 +431,11 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
});
"aarch64-android:lib:simplex-chat" = (drv' {
pkgs' = androidPkgs;
extra-modules = [{
packages.text.flags.simdutf = false;
packages.direct-sqlcipher.flags.openssl = true;
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(androidPkgs.openssl.override { static = true; })
@@ -233,12 +447,50 @@
(androidPkgs.openssl.override { static = true; })
];
}];
}).simplex-chat.components.library.override {
smallAddressSpace = true; enableShared = false;
}).simplex-chat.components.library.override (p: {
smallAddressSpace = true;
# we do not want a dynamically linked object, even though we _do_
# want to produce a _shared_ object. But `shared` implied -dyanmic
# with cabal, so we disable and pass `-shared` explicitly.
enableShared = false;
# we do want static (e.g. pass all dependencies in, so we get -staticlib)
enableStatic = true;
# for android we build a shared library, passing these arguments is a bit tricky, as
# we want only the threaded rts (HSrts_thr) and ffi to be linked, but not fed into iserv for
# template haskell cross compilation. Thus we just pass them as linker options (-optl).
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsimplex.so" "-optl-lHSrts_thr" "-optl-lffi"];
setupBuildFlags = p.component.setupBuildFlags
# flags to tell GHC we want to produce a -shared object, and we want to also link
# - the ffi library (ffi)
++ map (x: "--ghc-option=${x}") [
"-shared" "-o" "libsimplex.so"
"-threaded"
# "-debug"
"-optl-lffi"
]
# This is fairly idiotic. LLD will strip out foreign exported
# symbols (a GHC bug? Codegen bug?). So we need to pass `-u <sym>`
# to ensure they stay in the produced library. Having them
# _undefined_ and _lazy_ (lld will tell with -y <sym> that the
# symbol is lazy), makes them _defined_. m(
++ map (sym: "--ghc-option=-optl-Wl,-u,${sym}") [
"chat_close_store"
"chat_decrypt_file"
"chat_decrypt_media"
"chat_encrypt_file"
"chat_encrypt_media"
"chat_migrate_init"
"chat_parse_markdown"
"chat_parse_server"
"chat_password_hash"
"chat_read_file"
"chat_recv_msg"
"chat_recv_msg_wait"
"chat_send_cmd"
"chat_send_remote_cmd"
"chat_valid_name"
"chat_json_length"
"chat_write_file"
];
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
@@ -282,7 +534,7 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
});
};
# builds for iOS and iOS simulator
@@ -296,7 +548,8 @@
packages.direct-sqlcipher.flags.commoncrypto = true;
packages.entropy.flags.DoNotGetEntropy = true;
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(pkgs.openssl.override { static = true; })
# TODO: have a cross override for iOS, that sets this.
((pkgs.openssl.override { static = true; }).overrideDerivation (old: { CFLAGS = "-mcpu=apple-a7 -march=armv8-a+norcpc" ;}))
];
}];
}).simplex-chat.components.library.override (
+3 -2
View File
@@ -1,5 +1,5 @@
name: simplex-chat
version: 5.6.1.0
version: 5.6.0.4
#synopsis:
#description:
homepage: https://github.com/simplex-chat/simplex-chat#readme
@@ -18,7 +18,6 @@ dependencies:
- async == 2.2.*
- attoparsec == 0.14.*
- base >= 4.7 && < 5
- base64-bytestring >= 1.0 && < 1.3
- composition == 1.0.*
- constraints >= 0.12 && < 0.14
- containers == 0.6.*
@@ -159,6 +158,8 @@ ghc-options:
- -Wincomplete-record-updates
- -Wincomplete-uni-patterns
- -Wunused-type-patterns
- -finfo-table-map
- -fdistinct-constructor-tables
default-extensions:
- StrictData
@@ -2,7 +2,7 @@
set -e
trap "rm apps/multiplatform/local.properties || true; rm local.properties || true; rm /tmp/simplex.keychain || true" EXIT
trap "rm apps/multiplatform/local.properties 2> /dev/null || true; rm local.properties 2> /dev/null || true; rm /tmp/simplex.keychain" EXIT
echo "desktop.mac.signing.identity=Developer ID Application: SimpleX Chat Ltd (5NN7GUYB6T)" >> apps/multiplatform/local.properties
echo "desktop.mac.signing.keychain=/tmp/simplex.keychain" >> apps/multiplatform/local.properties
echo "desktop.mac.notarization.apple_id=$APPLE_SIMPLEX_NOTARIZATION_APPLE_ID" >> apps/multiplatform/local.properties
@@ -10,6 +10,10 @@ echo "desktop.mac.notarization.password=$APPLE_SIMPLEX_NOTARIZATION_PASSWORD" >>
echo "desktop.mac.notarization.team_id=5NN7GUYB6T" >> apps/multiplatform/local.properties
echo "$APPLE_SIMPLEX_SIGNING_KEYCHAIN" | base64 --decode - > /tmp/simplex.keychain
security unlock-keychain -p "" /tmp/simplex.keychain
# Adding keychain to the list of keychains.
# Otherwise, it can find cert but exits while signing with "error: The specified item could not be found in the keychain."
security list-keychains -s `security list-keychains | xargs` /tmp/simplex.keychain
scripts/desktop/build-lib-mac.sh
cd apps/multiplatform
./gradlew packageDmg
+10
View File
@@ -0,0 +1,10 @@
#!/bin/bash
security create-keychain -p "" simplex.keychain
security set-keychain-settings -u simplex.keychain
security add-certificates -k simplex.keychain "Developer ID Application: SimpleX Chat Ltd (5NN7GUYB6T).cer"
security add-certificates -k simplex.keychain "Developer ID Certification Authority.cer"
# Private key with access from any app
security import "SimpleX Chat.p12" -P "" -k simplex.keychain -A
# Public key
security import "SimpleX Chat.pem" -k simplex.keychain
+2 -2
View File
@@ -8,7 +8,7 @@ function readlink() {
OS=linux
ARCH=${1:-`uname -a | rev | cut -d' ' -f2 | rev`}
GHC_VERSION=8.10.7
GHC_VERSION=9.6.3
if [ "$ARCH" == "aarch64" ]; then
COMPOSE_ARCH=arm64
@@ -25,7 +25,7 @@ for elem in "${exports[@]}"; do count=$(grep -R "$elem$" libsimplex.dll.def | wc
for elem in "${exports[@]}"; do count=$(grep -R "\"$elem\"" flake.nix | wc -l); if [ $count -ne 2 ]; then echo Wrong exports in flake.nix. Add \"$elem\" in two places of the file; exit 1; fi ; done
rm -rf $BUILD_DIR
cabal build lib:simplex-chat --ghc-options='-optl-Wl,-rpath,$ORIGIN' --ghc-options="-optl-L$(ghc --print-libdir)/rts -optl-Wl,--as-needed,-lHSrts_thr-ghc$GHC_VERSION"
cabal build lib:simplex-chat --ghc-options='-optl-Wl,-rpath,$ORIGIN -flink-rts -threaded'
cd $BUILD_DIR/build
#patchelf --add-needed libHSrts_thr-ghc${GHC_VERSION}.so libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so
#patchelf --add-rpath '$ORIGIN' libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so
+19 -3
View File
@@ -5,13 +5,14 @@ set -e
OS=mac
ARCH="${1:-`uname -a | rev | cut -d' ' -f1 | rev`}"
COMPOSE_ARCH=$ARCH
GHC_VERSION=8.10.7
GHC_VERSION=9.6.3
if [ "$ARCH" == "arm64" ]; then
ARCH=aarch64
else
COMPOSE_ARCH=x64
fi
LIB_EXT=dylib
LIB=libHSsimplex-chat-*-inplace-ghc*.$LIB_EXT
GHC_LIBS_DIR=$(ghc --print-libdir)
@@ -23,13 +24,26 @@ for elem in "${exports[@]}"; do count=$(grep -R "$elem$" libsimplex.dll.def | wc
for elem in "${exports[@]}"; do count=$(grep -R "\"$elem\"" flake.nix | wc -l); if [ $count -ne 2 ]; then echo Wrong exports in flake.nix. Add \"$elem\" in two places of the file; exit 1; fi ; done
rm -rf $BUILD_DIR
cabal build lib:simplex-chat lib:simplex-chat --ghc-options="-optl-Wl,-rpath,@loader_path -optl-Wl,-L$GHC_LIBS_DIR/rts -optl-lHSrts_thr-ghc8.10.7 -optl-lffi"
cabal build lib:simplex-chat lib:simplex-chat --ghc-options="-optl-Wl,-rpath,@loader_path -optl-Wl,-L$GHC_LIBS_DIR/$ARCH-osx-ghc-$GHC_VERSION -optl-lHSrts_thr-ghc$GHC_VERSION -optl-lffi"
cd $BUILD_DIR/build
mkdir deps 2> /dev/null || true
# It's not included by default for some reason. Compiled lib tries to find system one but it's not always available
cp $GHC_LIBS_DIR/rts/libffi.dylib ./deps
#cp $GHC_LIBS_DIR/libffi.dylib ./deps
(
BUILD=$PWD
cp /tmp/libffi-3.4.4/*-apple-darwin*/.libs/libffi.dylib $BUILD/deps || \
( \
cd /tmp && \
curl --tlsv1.2 "https://gitlab.haskell.org/ghc/libffi-tarballs/-/raw/libffi-3.4.4/libffi-3.4.4.tar.gz?inline=false" -o libffi.tar.gz && \
tar -xzvf libffi.tar.gz && \
cd "libffi-3.4.4" && \
./configure && \
make && \
cp *-apple-darwin*/.libs/libffi.dylib $BUILD/deps \
)
)
DYLIBS=`otool -L $LIB | grep @rpath | tail -n +2 | cut -d' ' -f 1 | cut -d'/' -f2`
RPATHS=`otool -l $LIB | grep "path "| cut -d' ' -f11`
@@ -70,6 +84,8 @@ function copy_deps() {
}
copy_deps $LIB
# Special case
cp $(ghc --print-libdir)/$ARCH-osx-ghc-$GHC_VERSION/libHSghc-boot-th-$GHC_VERSION-ghc$GHC_VERSION.dylib deps
rm deps/`basename $LIB`
cd -
+242
View File
@@ -0,0 +1,242 @@
From 38be2c93acb6f459d24ed6c626981c35ccf44095 Mon Sep 17 00:00:00 2001
From: Sylvain Henry <sylvain@haskus.fr>
Date: Thu, 16 Feb 2023 15:40:45 +0100
Subject: [PATCH] Fix build on 32-bit architectures
---
Basement/Bits.hs | 4 ++++
Basement/From.hs | 24 -----------------------
Basement/Numerical/Additive.hs | 4 ++++
Basement/Numerical/Conversion.hs | 20 +++++++++++++++++++
Basement/PrimType.hs | 6 +++++-
Basement/Types/OffsetSize.hs | 22 +++++++++++++++++++--
6 files changed, 53 insertions(+), 27 deletions(-)
diff --git a/Basement/Bits.hs b/Basement/Bits.hs
index 7eeea0f5..24520ed7 100644
--- a/Basement/Bits.hs
+++ b/Basement/Bits.hs
@@ -54,8 +54,12 @@ import GHC.Int
import Basement.Compat.Primitive
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
-- | operation over finite bits
class FiniteBitsOps bits where
diff --git a/Basement/From.hs b/Basement/From.hs
index 7bbe141c..80014b3e 100644
--- a/Basement/From.hs
+++ b/Basement/From.hs
@@ -272,23 +272,11 @@ instance (NatWithinBound (CountOf ty) n, KnownNat n, PrimType ty)
tryFrom = BlockN.toBlockN . UArray.toBlock . BoxArray.mapToUnboxed id
instance (KnownNat n, NatWithinBound Word8 n) => From (Zn64 n) Word8 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . unZn64 where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . unZn64 where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word16 n) => From (Zn64 n) Word16 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . unZn64 where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . unZn64 where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word32 n) => From (Zn64 n) Word32 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . unZn64 where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . unZn64 where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# w))
-#endif
instance From (Zn64 n) Word64 where
from = unZn64
instance From (Zn64 n) Word128 where
@@ -297,23 +285,11 @@ instance From (Zn64 n) Word256 where
from = from . unZn64
instance (KnownNat n, NatWithinBound Word8 n) => From (Zn n) Word8 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word16 n) => From (Zn n) Word16 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word32 n) => From (Zn n) Word32 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word64 n) => From (Zn n) Word64 where
from = naturalToWord64 . unZn
instance (KnownNat n, NatWithinBound Word128 n) => From (Zn n) Word128 where
diff --git a/Basement/Numerical/Additive.hs b/Basement/Numerical/Additive.hs
index d0dfb973..8ab65aa0 100644
--- a/Basement/Numerical/Additive.hs
+++ b/Basement/Numerical/Additive.hs
@@ -30,8 +30,12 @@ import qualified Basement.Types.Word128 as Word128
import qualified Basement.Types.Word256 as Word256
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
-- | Represent class of things that can be added together,
-- contains a neutral element and is commutative.
diff --git a/Basement/Numerical/Conversion.hs b/Basement/Numerical/Conversion.hs
index db502c07..fddc8232 100644
--- a/Basement/Numerical/Conversion.hs
+++ b/Basement/Numerical/Conversion.hs
@@ -26,8 +26,12 @@ import GHC.Word
import Basement.Compat.Primitive
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
intToInt64 :: Int -> Int64
#if WORD_SIZE_IN_BITS == 64
@@ -96,11 +100,22 @@ int64ToWord64 (I64# i) = W64# (int64ToWord64# i)
#endif
#if WORD_SIZE_IN_BITS == 64
+#if __GLASGOW_HASKELL__ >= 904
+word64ToWord# :: Word64# -> Word#
+word64ToWord# i = word64ToWord# i
+#else
word64ToWord# :: Word# -> Word#
word64ToWord# i = i
+#endif
{-# INLINE word64ToWord# #-}
#endif
+#if WORD_SIZE_IN_BITS < 64
+word64ToWord32# :: Word64# -> Word32#
+word64ToWord32# i = wordToWord32# (word64ToWord# i)
+{-# INLINE word64ToWord32# #-}
+#endif
+
-- | 2 Word32s
data Word32x2 = Word32x2 {-# UNPACK #-} !Word32
{-# UNPACK #-} !Word32
@@ -113,9 +128,14 @@ word64ToWord32s (W64# w64) = Word32x2 (W32# (wordToWord32# (uncheckedShiftRL# (G
word64ToWord32s (W64# w64) = Word32x2 (W32# (wordToWord32# (uncheckedShiftRL# w64 32#))) (W32# (wordToWord32# w64))
#endif
#else
+#if __GLASGOW_HASKELL__ >= 904
+word64ToWord32s :: Word64 -> Word32x2
+word64ToWord32s (W64# w64) = Word32x2 (W32# (word64ToWord32# (uncheckedShiftRL64# w64 32#))) (W32# (word64ToWord32# w64))
+#else
word64ToWord32s :: Word64 -> Word32x2
word64ToWord32s (W64# w64) = Word32x2 (W32# (word64ToWord# (uncheckedShiftRL64# w64 32#))) (W32# (word64ToWord# w64))
#endif
+#endif
wordToChar :: Word -> Char
wordToChar (W# word) = C# (chr# (word2Int# word))
diff --git a/Basement/PrimType.hs b/Basement/PrimType.hs
index f8ca2926..a888ec91 100644
--- a/Basement/PrimType.hs
+++ b/Basement/PrimType.hs
@@ -54,7 +54,11 @@ import Basement.Nat
import qualified Prelude (quot)
#if WORD_SIZE_IN_BITS < 64
-import GHC.IntWord64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
+import GHC.IntWord64
+#endif
#endif
#ifdef FOUNDATION_BOUNDS_CHECK
diff --git a/Basement/Types/OffsetSize.hs b/Basement/Types/OffsetSize.hs
index cd944927..1ea80dad 100644
--- a/Basement/Types/OffsetSize.hs
+++ b/Basement/Types/OffsetSize.hs
@@ -70,8 +70,12 @@ import Data.List (foldl')
import qualified Prelude
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
-- | File size in bytes
newtype FileSize = FileSize Word64
@@ -225,20 +229,26 @@ countOfRoundUp alignment (CountOf n) = CountOf ((n + (alignment-1)) .&. compleme
csizeOfSize :: CountOf Word8 -> CSize
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+csizeOfSize (CountOf (I# sz)) = CSize (W32# (wordToWord32# (int2Word# sz)))
+#else
csizeOfSize (CountOf (I# sz)) = CSize (W32# (int2Word# sz))
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
csizeOfSize (CountOf (I# sz)) = CSize (W64# (wordToWord64# (int2Word# sz)))
-
#else
csizeOfSize (CountOf (I# sz)) = CSize (W64# (int2Word# sz))
-
#endif
#endif
csizeOfOffset :: Offset8 -> CSize
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+csizeOfOffset (Offset (I# sz)) = CSize (W32# (wordToWord32# (int2Word# sz)))
+#else
csizeOfOffset (Offset (I# sz)) = CSize (W32# (int2Word# sz))
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
csizeOfOffset (Offset (I# sz)) = CSize (W64# (wordToWord64# (int2Word# sz)))
@@ -250,7 +260,11 @@ csizeOfOffset (Offset (I# sz)) = CSize (W64# (int2Word# sz))
sizeOfCSSize :: CSsize -> CountOf Word8
sizeOfCSSize (CSsize (-1)) = error "invalid size: CSSize is -1"
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+sizeOfCSSize (CSsize (I32# sz)) = CountOf (I# (int32ToInt# sz))
+#else
sizeOfCSSize (CSsize (I32# sz)) = CountOf (I# sz)
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
sizeOfCSSize (CSsize (I64# sz)) = CountOf (I# (int64ToInt# sz))
@@ -261,7 +275,11 @@ sizeOfCSSize (CSsize (I64# sz)) = CountOf (I# sz)
sizeOfCSize :: CSize -> CountOf Word8
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+sizeOfCSize (CSize (W32# sz)) = CountOf (I# (word2Int# (word32ToWord# sz)))
+#else
sizeOfCSize (CSize (W32# sz)) = CountOf (I# (word2Int# sz))
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
sizeOfCSize (CSize (W64# sz)) = CountOf (I# (word2Int# (word64ToWord# sz)))
@@ -0,0 +1,12 @@
diff --git a/direct-sqlcipher.cabal b/direct-sqlcipher.cabal
index 728ba3e..c63745e 100644
--- a/direct-sqlcipher.cabal
+++ b/direct-sqlcipher.cabal
@@ -84,6 +84,8 @@ library
cc-options: -DSQLITE_TEMP_STORE=2
-DSQLITE_HAS_CODEC
+ extra-libraries: ws2_32
+
if !os(windows) && !os(android)
extra-libraries: pthread
+36
View File
@@ -0,0 +1,36 @@
From 2738929ce15b4c8704bbbac24a08539b5d4bf30e Mon Sep 17 00:00:00 2001
From: sternenseemann <sternenseemann@systemli.org>
Date: Mon, 14 Aug 2023 10:51:30 +0200
Subject: [PATCH] Data.Memory.Internal.CompatPrim64: fix 32 bit with GHC >= 9.4
Since 9.4, GHC.Prim exports Word64# operations like timesWord64# even on
i686 whereas GHC.IntWord64 no longer exists. Therefore, we can just use
the ready made solution.
Closes #98, as it should be the better solution.
---
Data/Memory/Internal/CompatPrim64.hs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Data/Memory/Internal/CompatPrim64.hs b/Data/Memory/Internal/CompatPrim64.hs
index b9eef8a..a134c88 100644
--- a/Data/Memory/Internal/CompatPrim64.hs
+++ b/Data/Memory/Internal/CompatPrim64.hs
@@ -150,6 +150,7 @@ w64# :: Word# -> Word# -> Word# -> Word64#
w64# w _ _ = w
#elif WORD_SIZE_IN_BITS == 32
+#if __GLASGOW_HASKELL__ < 904
import GHC.IntWord64
import GHC.Prim (Word#)
@@ -158,6 +159,9 @@ timesWord64# a b =
let !ai = word64ToInt64# a
!bi = word64ToInt64# b
in int64ToWord64# (timesInt64# ai bi)
+#else
+import GHC.Prim
+#endif
w64# :: Word# -> Word# -> Word# -> Word64#
w64# _ hw lw =
+2 -1
View File
@@ -1,9 +1,10 @@
{
"https://github.com/simplex-chat/simplexmq.git"."1e6268cc1dbba69639425f7d5a6c9a07995e0bb2" = "14pvy7vivvigxj876kwikxcy7c2jc30azwydfgvnlj4xwcclil8q";
"https://github.com/simplex-chat/simplexmq.git"."8b94264623eb8f32793a3b4129cb12770f54ef3a" = "0n4wwpkj9dps7ansvlrdf4kiwjczij7y79i4cnr3gr0lmml8bpbs";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";
"https://github.com/simplex-chat/aeson.git"."aab7b5a14d6c5ea64c64dcaee418de1bb00dcc2b" = "0jz7kda8gai893vyvj96fy962ncv8dcsx71fbddyy8zrvc88jfrr";
"https://github.com/simplex-chat/base64.git"."2d77b6dbcaffc00570a70be8694049f3710e7c94" = "0zdskk67fzqrrx1i29s3shp7fh9c0krmq5h6hq03qx0n3xy2m44b";
"https://github.com/simplex-chat/haskell-terminal.git"."f708b00009b54890172068f168bf98508ffcd495" = "0zmq7lmfsk8m340g47g5963yba7i88n4afa6z93sg9px5jv1mijj";
"https://github.com/simplex-chat/android-support.git"."9aa09f148089d6752ce563b14c2df1895718d806" = "0pbf2pf13v2kjzi397nr13f1h3jv0imvsq8rpiyy2qyx5vd50pqn";
"https://github.com/simplex-chat/zip.git"."bd421c6b19cc4c465cd7af1f6f26169fb8ee1ebc" = "1csqfjhvc8wb5h4kxxndmb6iw7b4ib9ff2n81hrizsmnf45a6gg0";
+8 -15
View File
@@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack
name: simplex-chat
version: 5.6.1.0
version: 5.6.0.4
category: Web, System, Services, Cryptography
homepage: https://github.com/simplex-chat/simplex-chat#readme
author: simplex.chat
@@ -183,14 +183,13 @@ library
src
default-extensions:
StrictData
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -finfo-table-map -fdistinct-constructor-tables
build-depends:
aeson ==2.2.*
, ansi-terminal >=0.10 && <0.12
, async ==2.2.*
, attoparsec ==0.14.*
, base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3
, composition ==1.0.*
, constraints >=0.12 && <0.14
, containers ==0.6.*
@@ -245,14 +244,13 @@ executable simplex-bot
apps/simplex-bot
default-extensions:
StrictData
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -threaded
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -finfo-table-map -fdistinct-constructor-tables -threaded
build-depends:
aeson ==2.2.*
, ansi-terminal >=0.10 && <0.12
, async ==2.2.*
, attoparsec ==0.14.*
, base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3
, composition ==1.0.*
, constraints >=0.12 && <0.14
, containers ==0.6.*
@@ -308,14 +306,13 @@ executable simplex-bot-advanced
apps/simplex-bot-advanced
default-extensions:
StrictData
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -threaded
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -finfo-table-map -fdistinct-constructor-tables -threaded
build-depends:
aeson ==2.2.*
, ansi-terminal >=0.10 && <0.12
, async ==2.2.*
, attoparsec ==0.14.*
, base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3
, composition ==1.0.*
, constraints >=0.12 && <0.14
, containers ==0.6.*
@@ -374,14 +371,13 @@ executable simplex-broadcast-bot
Broadcast.Bot
Broadcast.Options
Paths_simplex_chat
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -threaded
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -finfo-table-map -fdistinct-constructor-tables -threaded
build-depends:
aeson ==2.2.*
, ansi-terminal >=0.10 && <0.12
, async ==2.2.*
, attoparsec ==0.14.*
, base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3
, composition ==1.0.*
, constraints >=0.12 && <0.14
, containers ==0.6.*
@@ -438,14 +434,13 @@ executable simplex-chat
apps/simplex-chat
default-extensions:
StrictData
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -threaded
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -finfo-table-map -fdistinct-constructor-tables -threaded
build-depends:
aeson ==2.2.*
, ansi-terminal >=0.10 && <0.12
, async ==2.2.*
, attoparsec ==0.14.*
, base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3
, composition ==1.0.*
, constraints >=0.12 && <0.14
, containers ==0.6.*
@@ -508,14 +503,13 @@ executable simplex-directory-service
Directory.Service
Directory.Store
Paths_simplex_chat
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -threaded
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -finfo-table-map -fdistinct-constructor-tables -threaded
build-depends:
aeson ==2.2.*
, ansi-terminal >=0.10 && <0.12
, async ==2.2.*
, attoparsec ==0.14.*
, base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3
, composition ==1.0.*
, constraints >=0.12 && <0.14
, containers ==0.6.*
@@ -602,7 +596,7 @@ test-suite simplex-chat-test
apps/simplex-directory-service/src
default-extensions:
StrictData
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -threaded
ghc-options: -O2 -Wall -Wcompat -Werror=incomplete-patterns -Wredundant-constraints -Wincomplete-record-updates -Wincomplete-uni-patterns -Wunused-type-patterns -finfo-table-map -fdistinct-constructor-tables -threaded
build-depends:
QuickCheck ==2.14.*
, aeson ==2.2.*
@@ -610,7 +604,6 @@ test-suite simplex-chat-test
, async ==2.2.*
, attoparsec ==0.14.*
, base >=4.7 && <5
, base64-bytestring >=1.0 && <1.3
, composition ==1.0.*
, constraints >=0.12 && <0.14
, containers ==0.6.*
+5 -5
View File
@@ -29,7 +29,6 @@ import qualified Data.Attoparsec.ByteString.Char8 as A
import Data.Bifunctor (bimap, first, second)
import Data.ByteArray (ScrubbedBytes)
import qualified Data.ByteArray as BA
import qualified Data.ByteString.Base64 as B64
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as LB
@@ -104,8 +103,9 @@ import qualified Simplex.Messaging.Crypto.File as CF
import Simplex.Messaging.Crypto.Ratchet (PQEncryption (..), PQSupport (..), pattern IKNoPQ, pattern IKPQOff, pattern PQEncOff, pattern PQEncOn, pattern PQSupportOff, pattern PQSupportOn)
import qualified Simplex.Messaging.Crypto.Ratchet as CR
import Simplex.Messaging.Encoding
import Simplex.Messaging.Encoding.Base64 (base64P)
import qualified Simplex.Messaging.Encoding.Base64 as B64
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers (base64P)
import Simplex.Messaging.Protocol (AProtoServerWithAuth (..), AProtocolType (..), EntityId, ErrorType (..), MsgBody, MsgFlags (..), NtfServer, ProtoServerWithAuth, ProtocolTypeI, SProtocolType (..), SubscriptionMode (..), UserProtocol, userProtocol)
import qualified Simplex.Messaging.Protocol as SMP
import Simplex.Messaging.ServiceScheme (ServiceScheme (..))
@@ -2989,9 +2989,9 @@ agentSubscriber :: CM' ()
agentSubscriber = do
q <- asks $ subQ . smpAgent
l <- asks chatLock
forever $ atomically (readTBQueue q) >>= process l
forever $ atomically (readTBQueue q) >>= void . process l
where
process :: Lock -> (ACorrId, EntityId, APartyCmd 'Agent) -> CM' ()
process :: Lock -> (ACorrId, EntityId, APartyCmd 'Agent) -> CM' (Either ChatError ())
process l (corrId, entId, APC e msg) = run $ case e of
SAENone -> processAgentMessageNoConn msg
SAEConn -> processAgentMessage corrId entId msg
@@ -3000,7 +3000,7 @@ agentSubscriber = do
where
run action = do
let name = "agentSubscriber entity=" <> show e <> " entId=" <> str entId <> " msg=" <> str (aCommandTag msg)
withLock' l name $ action `catchChatError'` (toView' . CRChatError Nothing)
withLock l name $ runExceptT $ action `catchChatError` (toView . CRChatError Nothing)
str :: StrEncoding a => a -> String
str = B.unpack . strEncode
+1 -2
View File
@@ -62,7 +62,6 @@ import Simplex.Chat.Remote.Types
import Simplex.Chat.Store (AutoAccept, StoreError (..), UserContactLink, UserMsgReceiptSettings)
import Simplex.Chat.Types
import Simplex.Chat.Types.Preferences
import Simplex.Chat.Util (liftIOEither)
import Simplex.FileTransfer.Description (FileDescriptionURI)
import Simplex.Messaging.Agent (AgentClient, SubscriptionsInfo)
import Simplex.Messaging.Agent.Client (AgentLocks, AgentWorkersDetails (..), AgentWorkersSummary (..), ProtocolTestFailure)
@@ -1341,7 +1340,7 @@ withStore' action = withStore $ liftIO . action
withStore :: (DB.Connection -> ExceptT StoreError IO a) -> CM a
withStore action = do
ChatController {chatStore} <- ask
liftIOEither $ withTransaction chatStore (runExceptT . withExceptT ChatErrorStore . action) `E.catches` handleDBErrors
liftEither =<< liftIO (withTransaction chatStore (runExceptT . withExceptT ChatErrorStore . action) `E.catches` handleDBErrors)
withStoreBatch :: Traversable t => (DB.Connection -> t (IO (Either ChatError a))) -> CM' (t (Either ChatError a))
withStoreBatch actions = do
+1 -1
View File
@@ -24,7 +24,6 @@ import qualified Data.Aeson as J
import qualified Data.Aeson.Encoding as JE
import qualified Data.Aeson.TH as JQ
import qualified Data.Attoparsec.ByteString.Char8 as A
import qualified Data.ByteString.Base64 as B64
import qualified Data.ByteString.Lazy.Char8 as LB
import Data.Char (isSpace)
import Data.Int (Int64)
@@ -48,6 +47,7 @@ import Simplex.Chat.Types.Preferences
import Simplex.Messaging.Agent.Protocol (AgentMsgId, MsgMeta (..), MsgReceiptStatus (..))
import Simplex.Messaging.Crypto.File (CryptoFile (..))
import qualified Simplex.Messaging.Crypto.File as CF
import qualified Simplex.Messaging.Encoding.Base64 as B64
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, enumJSON, fromTextField_, parseAll, sumTypeJSON)
import Simplex.Messaging.Protocol (MsgBody)
+1 -1
View File
@@ -17,7 +17,6 @@ import qualified Data.Aeson.TH as JQ
import Data.Bifunctor (first)
import Data.ByteArray (ScrubbedBytes)
import qualified Data.ByteArray as BA
import qualified Data.ByteString.Base64.URL as U
import Data.ByteString.Char8 (ByteString)
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as LB
@@ -50,6 +49,7 @@ import Simplex.Messaging.Agent.Env.SQLite (createAgentStore)
import Simplex.Messaging.Agent.Store.SQLite (MigrationConfirmation (..), MigrationError, closeSQLiteStore, reopenSQLiteStore)
import Simplex.Messaging.Client (defaultNetworkConfig)
import qualified Simplex.Messaging.Crypto as C
import qualified Simplex.Messaging.Encoding.Base64.URL as U
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Parsers (defaultJSON, dropPrefix, sumTypeJSON)
import Simplex.Messaging.Protocol (AProtoServerWithAuth (..), AProtocolType (..), BasicAuth (..), CorrId (..), ProtoServerWithAuth (..), ProtocolServer (..))
+1 -1
View File
@@ -17,7 +17,6 @@ import Data.Bifunctor (bimap)
import qualified Data.ByteArray as BA
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import qualified Data.ByteString.Base64.URL as U
import Data.Either (fromLeft)
import Data.Word (Word8)
import Foreign.C (CInt, CString, newCAString)
@@ -26,6 +25,7 @@ import Foreign.StablePtr
import Simplex.Chat.Controller (ChatController (..))
import Simplex.Chat.Mobile.Shared
import qualified Simplex.Messaging.Crypto as C
import qualified Simplex.Messaging.Encoding.Base64.URL as U
import UnliftIO (atomically)
cChatEncryptMedia :: StablePtr ChatController -> CString -> Ptr Word8 -> CInt -> IO CString
+22 -24
View File
@@ -22,7 +22,6 @@ import Crypto.Random (getRandomBytes)
import qualified Data.Aeson as J
import qualified Data.Aeson.Types as JT
import Data.ByteString (ByteString)
import qualified Data.ByteString.Base64.URL as B64U
import Data.ByteString.Builder (Builder)
import qualified Data.ByteString.Char8 as B
import Data.Functor (($>))
@@ -56,6 +55,7 @@ import Simplex.Messaging.Agent
import Simplex.Messaging.Agent.Protocol (AgentErrorType (RCP))
import Simplex.Messaging.Crypto.File (CryptoFile (..), CryptoFileArgs (..))
import qualified Simplex.Messaging.Crypto.File as CF
import qualified Simplex.Messaging.Encoding.Base64.URL as B64U
import Simplex.Messaging.Encoding.String (StrEncoding (..))
import qualified Simplex.Messaging.TMap as TM
import Simplex.Messaging.Transport (TLS, closeConnection, tlsUniq)
@@ -353,7 +353,7 @@ storeRemoteFile rhId encrypted_ localPath = do
createDirectoryIfMissing True tmpDir
tmpFile <- liftIO $ tmpDir `uniqueCombine` takeFileName localPath
cfArgs <- atomically . CF.randomArgs =<< asks random
liftError (ChatError . CEFileWrite tmpFile) $ encryptFile localPath tmpFile cfArgs
liftEither =<< liftIO (runExceptT $ withExceptT (ChatError . CEFileWrite tmpFile) $ encryptFile localPath tmpFile cfArgs)
pure $ CryptoFile tmpFile $ Just cfArgs
getRemoteFile :: RemoteHostId -> RemoteFile -> CM ()
@@ -493,14 +493,14 @@ parseCtrlAppInfo :: JT.Value -> CM CtrlAppInfo
parseCtrlAppInfo ctrlAppInfo = do
liftEitherWith (const $ ChatErrorRemoteCtrl RCEBadInvitation) $ JT.parseEither J.parseJSON ctrlAppInfo
handleRemoteCommand :: (ByteString -> CM' ChatResponse) -> RemoteCrypto -> TBQueue ChatResponse -> HTTP2Request -> CM' ()
handleRemoteCommand :: (ByteString -> CM' ChatResponse) -> RemoteCrypto -> TBQueue ChatResponse -> HTTP2Request -> CM ()
handleRemoteCommand execChatCommand encryption remoteOutputQ HTTP2Request {request, reqBody, sendResponse} = do
logDebug "handleRemoteCommand"
liftIO (tryRemoteError' parseRequest) >>= \case
liftRC (tryRemoteError parseRequest) >>= \case
Right (getNext, rc) -> do
chatReadVar' currentUser >>= \case
chatReadVar currentUser >>= \case
Nothing -> replyError $ ChatError CENoActiveUser
Just user -> processCommand user getNext rc `catchChatError'` replyError
Just user -> processCommand user getNext rc `catchChatError` replyError
Left e -> reply $ RRProtocolError e
where
parseRequest :: ExceptT RemoteProtocolError IO (GetChunk, RemoteCommand)
@@ -510,20 +510,19 @@ handleRemoteCommand execChatCommand encryption remoteOutputQ HTTP2Request {reque
replyError = reply . RRChatResponse . CRChatCmdError Nothing
processCommand :: User -> GetChunk -> RemoteCommand -> CM ()
processCommand user getNext = \case
RCSend {command} -> lift $ handleSend execChatCommand command >>= reply
RCRecv {wait = time} -> lift $ liftIO (handleRecv time remoteOutputQ) >>= reply
RCStoreFile {fileName, fileSize, fileDigest} -> lift $ handleStoreFile encryption fileName fileSize fileDigest getNext >>= reply
RCSend {command} -> lift (handleSend execChatCommand command) >>= reply
RCRecv {wait = time} -> liftIO (handleRecv time remoteOutputQ) >>= reply
RCStoreFile {fileName, fileSize, fileDigest} -> lift (handleStoreFile encryption fileName fileSize fileDigest getNext) >>= reply
RCGetFile {file} -> handleGetFile encryption user file replyWith
reply :: RemoteResponse -> CM' ()
reply :: RemoteResponse -> CM ()
reply = (`replyWith` \_ -> pure ())
replyWith :: Respond
replyWith rr attach =
liftIO (tryRemoteError' . encryptEncodeHTTP2Body encryption $ J.encode rr) >>= \case
Right resp -> liftIO . sendResponse . responseStreaming N.status200 [] $ \send flush -> do
send resp
attach send
flush
Left e -> toView' . CRChatError Nothing . ChatErrorRemoteCtrl $ RCEProtocolError e
replyWith rr attach = do
resp <- liftRC $ encryptEncodeHTTP2Body encryption $ J.encode rr
liftIO . sendResponse . responseStreaming N.status200 [] $ \send flush -> do
send resp
attach send
flush
takeRCStep :: RCStepTMVar a -> CM a
takeRCStep = liftError' (\e -> ChatErrorAgent {agentError = RCP e, connectionEntity_ = Nothing}) . atomically . takeTMVar
@@ -532,7 +531,7 @@ type GetChunk = Int -> IO ByteString
type SendChunk = Builder -> IO ()
type Respond = RemoteResponse -> (SendChunk -> IO ()) -> CM' ()
type Respond = RemoteResponse -> (SendChunk -> IO ()) -> CM ()
liftRC :: ExceptT RemoteProtocolError IO a -> CM a
liftRC = liftError (ChatErrorRemoteCtrl . RCEProtocolError)
@@ -550,7 +549,7 @@ handleSend execChatCommand command = do
logDebug $ "Send: " <> tshow command
-- execChatCommand checks for remote-allowed commands
-- convert errors thrown in execChatCommand into error responses to prevent aborting the protocol wrapper
RRChatResponse <$> execChatCommand (encodeUtf8 command)
RRChatResponse <$> lift (execChatCommand $ encodeUtf8 command) `catchChatError'` (pure . CRChatError Nothing)
handleRecv :: Int -> TBQueue ChatResponse -> IO RemoteResponse
handleRecv time events = do
@@ -582,11 +581,11 @@ handleGetFile encryption User {userId} RemoteFile {userId = commandUserId, fileI
cf <- getLocalCryptoFile db commandUserId fileId sent
unless (cf == cf') $ throwError $ SEFileNotFound fileId
liftRC (tryRemoteError $ getFileInfo path) >>= \case
Left e -> lift $ reply (RRProtocolError e) $ \_ -> pure ()
Left e -> reply (RRProtocolError e) $ \_ -> pure ()
Right (fileSize, fileDigest) ->
ExceptT . withFile path ReadMode $ \h -> runExceptT $ do
withFile path ReadMode $ \h -> do
encFile <- liftRC $ prepareEncryptedFile encryption (h, fileSize)
lift $ reply RRFile {fileSize, fileDigest} $ sendEncryptedFile encFile
reply RRFile {fileSize, fileDigest} $ sendEncryptedFile encFile
listRemoteCtrls :: CM [RemoteCtrlInfo]
listRemoteCtrls = do
@@ -624,8 +623,7 @@ verifyRemoteCtrlSession execChatCommand sessCode' = do
rc@RemoteCtrl {remoteCtrlId} <- upsertRemoteCtrl ctrlName rcCtrlPairing
remoteOutputQ <- asks (tbqSize . config) >>= newTBQueueIO
encryption <- mkCtrlRemoteCrypto sessionKeys $ tlsUniq tls
cc <- ask
http2Server <- liftIO . async $ attachHTTP2Server tls $ \req -> handleRemoteCommand execChatCommand encryption remoteOutputQ req `runReaderT` cc
http2Server <- async $ attachHTTP2Server tls $ handleRemoteCommand execChatCommand encryption remoteOutputQ
void . forkIO $ monitor sseq http2Server
updateRemoteCtrlSession sseq $ \case
RCSessionPendingConfirmation {} -> Right RCSessionConnected {remoteCtrlId, rcsClient = client, rcsSession, tls, http2Server, remoteOutputQ}
+7 -5
View File
@@ -13,17 +13,19 @@ import Simplex.Messaging.Transport.HTTP2 (defaultHTTP2BufferSize, getHTTP2Body)
import Simplex.Messaging.Transport.HTTP2.Client (HTTP2Client, HTTP2ClientError (..), attachHTTP2Client, bodyHeadSize, connTimeout, defaultHTTP2ClientConfig)
import Simplex.Messaging.Transport.HTTP2.Server (HTTP2Request (..), runHTTP2ServerWith)
import Simplex.RemoteControl.Discovery
import UnliftIO
attachRevHTTP2Client :: IO () -> TLS -> IO (Either HTTP2ClientError HTTP2Client)
attachRevHTTP2Client disconnected = attachHTTP2Client config ANY_ADDR_V4 "0" disconnected defaultHTTP2BufferSize
where
config = defaultHTTP2ClientConfig {bodyHeadSize = doNotPrefetchHead, connTimeout = maxBound}
attachHTTP2Server :: TLS -> (HTTP2Request -> IO ()) -> IO ()
attachHTTP2Server tls processRequest =
runHTTP2ServerWith defaultHTTP2BufferSize ($ tls) $ \sessionId r sendResponse -> do
reqBody <- getHTTP2Body r doNotPrefetchHead
processRequest HTTP2Request {sessionId, request = r, reqBody, sendResponse}
attachHTTP2Server :: MonadUnliftIO m => TLS -> (HTTP2Request -> m ()) -> m ()
attachHTTP2Server tls processRequest = do
withRunInIO $ \unlift ->
runHTTP2ServerWith defaultHTTP2BufferSize ($ tls) $ \sessionId r sendResponse -> do
reqBody <- getHTTP2Body r doNotPrefetchHead
unlift $ processRequest HTTP2Request {sessionId, request = r, reqBody, sendResponse}
-- | Suppress storing initial chunk in bodyHead, forcing clients and servers to stream chunks
doNotPrefetchHead :: Int
+1 -1
View File
@@ -18,7 +18,6 @@ import Control.Monad.Except
import Control.Monad.IO.Class
import Crypto.Random (ChaChaDRG)
import qualified Data.Aeson.TH as J
import qualified Data.ByteString.Base64 as B64
import Data.ByteString.Char8 (ByteString)
import Data.Int (Int64)
import Data.Maybe (fromMaybe, isJust, listToMaybe)
@@ -39,6 +38,7 @@ import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB
import qualified Simplex.Messaging.Crypto as C
import Simplex.Messaging.Crypto.Ratchet (PQEncryption (..), PQSupport (..))
import qualified Simplex.Messaging.Crypto.Ratchet as CR
import qualified Simplex.Messaging.Encoding.Base64 as B64
import Simplex.Messaging.Parsers (dropPrefix, sumTypeJSON)
import Simplex.Messaging.Protocol (SubscriptionMode (..))
import Simplex.Messaging.Util (allFinally)
+1 -1
View File
@@ -14,7 +14,6 @@ import Control.Concurrent.STM
import Control.Monad (unless, when)
import Control.Monad.Except (runExceptT)
import Data.ByteString (ByteString)
import qualified Data.ByteString.Base64 as B64
import qualified Data.ByteString.Char8 as B
import Data.Char (isDigit)
import Data.List (isPrefixOf, isSuffixOf)
@@ -35,6 +34,7 @@ import Simplex.Messaging.Agent.Store.SQLite (maybeFirstRow, withTransaction)
import qualified Simplex.Messaging.Agent.Store.SQLite.DB as DB
import qualified Simplex.Messaging.Crypto as C
import Simplex.Messaging.Crypto.Ratchet (PQEncryption (..), PQSupport, pattern PQEncOff, pattern PQEncOn, pattern PQSupportOff)
import qualified Simplex.Messaging.Encoding.Base64 as B64
import Simplex.Messaging.Encoding.String
import Simplex.Messaging.Version
import System.Directory (doesFileExist)
+3 -3
View File
@@ -4,12 +4,12 @@ module WebRTCTests where
import Control.Monad.Except
import Crypto.Random (getRandomBytes)
import qualified Data.ByteString.Base64.URL as U
import qualified Data.ByteString.Char8 as B
import Foreign.StablePtr
import Simplex.Chat.Mobile
import Simplex.Chat.Mobile.WebRTC
import qualified Simplex.Messaging.Crypto as C
import qualified Simplex.Messaging.Encoding.Base64.URL as U
import System.FilePath ((</>))
import Test.Hspec
@@ -36,8 +36,8 @@ webRTCTests = describe "WebRTC crypto" $ do
cc <- newStablePtr c
let key = B.replicate 32 '#'
frame <- (<> B.replicate reservedSize '\NUL') <$> getRandomBytes 100
runExceptT (chatEncryptMedia cc key frame) `shouldReturn` Left "invalid key: invalid character at offset: 0"
runExceptT (chatDecryptMedia key frame) `shouldReturn` Left "invalid key: invalid character at offset: 0"
runExceptT (chatEncryptMedia cc key frame) `shouldReturn` Left "invalid key: invalid base64 encoding near offset: 0"
runExceptT (chatDecryptMedia key frame) `shouldReturn` Left "invalid key: invalid base64 encoding near offset: 0"
it "should fail on invalid auth tag" $ \tmp -> do
Right c <- chatMigrateInit (tmp </> "1") "" "yesUp"
cc <- newStablePtr c