Compare commits
96 Commits
indexedack
...
trunk
Author | SHA1 | Date |
---|---|---|
Dan Ballard | 3964348dd0 | |
Sarah Jamie Lewis | ae16c7c6a5 | |
Sarah Jamie Lewis | 69f14f9bb1 | |
erinn | f1775eb975 | |
erinn | c1b7e4c75d | |
Sarah Jamie Lewis | a460b900b6 | |
Sarah Jamie Lewis | b2d8f3f34a | |
Sarah Jamie Lewis | 6c5b48311d | |
Sarah Jamie Lewis | b33c6c77dd | |
Sarah Jamie Lewis | c864bccbb9 | |
erinn | 5dddb16f2b | |
erinn | 001470257a | |
Sarah Jamie Lewis | b37f283fe3 | |
Dan Ballard | 2f495dfd62 | |
erinn | e09e9c09a7 | |
erinn | ae3aef0518 | |
Sarah Jamie Lewis | 0f53ae0062 | |
Sarah Jamie Lewis | f6eaa2d691 | |
Sarah Jamie Lewis | 8f1b1b8630 | |
Dan Ballard | e2cf1d25e3 | |
Dan Ballard | 7b3ff2c1af | |
Sarah Jamie Lewis | c6f1c4d0f9 | |
erinn | e7ef2fef4a | |
erinn | ffaca8d876 | |
Sarah Jamie Lewis | 6070d378c5 | |
Sarah Jamie Lewis | fafdb8132a | |
Sarah Jamie Lewis | 9a764b5b35 | |
Dan Ballard | 3261d18118 | |
Sarah Jamie Lewis | 08b1b19f7a | |
erinn | 204cc35e0d | |
erinn | 28011ae674 | |
erinn | eb4150c0be | |
erinn | d9f9489fa2 | |
erinn | 854dc1946f | |
Sarah Jamie Lewis | 26b0151e79 | |
Sarah Jamie Lewis | abe06912a1 | |
Dan Ballard | 11f09c95d2 | |
Dan Ballard | 9b18bef47a | |
Sarah Jamie Lewis | c5f36a9480 | |
Dan Ballard | 192d98a89b | |
Dan Ballard | 00c5412551 | |
Dan Ballard | d921612d25 | |
erinn | 39187a7db7 | |
erinn | 6fabfa507d | |
Sarah Jamie Lewis | 6560fcef49 | |
Sarah Jamie Lewis | 033de73b6a | |
erinn | 370e6090ce | |
erinn | 61d078f645 | |
erinn | af4d994d6a | |
erinn | 78a2e033dc | |
Dan Ballard | fddfd41fbf | |
Sarah Jamie Lewis | 936c45f234 | |
Dan Ballard | 08fe76bf30 | |
Sarah Jamie Lewis | 2b86f7b282 | |
Dan Ballard | 33945af046 | |
Sarah Jamie Lewis | 9b1814e43d | |
Sarah Jamie Lewis | 4dd8d74bfb | |
Sarah Jamie Lewis | 772cf7949a | |
Dan Ballard | 62a55a6fec | |
erinn | 6a0e839bb6 | |
Sarah Jamie Lewis | 53d11dc45d | |
Sarah Jamie Lewis | ee47798714 | |
Sarah Jamie Lewis | 6f01c992af | |
Dan Ballard | 4f625c7f8e | |
Sarah Jamie Lewis | ed868c140b | |
erinn | a98b5deb02 | |
Sarah Jamie Lewis | af338e7e95 | |
Sarah Jamie Lewis | 1787f87607 | |
Dan Ballard | 47f8cf2f42 | |
Sarah Jamie Lewis | b4681241bc | |
Sarah Jamie Lewis | 30490f7b9d | |
Sarah Jamie Lewis | 406b3510b8 | |
erinn | 84d85b7694 | |
Sarah Jamie Lewis | c9d589a27a | |
Sarah Jamie Lewis | 66d7c63c08 | |
erinn | 83c3ad21c3 | |
erinn | 299595180b | |
Sarah Jamie Lewis | dd0fc13b89 | |
erinn | 2788c068dd | |
Sarah Jamie Lewis | 2c76504e0b | |
Sarah Jamie Lewis | bef54c6091 | |
erinn | 54c2048f58 | |
erinn | 33c42f32d2 | |
erinn | a1095b7c35 | |
Sarah Jamie Lewis | 62db995842 | |
erinn | f6d4708501 | |
erinn | dbf12007c7 | |
Sarah Jamie Lewis | 8a67b88f2e | |
erinn | 7ad9c25b19 | |
erinn | f4ea408b7b | |
Sarah Jamie Lewis | c1121f13a1 | |
erinn | df414ed23f | |
Sarah Jamie Lewis | 699d249ad7 | |
Sarah Jamie Lewis | c2e3488a45 | |
Sarah Jamie Lewis | 4df9a22075 | |
Sarah Jamie Lewis | 8f493b8fbb |
|
@ -0,0 +1,5 @@
|
|||
package constants
|
||||
|
||||
// We offer "un-passworded" profiles but our storage encrypts everything with a password. We need an agreed upon
|
||||
// password to use in that case, that the app case use behind the scenes to password and unlock with
|
||||
const DefactoPasswordForUnencryptedProfiles = "be gay do crime"
|
|
@ -47,19 +47,16 @@ func ExperimentGate(experimentMap map[string]bool) (*GroupFunctionality, error)
|
|||
}
|
||||
|
||||
// SendMessage is a deprecated api
|
||||
func (gf *GroupFunctionality) SendMessage(peer peer.CwtchPeer, handle string, message string) error {
|
||||
func (gf *GroupFunctionality) SendMessage(peer peer.CwtchPeer, handle string, message string) (string, error) {
|
||||
// TODO this auto accepting behaviour needs some thinking through
|
||||
if !peer.GetGroup(handle).Accepted {
|
||||
err := peer.AcceptInvite(handle)
|
||||
if err != nil {
|
||||
log.Errorf("tried to mark a nonexistent group as existed. bad!")
|
||||
return err
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
_, err := peer.SendMessageToGroupTracked(handle, message)
|
||||
|
||||
return err
|
||||
return peer.SendMessageToGroupTracked(handle, message)
|
||||
}
|
||||
|
||||
// ValidPrefix returns true if an import string contains a prefix that indicates it contains information about a
|
||||
|
@ -94,13 +91,12 @@ func (gf *GroupFunctionality) GetServerInfo(serverOnion string, profile peer.Rea
|
|||
|
||||
// HandleImportString handles import strings for groups and servers
|
||||
func (gf *GroupFunctionality) HandleImportString(peer peer.CwtchPeer, importString string) error {
|
||||
|
||||
if strings.HasPrefix(importString, tofuBundlePrefix) {
|
||||
bundle := strings.Split(importString, "||")
|
||||
if len(bundle) == 2 {
|
||||
err := gf.HandleImportString(peer, bundle[0][len(tofuBundlePrefix):])
|
||||
// if the server import failed then abort the whole process..
|
||||
if strings.HasSuffix(err.Error(), "success") == false {
|
||||
if !strings.HasSuffix(err.Error(), "success") {
|
||||
return features.ConstructResponse(importBundlePrefix, err.Error())
|
||||
}
|
||||
return gf.HandleImportString(peer, bundle[1])
|
||||
|
@ -117,10 +113,15 @@ func (gf *GroupFunctionality) HandleImportString(peer peer.CwtchPeer, importStri
|
|||
return features.ConstructResponse(importBundlePrefix, err.Error())
|
||||
} else if strings.HasPrefix(importString, groupPrefix) {
|
||||
//eg: torv3JFDWkXExBsZLkjvfkkuAxHsiLGZBk0bvoeJID9ItYnU=EsEBCiBhOWJhZDU1OTQ0NWI3YmM2N2YxYTM5YjkzMTNmNTczNRIgpHeNaG+6jy750eDhwLO39UX4f2xs0irK/M3P6mDSYQIaOTJjM2ttb29ibnlnaGoyenc2cHd2N2Q1N3l6bGQ3NTNhdW8zdWdhdWV6enB2ZmFrM2FoYzRiZHlkCiJAdVSSVgsksceIfHe41OJu9ZFHO8Kwv3G6F5OK3Hw4qZ6hn6SiZjtmJlJezoBH0voZlCahOU7jCOg+dsENndZxAA==
|
||||
if err := peer.ImportGroup(importString); err != nil {
|
||||
if gid, err := peer.ImportGroup(importString); err != nil {
|
||||
return features.ConstructResponse(importBundlePrefix, err.Error())
|
||||
} else {
|
||||
// Auto accept the group here.
|
||||
if peer.AcceptInvite(gid) != nil {
|
||||
log.Errorf("Error accepting invite: %v", err)
|
||||
}
|
||||
return features.ConstructResponse(importBundlePrefix, "success")
|
||||
}
|
||||
}
|
||||
return features.ConstructResponse(importBundlePrefix, "invalid_group_invite_prefix")
|
||||
}
|
||||
|
|
6
go.mod
6
go.mod
|
@ -3,8 +3,8 @@ module git.openprivacy.ca/flutter/libcwtch-go
|
|||
go 1.15
|
||||
|
||||
require (
|
||||
cwtch.im/cwtch v0.6.10
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.4.2
|
||||
cwtch.im/cwtch v0.8.11
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.4.4
|
||||
git.openprivacy.ca/openprivacy/log v1.0.2
|
||||
golang.org/x/mobile v0.0.0-20210220033013-bdb1ca9a1e08 // indirect
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 // indirect
|
||||
)
|
||||
|
|
121
go.sum
121
go.sum
|
@ -1,68 +1,21 @@
|
|||
cwtch.im/cwtch v0.5.1 h1:84foD/HBebPbA4gUEwp+feakeHkD3Di53Q3FnSbqDMM=
|
||||
cwtch.im/cwtch v0.5.1/go.mod h1:snHZIZwRQPAZG2LRZsN5SpAIbeR597VJoDS+KHm7q9w=
|
||||
cwtch.im/cwtch v0.6.0 h1:LaIRs8dDtnSr/MVFX3giTxnYwSyAIu0w55eZWWO7VZI=
|
||||
cwtch.im/cwtch v0.6.0/go.mod h1:snHZIZwRQPAZG2LRZsN5SpAIbeR597VJoDS+KHm7q9w=
|
||||
cwtch.im/cwtch v0.6.1 h1:NqfLPS7k3rRi5A0qf/tHoq42BEc/K89LHgZqsBs7Luk=
|
||||
cwtch.im/cwtch v0.6.1/go.mod h1:snHZIZwRQPAZG2LRZsN5SpAIbeR597VJoDS+KHm7q9w=
|
||||
cwtch.im/cwtch v0.6.2 h1:UqwVnxNXvhhG7yGpcY9aXyq0dy31XzjV708BWCHHIms=
|
||||
cwtch.im/cwtch v0.6.2/go.mod h1:snHZIZwRQPAZG2LRZsN5SpAIbeR597VJoDS+KHm7q9w=
|
||||
cwtch.im/cwtch v0.6.3 h1:AifcbxK60UTeOiOt0ur8PLQeDCuljQLhLqrAOO/8guA=
|
||||
cwtch.im/cwtch v0.6.3/go.mod h1:snHZIZwRQPAZG2LRZsN5SpAIbeR597VJoDS+KHm7q9w=
|
||||
cwtch.im/cwtch v0.6.4 h1:7P7+c7pBw2/aGE1cVWWLlLWhkVrGwuhQomIRbWB840E=
|
||||
cwtch.im/cwtch v0.6.4/go.mod h1:snHZIZwRQPAZG2LRZsN5SpAIbeR597VJoDS+KHm7q9w=
|
||||
cwtch.im/cwtch v0.6.5 h1:s2sTn7rmHzAEGYje/oWv2AvM58++x7WNauC9GxyTtho=
|
||||
cwtch.im/cwtch v0.6.5/go.mod h1:YnNbfZlOhEWXEEZvWpWr1G+KhuwODZkSSmdqg2/8lOI=
|
||||
cwtch.im/cwtch v0.6.6 h1:GlEoAYfastcimhYsctLSbqql0RNz9t1jphAxTcCvu0M=
|
||||
cwtch.im/cwtch v0.6.6/go.mod h1:KDy4lWWxcYAjeKclwVFkoTQ2dWnZcM0k3Xck+zEuBmE=
|
||||
cwtch.im/cwtch v0.6.7 h1:HerkAptEtiDNeaeebgcOHAbkqpGnHo8mbmBtbgjc8PU=
|
||||
cwtch.im/cwtch v0.6.7/go.mod h1:KDy4lWWxcYAjeKclwVFkoTQ2dWnZcM0k3Xck+zEuBmE=
|
||||
cwtch.im/cwtch v0.6.8 h1:xwPrhqwc9S2+XIEPVL1JDrfJ0Ct7AtW5+K46g+mymdc=
|
||||
cwtch.im/cwtch v0.6.8/go.mod h1:KDy4lWWxcYAjeKclwVFkoTQ2dWnZcM0k3Xck+zEuBmE=
|
||||
cwtch.im/cwtch v0.6.9 h1:R4UgKd8ucw8qGZ0K0RrYB+tZrgCXJ83HsH/MrNfsqps=
|
||||
cwtch.im/cwtch v0.6.9/go.mod h1:KDy4lWWxcYAjeKclwVFkoTQ2dWnZcM0k3Xck+zEuBmE=
|
||||
cwtch.im/cwtch v0.6.10 h1:5w9G3HXBLIFE1Jrn2tQ+Alc8+td3ty5bWOOq4xeTXXk=
|
||||
cwtch.im/cwtch v0.6.10/go.mod h1:KDy4lWWxcYAjeKclwVFkoTQ2dWnZcM0k3Xck+zEuBmE=
|
||||
cwtch.im/tapir v0.2.1 h1:t1YJB9q5sV1A9xwiiwL6WVfw3dwQWLoecunuzT1PQtw=
|
||||
cwtch.im/tapir v0.2.1/go.mod h1:xzzZ28adyUXNkYL1YodcHsAiTt3IJ8Loc29YVn9mIEQ=
|
||||
git.openprivacy.ca/cwtch.im/tapir v0.3.2 h1:thLWqqY1LkirWFcy9Tg6NgWeYbvo9xBm+s2XVnCIvpY=
|
||||
git.openprivacy.ca/cwtch.im/tapir v0.3.2/go.mod h1:q6RMI/TQvRN8SCtRY3GryOawMcB0uG6NjP6M77oSMx8=
|
||||
git.openprivacy.ca/cwtch.im/tapir v0.3.3 h1:Q7F8JijgOMMYSy3IdZl7+r6qkWckEWV1+EY7q6MAkVs=
|
||||
git.openprivacy.ca/cwtch.im/tapir v0.3.3/go.mod h1:ZMg9Jzh0n3Os2aSF4z+bx/n8WBCJBN7KCQESXperYts=
|
||||
git.openprivacy.ca/cwtch.im/tapir v0.3.4 h1:g7yZkfz/vWr/t2tFXa/t0Ebr/w665uIKpxpCZ3lIPCo=
|
||||
git.openprivacy.ca/cwtch.im/tapir v0.3.4/go.mod h1:+Niy2AHhQC351ZTtfhC0uLjViCICyOxCJZsIlGKKNAU=
|
||||
cwtch.im/cwtch v0.8.11 h1:nUrd6srjLxInSJ0q1JdmRBhN4RRlZRL+2vIyE/AXkfY=
|
||||
cwtch.im/cwtch v0.8.11/go.mod h1:D9dtO+WnKqdmufKSfFeFlUYaxLTfE/RtqVe1OD0kiKc=
|
||||
git.openprivacy.ca/cwtch.im/tapir v0.4.3 h1:sctSfUXHDIqaHfJPDl+5lHtmoEJolQiHTcHZGAe5Qc4=
|
||||
git.openprivacy.ca/cwtch.im/tapir v0.4.3/go.mod h1:10qEaib5x021zgyZ/97JKWsEpedH5+Vfy2CvB2V+08E=
|
||||
git.openprivacy.ca/openprivacy/bine v0.0.4 h1:CO7EkGyz+jegZ4ap8g5NWRuDHA/56KKvGySR6OBPW+c=
|
||||
git.openprivacy.ca/openprivacy/bine v0.0.4/go.mod h1:13ZqhKyqakDsN/ZkQkIGNULsmLyqtXc46XBcnuXm/mU=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.2.0/go.mod h1:B7vzuVmChJtSKoh0ezph5vu6DQ0gIk0zHUNG6IgXCcA=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.3.3 h1:OKHZ/pzY95+UNOhF74DisSYPh7lULtjbxFQnK9r6cAk=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.3.3/go.mod h1:DL9QitHjpyNspMUe3wjIej9gFgDK2FdRKP2JE4+7T90=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.4.0 h1:c7AANUCrlA4hIqXxIGDOWMtSe8CpDleD1877PShScbM=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.4.0/go.mod h1:bR0Myx9nm2YzWtsThRelkNMV4Pp7sPDa123O1qsAbVo=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.4.1 h1:zoM+j7PFj8mQeUCNiDNMe7Uq9dhcJDOhaZcSANfeDL4=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.4.1/go.mod h1:bR0Myx9nm2YzWtsThRelkNMV4Pp7sPDa123O1qsAbVo=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.4.2 h1:rQFIjWunLlRmXL5Efsv+7+1cA70T6Uza6RCy2PRm9zc=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.4.2/go.mod h1:bR0Myx9nm2YzWtsThRelkNMV4Pp7sPDa123O1qsAbVo=
|
||||
git.openprivacy.ca/openprivacy/log v1.0.0/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
|
||||
git.openprivacy.ca/openprivacy/log v1.0.1/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.4.4 h1:11M3akVCyy/luuhMpZTM1r9Jayl7IHD944Bxsn2FDpU=
|
||||
git.openprivacy.ca/openprivacy/connectivity v1.4.4/go.mod h1:JVRCIdL+lAG6ohBFWiKeC/MN42nnC0sfFszR9XG6vPQ=
|
||||
git.openprivacy.ca/openprivacy/log v1.0.2 h1:HLP4wsw4ljczFAelYnbObIs821z+jgMPCe8uODPnGQM=
|
||||
git.openprivacy.ca/openprivacy/log v1.0.2/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802 h1:1BDTz0u9nC3//pOCMdNH+CiXJVYJh5UQNCOBG7jbELc=
|
||||
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cretz/bine v0.1.1-0.20200124154328-f9f678b84cca/go.mod h1:6PF6fWAvYtwjRGkAuDEJeWNOv3a2hUouSP/yRYXmvHw=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20190411002643-bd77b112433e/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/gordonklaus/ineffassign v0.0.0-20200309095847-7953dde2c7bf/go.mod h1:cuNKsD1zp2v6XfE/orVX2QE1LC+i254ceGcVeDT3pTU=
|
||||
github.com/gtank/merlin v0.1.1 h1:eQ90iG7K9pOhtereWsmyRJ6RAwcP4tHTDBHXNg+u5is=
|
||||
github.com/gtank/merlin v0.1.1/go.mod h1:T86dnYJhcGOh5BjZFCJWTDeTK7XW8uE+E21Cy/bIQ+s=
|
||||
github.com/gtank/ristretto255 v0.1.2 h1:JEqUCPA1NvLq5DwYtuzigd7ss8fwbYay9fi4/5uMzcc=
|
||||
github.com/gtank/ristretto255 v0.1.2/go.mod h1:Ph5OpO6c7xKUGROZfWVLiJf9icMDwUeIvY4OmlYW69o=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.2.0 h1:s5hAObm+yFO5uHYt5dYjxi2rXrsnmRpJx4OYvIWUaQs=
|
||||
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||
github.com/kr/pty v1.1.1 h1:VkoXIwSboBpnk99O/KFauAEILuNHv5DVFKZMBN/gUgw=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
|
@ -72,94 +25,50 @@ github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWb
|
|||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
|
||||
github.com/stretchr/objx v0.1.0 h1:4G4v2dO3VZwixGIRoQ5Lfboy6nUhCyYzaqnIAPPhYs4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/struCoder/pidusage v0.1.3 h1:pZcSa6asBE38TJtW0Nui6GeCjLTpaT/jAnNP7dUTLSQ=
|
||||
github.com/struCoder/pidusage v0.1.3/go.mod h1:pWBlW3YuSwRl6h7R5KbvA4N8oOqe9LjaKW5CwT1SPjI=
|
||||
github.com/therecipe/qt v0.0.0-20200904063919-c0c124a5770d/go.mod h1:SUUR2j3aE1z6/g76SdD6NwACEpvCxb3fvG82eKbD6us=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.etcd.io/bbolt v1.3.4 h1:hi1bXHMVrlQh6WwxAy+qZCV/SYIlqo+Ushwdpa4tAKg=
|
||||
go.etcd.io/bbolt v1.3.4/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
|
||||
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200204104054-c9f3fb736b72/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200206161412-a0c6ece9d31a/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee h1:4yd7jl+vXjalO5ztz6Vc1VADv+S/80LGJmyl1ROJ2AI=
|
||||
golang.org/x/crypto v0.0.0-20201012173705-84dcc777aaee/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56 h1:estk1glOnSVeJ9tdEZZc5mAMDZk5lNJNyJ6DvrBkTEU=
|
||||
golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4=
|
||||
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b h1:+qEpEAPhDZ1o0x3tHzZTQDArnOixOzGD9HUJfcg0mb4=
|
||||
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
|
||||
golang.org/x/mobile v0.0.0-20210220033013-bdb1ca9a1e08 h1:h+GZ3ubjuWaQjGe8owMGcmMVCqs0xYJtRG5y2bpHaqU=
|
||||
golang.org/x/mobile v0.0.0-20210220033013-bdb1ca9a1e08/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4=
|
||||
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
|
||||
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
|
||||
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd h1:ePuNC7PZ6O5BzgPn9bZayERXBdfZjUYoXEf5BTfDfh8=
|
||||
golang.org/x/mod v0.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.2.0 h1:KU7oHjnv3XNWfa5COkzUifxZmxp1TyI7ImMXqFxLwvQ=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190420063019-afa5a82059c6/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb h1:mUVeFHoDKis5nxCAzoAi7E8Ghb86EXh/RK6wtvJIqRY=
|
||||
golang.org/x/net v0.0.0-20201010224723-4f7140c49acb/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58 h1:8gQV6CLnAEikrhgkHFbMAEhagSSnXWGV915qUMm9mrU=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190419153524-e8e3143a4f4a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f h1:+Nyd8tzPX9R7BWHguqsrbFdRx3WQ/1ib8I44HXV5yTA=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44 h1:Bli41pIlzTzf3KEY06n+xnzK/BESIg2ze4Pgfh/aI8c=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1 h1:v+OssWQX+hTHEmOBgwxdZxK4zHq3yOs8F9J7mk0PY8E=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22 h1:RqytpXGR1iVNX7psjB3ff8y7sNFinVFvkx1c8SjBkio=
|
||||
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3 h1:cokOdA+Jmi5PJGXLlLllQSgYigAEfHXJAERHVMaCc2k=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190420181800-aa740d480789/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69 h1:yBHHx+XZqXJBm6Exke3N7V9gnlsyXxoCPEb1yVenjfk=
|
||||
golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
|
||||
golang.org/x/tools v0.0.0-20200625195345-7480c7b4547d h1:V1BGE5ZHrUIYZYNEm0i7jrPwSo3ks0HSn1TrartSqME=
|
||||
golang.org/x/tools v0.0.0-20200625195345-7480c7b4547d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898 h1:/atklqdjdhuosWIl6AIbOeHJjicWYPqR9bpxqxYG2pA=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
|
||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
|
395
lib.go
395
lib.go
|
@ -10,14 +10,16 @@ import (
|
|||
"cwtch.im/cwtch/model"
|
||||
"cwtch.im/cwtch/model/attr"
|
||||
"cwtch.im/cwtch/peer"
|
||||
contact "git.openprivacy.ca/flutter/libcwtch-go/features/contacts"
|
||||
"git.openprivacy.ca/flutter/libcwtch-go/features/groups"
|
||||
"git.openprivacy.ca/openprivacy/connectivity"
|
||||
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"git.openprivacy.ca/flutter/libcwtch-go/constants"
|
||||
contact "git.openprivacy.ca/flutter/libcwtch-go/features/contacts"
|
||||
"git.openprivacy.ca/flutter/libcwtch-go/features/groups"
|
||||
"git.openprivacy.ca/flutter/libcwtch-go/utils"
|
||||
"git.openprivacy.ca/openprivacy/connectivity"
|
||||
"runtime"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"encoding/base64"
|
||||
"git.openprivacy.ca/openprivacy/connectivity/tor"
|
||||
|
@ -41,22 +43,66 @@ var acnQueue event.Queue
|
|||
var contactEventsQueue event.Queue
|
||||
var globalACN connectivity.ACN
|
||||
|
||||
//export c_StartCwtch
|
||||
func c_StartCwtch(dir_c *C.char, len C.int, tor_c *C.char, torLen C.int) {
|
||||
dir := C.GoStringN(dir_c, len)
|
||||
tor := C.GoStringN(tor_c, torLen)
|
||||
StartCwtch(dir, tor)
|
||||
// ChatMessage API currently not officially documented, see
|
||||
// https://git.openprivacy.ca/cwtch.im/secure-development-handbook/issues/3
|
||||
// for latest updates for now
|
||||
//
|
||||
// A ChatMessage is the application-layer Cwtch message, delivered to the UI
|
||||
// as serialized json.
|
||||
type ChatMessage struct {
|
||||
O int `json:"o"`
|
||||
D string `json:"d"`
|
||||
}
|
||||
|
||||
func StartCwtch(appDir string, torPath string) {
|
||||
//export c_StartCwtch
|
||||
func c_StartCwtch(dir_c *C.char, len C.int, tor_c *C.char, torLen C.int) int8 {
|
||||
dir := C.GoStringN(dir_c, len)
|
||||
tor := C.GoStringN(tor_c, torLen)
|
||||
return int8(StartCwtch(dir, tor))
|
||||
}
|
||||
|
||||
// StartCwtch starts cwtch in the library and initlaizes all data structures
|
||||
// GetAppbusEvents is always safe to use
|
||||
// the rest of functions are unsafe until the CwtchStarted event has been received indicating StartCwtch has completed
|
||||
// returns:
|
||||
// message: CwtchStarted when start up is complete and app is safe to use
|
||||
// CwtchStartError message when start up fails (includes event.Error data field)
|
||||
func StartCwtch(appDir string, torPath string) int {
|
||||
log.SetLevel(log.LevelInfo)
|
||||
|
||||
// Exclude Tapir wire Messages (We need a TRACE level)
|
||||
|
||||
log.Infof("StartCwtch(...)")
|
||||
// Quick hack check that we're being called with the correct params
|
||||
// On android a stale worker could be calling us with "last apps" directory. Best to abort fast so the app can make a new worker
|
||||
if runtime.GOOS == "android" {
|
||||
fh, err := os.Open(torPath)
|
||||
if err != nil {
|
||||
log.Errorf("%v", err)
|
||||
log.Errorf("failed to stat tor, skipping StartCwtch(). potentially normal if the app was reinstalled or the device was restarted; this workorder should get canceled soon")
|
||||
return 1
|
||||
}
|
||||
_ = fh.Close()
|
||||
}
|
||||
go _startCwtch(appDir, torPath)
|
||||
return 0
|
||||
}
|
||||
|
||||
func _startCwtch(appDir string, torPath string) {
|
||||
log.Infof("application: %v eventHandler: %v acn: %v", application, eventHandler, globalACN)
|
||||
|
||||
if application != nil {
|
||||
log.Infof("_startCwtch detected existing application; resuming instead of relaunching")
|
||||
ReconnectCwtchForeground()
|
||||
return
|
||||
}
|
||||
|
||||
// Exclude Tapir wire Messages
|
||||
//(We need a TRACE level)
|
||||
log.ExcludeFromPattern("service.go")
|
||||
|
||||
// Ensure that the application directory exists...and then initialize settings..
|
||||
os.MkdirAll(path.Join(appDir), 0700)
|
||||
utils.InitGlobalSettingsFile(appDir, "be gay do crime")
|
||||
utils.InitGlobalSettingsFile(appDir, constants.DefactoPasswordForUnencryptedProfiles)
|
||||
|
||||
log.Infof("Loading Cwtch Directory %v and tor path: %v", appDir, torPath)
|
||||
|
||||
|
@ -71,14 +117,18 @@ func StartCwtch(appDir string, torPath string) {
|
|||
panic(err)
|
||||
}
|
||||
|
||||
log.Infof("Creating new EventHandler()")
|
||||
eventHandler = utils.NewEventHandler()
|
||||
|
||||
log.Infof("making directory %v", appDir)
|
||||
os.MkdirAll(path.Join(appDir, "/.tor", "tor"), 0700)
|
||||
tor.NewTorrc().WithSocksPort(port).WithOnionTrafficOnly().WithControlPort(controlPort).WithHashedPassword(base64.StdEncoding.EncodeToString(key)).Build(filepath.Join(appDir, ".tor", "tor", "torrc"))
|
||||
acn, err := tor.NewTorACNWithAuth(path.Join(appDir, "/.tor"), torPath, controlPort, tor.HashedPasswordAuthenticator{Password: base64.StdEncoding.EncodeToString(key)})
|
||||
if err != nil {
|
||||
log.Errorf("\nError connecting to Tor: %v\n", err)
|
||||
log.Errorf("\nError connecting to Tor replacing with ErrorACN: %v\n", err)
|
||||
eventHandler.PublishAppEvent(event.NewEventList(utils.CwtchStartError, event.Error, err))
|
||||
return
|
||||
}
|
||||
//acn.WaitTillBootstrapped()
|
||||
globalACN = acn
|
||||
newApp := app.NewApp(acn, appDir)
|
||||
acnQueue = event.NewQueue()
|
||||
|
@ -87,14 +137,14 @@ func StartCwtch(appDir string, torPath string) {
|
|||
newApp.GetPrimaryBus().Subscribe(utils.SetLoggingLevel, acnQueue)
|
||||
newApp.GetPrimaryBus().Subscribe(event.AppError, acnQueue)
|
||||
|
||||
eventHandler = utils.NewEventHandler(newApp)
|
||||
eventHandler.HandleApp(newApp)
|
||||
|
||||
peer.DefaultEventsToHandle = []event.Type{
|
||||
event.EncryptedGroupMessage,
|
||||
event.NewMessageFromPeer,
|
||||
event.PeerAcknowledgement,
|
||||
event.NewGroupInvite,
|
||||
event.PeerError,
|
||||
event.SendMessageToPeerError,
|
||||
event.SendMessageToGroupError,
|
||||
event.NewGetValMessageFromPeer,
|
||||
event.PeerStateChange,
|
||||
|
@ -102,30 +152,69 @@ func StartCwtch(appDir string, torPath string) {
|
|||
event.NewGroupInvite,
|
||||
event.ServerStateChange,
|
||||
event.ProtocolEngineStopped,
|
||||
event.RetryServerRequest,
|
||||
}
|
||||
settings := utils.ReadGlobalSettings()
|
||||
settingsJson, _ := json.Marshal(settings)
|
||||
|
||||
newApp.LoadProfiles("be gay do crime")
|
||||
newApp.LoadProfiles(constants.DefactoPasswordForUnencryptedProfiles)
|
||||
application = newApp
|
||||
|
||||
// Send global settings to the UI...
|
||||
application.GetPrimaryBus().Publish(event.NewEvent(utils.UpdateGlobalSettings, map[event.Field]string{event.Data: string(settingsJson)}))
|
||||
log.Infof("libcwtch-go application launched")
|
||||
application.GetPrimaryBus().Publish(event.NewEvent(utils.CwtchStarted, map[event.Field]string{}))
|
||||
application.QueryACNVersion()
|
||||
}
|
||||
|
||||
//export c_ACNEvents
|
||||
func c_ACNEvents() *C.char {
|
||||
return C.CString(ACNEvents())
|
||||
//export c_ReconnectCwtchForeground
|
||||
func c_ReconnectCwtchForeground() {
|
||||
ReconnectCwtchForeground()
|
||||
}
|
||||
|
||||
func ACNEvents() string {
|
||||
select {
|
||||
case myevent := <-acnQueue.OutChan():
|
||||
return fmt.Sprintf("%v", myevent)
|
||||
default:
|
||||
return ""
|
||||
// Like StartCwtch, but StartCwtch has already been called so we don't need to restart Tor etc (probably)
|
||||
// Do need to re-send initial state tho, eg profiles that are already loaded
|
||||
func ReconnectCwtchForeground() {
|
||||
log.Infof("Reconnecting cwtchforeground")
|
||||
if application == nil {
|
||||
log.Errorf("ReconnectCwtchForeground: Application is nil, presuming stale thread, EXITING Reconnect\n")
|
||||
return
|
||||
}
|
||||
|
||||
// populate profile list
|
||||
peerList := application.ListPeers()
|
||||
for onion := range peerList {
|
||||
eventHandler.Push(event.NewEvent(event.NewPeer, map[event.Field]string{event.Identity: onion, event.Created: event.False, "Reload": event.True}))
|
||||
}
|
||||
|
||||
for onion := range peerList {
|
||||
// fix peerpeercontact message counts
|
||||
contactList := application.GetPeer(onion).GetContacts()
|
||||
for _, handle := range contactList {
|
||||
totalMessages := application.GetPeer(onion).GetContact(handle).Timeline.Len() + len(application.GetPeer(onion).GetContact(handle).UnacknowledgedMessages)
|
||||
eventHandler.Push(event.NewEvent(event.MessageCounterResync, map[event.Field]string{
|
||||
event.Identity: onion,
|
||||
event.RemotePeer: handle,
|
||||
event.Data: strconv.Itoa(totalMessages),
|
||||
}))
|
||||
}
|
||||
|
||||
// fix peergroupcontact message counts
|
||||
groupList := application.GetPeer(onion).GetGroups()
|
||||
for _, groupID := range groupList {
|
||||
totalMessages := application.GetPeer(onion).GetGroup(groupID).Timeline.Len() + len(application.GetPeer(onion).GetGroup(groupID).UnacknowledgedMessages)
|
||||
eventHandler.Push(event.NewEvent(event.MessageCounterResync, map[event.Field]string{
|
||||
event.Identity: onion,
|
||||
event.GroupID: groupID,
|
||||
event.Data: strconv.Itoa(totalMessages),
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
application.GetPrimaryBus().Publish(event.NewEvent(utils.CwtchStarted, map[event.Field]string{}))
|
||||
application.QueryACNStatus()
|
||||
application.QueryACNVersion()
|
||||
}
|
||||
|
||||
//export c_SendAppEvent
|
||||
|
@ -258,73 +347,38 @@ func c_GetAppBusEvent() *C.char {
|
|||
|
||||
// GetAppBusEvent blocks until an event
|
||||
func GetAppBusEvent() string {
|
||||
log.Debugf("appbusevent called")
|
||||
for eventHandler == nil {
|
||||
log.Debugf("waiting for eventHandler != nil")
|
||||
time.Sleep(time.Second)
|
||||
}
|
||||
|
||||
var json = ""
|
||||
for json == "" {
|
||||
log.Debugf("waiting for json != ''")
|
||||
json = eventHandler.GetNextEvent()
|
||||
}
|
||||
log.Debugf("appbusevent: %v", json)
|
||||
return json
|
||||
}
|
||||
|
||||
//export c_GetProfileRepaintEvent
|
||||
func c_GetProfileRepaintEvent() int8 {
|
||||
if GetProfileRepaintEvent() {
|
||||
return 1
|
||||
} else {
|
||||
return 0
|
||||
}
|
||||
}
|
||||
|
||||
func GetProfileRepaintEvent() bool {
|
||||
<-acnQueue.OutChan()
|
||||
return true
|
||||
}
|
||||
|
||||
type Profile struct {
|
||||
Name string `json:"name"`
|
||||
Onion string `json:"onion"`
|
||||
ImagePath string `json:"imagePath"`
|
||||
}
|
||||
|
||||
//export c_GetProfiles
|
||||
func c_GetProfiles() *C.char {
|
||||
return C.CString(GetProfiles())
|
||||
}
|
||||
|
||||
func GetProfiles() string {
|
||||
peerList := application.ListPeers()
|
||||
profiles := make([]Profile, len(peerList))
|
||||
i := 0
|
||||
for onion := range peerList {
|
||||
name, _ := application.GetPeer(onion).GetAttribute(attr.GetPublicScope(constants.Name))
|
||||
profiles[i] = Profile{
|
||||
Name: name,
|
||||
Onion: onion,
|
||||
ImagePath: "",
|
||||
}
|
||||
i += 1
|
||||
}
|
||||
jsonBytes, _ := json.Marshal(profiles)
|
||||
return string(jsonBytes)
|
||||
}
|
||||
|
||||
//export c_CreateProfile
|
||||
func c_CreateProfile(nick_ptr *C.char, nick_len C.int, pass_ptr *C.char, pass_len C.int) {
|
||||
CreateProfile(C.GoStringN(nick_ptr, nick_len), C.GoStringN(pass_ptr, pass_len))
|
||||
}
|
||||
|
||||
func CreateProfile(nick, pass string) {
|
||||
application.CreatePeer(nick, pass)
|
||||
if pass == constants.DefactoPasswordForUnencryptedProfiles {
|
||||
application.CreateTaggedPeer(nick, pass, constants.ProfileTypeV1DefaultPassword)
|
||||
} else {
|
||||
application.CreateTaggedPeer(nick, pass, constants.ProfileTypeV1Password)
|
||||
}
|
||||
|
||||
//export c_SelectProfile
|
||||
func c_SelectProfile(onion_ptr *C.char, onion_len C.int) *C.char {
|
||||
return C.CString(SelectProfile(C.GoStringN(onion_ptr, onion_len)))
|
||||
}
|
||||
|
||||
func SelectProfile(onion string) string {
|
||||
contactEventsQueue = event.NewQueue()
|
||||
application.GetEventBus(onion).Subscribe(event.PeerStateChange, contactEventsQueue)
|
||||
return ""
|
||||
}
|
||||
|
||||
//export c_LoadProfiles
|
||||
|
@ -410,34 +464,22 @@ func BlockContact(profile, handle string) {
|
|||
}
|
||||
}
|
||||
|
||||
//export c_DebugResetContact
|
||||
func c_DebugResetContact(profilePtr *C.char, profileLen C.int, handlePtr *C.char, handleLen C.int) {
|
||||
DebugResetContact(C.GoStringN(profilePtr, profileLen), C.GoStringN(handlePtr, handleLen))
|
||||
}
|
||||
|
||||
func DebugResetContact(profile, handle string) {
|
||||
err := application.GetPeer(profile).SetContactAuthorization(handle, model.AuthUnknown)
|
||||
if err == nil {
|
||||
application.GetPrimaryBus().Publish(event.NewEvent(event.PeerStateChange, map[event.Field]string{
|
||||
ProfileOnion: profile,
|
||||
event.RemotePeer: handle,
|
||||
"authorization": string(model.AuthUnknown),
|
||||
}))
|
||||
} else {
|
||||
log.Errorf("error resetting contact: %s", err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
//export c_NumMessages
|
||||
func c_NumMessages(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int) (n int) {
|
||||
//export c_UpdateMessageFlags
|
||||
func c_UpdateMessageFlags(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, mIdx C.int, message_flags C.ulong) {
|
||||
profile := C.GoStringN(profile_ptr, profile_len)
|
||||
handle := C.GoStringN(handle_ptr, handle_len)
|
||||
return (NumMessages(profile, handle))
|
||||
UpdateMessageFlags(profile, handle, int(mIdx), int64(message_flags))
|
||||
}
|
||||
|
||||
func NumMessages(profile, handle string) (n int) {
|
||||
n = len(application.GetPeer(profile).GetContact(handle).Timeline.Messages)
|
||||
return
|
||||
// UpdateMessageFlags sets the messages flags on a given message for a given profile.
|
||||
// gomobile doesn't support uint64...so here we are....
|
||||
func UpdateMessageFlags(profileOnion, handle string, mIdx int, flags int64) {
|
||||
profile := application.GetPeer(profileOnion)
|
||||
if profile != nil {
|
||||
profile.UpdateMessageFlags(handle, mIdx, uint64(flags))
|
||||
} else {
|
||||
log.Errorf("called updatemessageflags with invalid profile onion")
|
||||
}
|
||||
}
|
||||
|
||||
//export c_GetMessage
|
||||
|
@ -461,27 +503,35 @@ func GetMessage(profileOnion, handle string, message_index int) string {
|
|||
if len(profile.GetGroup(handle).Timeline.Messages) > message_index {
|
||||
message.Message = profile.GetGroup(handle).Timeline.Messages[message_index]
|
||||
message.ContactImage = ph.GetProfilePic(message.Message.PeerID)
|
||||
} else {
|
||||
// Message Index Request exceeded Timeline, most likely reason is this is a request for an
|
||||
// unacknowledged sent message (it can take a many seconds for a message to be confirmed in the worst
|
||||
// case).
|
||||
offset := message_index - len(profile.GetGroup(handle).Timeline.Messages)
|
||||
if len(profile.GetGroup(handle).UnacknowledgedMessages) > offset {
|
||||
message.Message = profile.GetGroup(handle).UnacknowledgedMessages[offset]
|
||||
message.ContactImage = ph.GetProfilePic(message.Message.PeerID)
|
||||
} else {
|
||||
log.Errorf("Couldn't find message in timeline or unacked messages, probably transient threading issue, but logging for visibility..")
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if message_index < len(profile.GetContact(handle).Timeline.Messages) {
|
||||
message.Message = profile.GetContact(handle).Timeline.Messages[message_index]
|
||||
message.ContactImage = ph.GetProfilePic(handle)
|
||||
} else {
|
||||
log.Errorf("peerpeercontact getmessage out of range; sending counter resync just in case")
|
||||
eventHandler.Push(event.NewEvent(event.MessageCounterResync, map[event.Field]string{
|
||||
event.Identity: profileOnion,
|
||||
event.RemotePeer: handle,
|
||||
event.Data: strconv.Itoa(len(profile.GetContact(handle).Timeline.Messages)),
|
||||
}))
|
||||
}
|
||||
}
|
||||
bytes, _ := json.Marshal(message)
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
//export c_GetMessages
|
||||
func c_GetMessages(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, start C.int, end C.int) *C.char {
|
||||
profile := C.GoStringN(profile_ptr, profile_len)
|
||||
handle := C.GoStringN(handle_ptr, handle_len)
|
||||
return C.CString(GetMessages(profile, handle, int(start), int(end)))
|
||||
}
|
||||
|
||||
func GetMessages(profile, handle string, start, end int) string {
|
||||
messages := application.GetPeer(profile).GetContact(handle).Timeline.Messages[start:end]
|
||||
bytes, _ := json.Marshal(messages)
|
||||
return string(bytes)
|
||||
}
|
||||
|
||||
//export c_SendMessage
|
||||
func c_SendMessage(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, msg_ptr *C.char, msg_len C.int) {
|
||||
|
@ -505,6 +555,40 @@ func SendMessage(profileOnion, handle, msg string) {
|
|||
}
|
||||
}
|
||||
|
||||
//export c_SendInvitation
|
||||
func c_SendInvitation(profile_ptr *C.char, profile_len C.int, handle_ptr *C.char, handle_len C.int, target_ptr *C.char, target_len C.int) {
|
||||
profile := C.GoStringN(profile_ptr, profile_len)
|
||||
handle := C.GoStringN(handle_ptr, handle_len)
|
||||
target := C.GoStringN(target_ptr, target_len)
|
||||
SendInvitation(profile, handle, target)
|
||||
}
|
||||
|
||||
// Send an invitation from `profileOnion` to contact `handle` (peer or group)
|
||||
// asking them to add the contact `target` (also peer or group).
|
||||
// For groups, the profile must already have `target` as a contact.
|
||||
func SendInvitation(profileOnion, handle, target string) {
|
||||
profile := application.GetPeer(profileOnion)
|
||||
ph := utils.NewPeerHelper(profile)
|
||||
|
||||
var invite ChatMessage
|
||||
if ph.IsGroup(target) {
|
||||
bundle, _ := profile.GetContact(profile.GetGroup(target).GroupServer).GetAttribute(string(model.BundleType))
|
||||
inviteStr, err := profile.GetGroup(target).Invite()
|
||||
if err == nil {
|
||||
invite = ChatMessage{O: 101, D: fmt.Sprintf("tofubundle:server:%s||%s", base64.StdEncoding.EncodeToString([]byte(bundle)), inviteStr)}
|
||||
}
|
||||
} else {
|
||||
invite = ChatMessage{O: 100, D: target}
|
||||
}
|
||||
|
||||
inviteBytes, err := json.Marshal(invite)
|
||||
if err != nil {
|
||||
log.Errorf("malformed invite: %v", err)
|
||||
} else {
|
||||
SendMessage(profileOnion, handle, string(inviteBytes))
|
||||
}
|
||||
}
|
||||
|
||||
//export c_ResetTor
|
||||
func c_ResetTor() {
|
||||
ResetTor()
|
||||
|
@ -531,13 +615,60 @@ func CreateGroup(profile string, server string, name string) {
|
|||
if err == nil {
|
||||
log.Debugf("created group %v on %v: $v", profile, server, gid)
|
||||
// set the group name
|
||||
peer.SetGroupAttribute(gid, attr.GetPublicScope(name), name)
|
||||
peer.SetGroupAttribute(gid, attr.GetLocalScope("name"), name)
|
||||
} else {
|
||||
log.Errorf("error creating group or %v on server %v: %v", profile, server, err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//export c_DeleteProfile
|
||||
func c_DeleteProfile(profile_ptr *C.char, profile_len C.int, password_ptr *C.char, password_len C.int) {
|
||||
profile := C.GoStringN(profile_ptr, profile_len)
|
||||
password := C.GoStringN(password_ptr, password_len)
|
||||
DeleteProfile(profile, password)
|
||||
}
|
||||
|
||||
// DeleteProfile deletes a profile given the right password
|
||||
func DeleteProfile(profile string, password string) {
|
||||
|
||||
// allow a blank password to delete "unencrypted" accounts...
|
||||
if password == "" {
|
||||
password = constants.DefactoPasswordForUnencryptedProfiles
|
||||
}
|
||||
|
||||
application.DeletePeer(profile, password)
|
||||
}
|
||||
|
||||
//export c_LeaveConversation
|
||||
func c_LeaveConversation(profile_ptr *C.char, profile_len C.int, contact_ptr *C.char, contact_len C.int) {
|
||||
profile := C.GoStringN(profile_ptr, profile_len)
|
||||
contact := C.GoStringN(contact_ptr, contact_len)
|
||||
LeaveConversation(profile, contact)
|
||||
}
|
||||
|
||||
// LeaveConversation forces profile to leave the peer
|
||||
func LeaveConversation(profile string, contact string) {
|
||||
peer := application.GetPeer(profile)
|
||||
peer.DeleteContact(contact)
|
||||
}
|
||||
|
||||
//export c_LeaveGroup
|
||||
func c_LeaveGroup(profile_ptr *C.char, profile_len C.int, group_ptr *C.char, group_len C.int) {
|
||||
profile := C.GoStringN(profile_ptr, profile_len)
|
||||
groupID := C.GoStringN(group_ptr, group_len)
|
||||
LeaveGroup(profile, groupID)
|
||||
}
|
||||
|
||||
// LeaveGroup forces profile to leave the group groupID
|
||||
func LeaveGroup(profile string, groupID string) {
|
||||
peer := application.GetPeer(profile)
|
||||
_, err := groups.ExperimentGate(utils.ReadGlobalSettings().Experiments)
|
||||
if err == nil {
|
||||
peer.DeleteGroup(groupID)
|
||||
}
|
||||
}
|
||||
|
||||
//export c_ImportBundle
|
||||
func c_ImportBundle(profile_ptr *C.char, profile_len C.int, bundle_ptr *C.char, bundle_len C.int) {
|
||||
profile := C.GoStringN(profile_ptr, profile_len)
|
||||
|
@ -545,17 +676,27 @@ func c_ImportBundle(profile_ptr *C.char, profile_len C.int, bundle_ptr *C.char,
|
|||
ImportBundle(profile, name)
|
||||
}
|
||||
|
||||
// ImportGroupInviteString takes in a handle to a profile and an invite string which could have one of many
|
||||
// different formats (e.g. a group invite, a server key bundle, or a combination)
|
||||
// TODO: extend to also handle AddContact flow...
|
||||
// ImportBundle takes in a handle to a profile and an invite string which could have one of many
|
||||
// different formats (e.g. a peer address, a group invite, a server key bundle, or a combination)
|
||||
func ImportBundle(profileOnion string, bundle string) {
|
||||
profile := application.GetPeer(profileOnion)
|
||||
peerHandler, _ := contact.FunctionalityGate(utils.ReadGlobalSettings().Experiments)
|
||||
response := peerHandler.HandleImportString(profile, bundle)
|
||||
if strings.Contains(response.Error(), "invalid_import_string") {
|
||||
groupHandler, err := groups.ExperimentGate(utils.ReadGlobalSettings().Experiments)
|
||||
if err == nil {
|
||||
err = groupHandler.HandleImportString(profile, bundle)
|
||||
eventHandler.Push(event.NewEvent(event.AppError, map[event.Field]string{event.Data: err.Error()}))
|
||||
response = groupHandler.HandleImportString(profile, bundle)
|
||||
eventHandler.Push(event.NewEvent(event.AppError, map[event.Field]string{event.Data: response.Error()}))
|
||||
|
||||
// We might have added a new server, so refresh the server list...
|
||||
serverListForOnion := groupHandler.GetServerInfoList(profile)
|
||||
serversListBytes, _ := json.Marshal(serverListForOnion)
|
||||
eventHandler.Push(event.NewEvent(groups.UpdateServerInfo, map[event.Field]string{"ProfileOnion": profileOnion, groups.ServerList: string(serversListBytes)}))
|
||||
return
|
||||
}
|
||||
}
|
||||
eventHandler.Push(event.NewEvent(event.AppError, map[event.Field]string{event.Data: response.Error()}))
|
||||
}
|
||||
|
||||
//export c_SetGroupAttribute
|
||||
func c_SetGroupAttribute(profile_ptr *C.char, profile_len C.int, group_ptr *C.char, group_len C.int, key_ptr *C.char, key_len C.int, val_ptr *C.char, val_len C.int) {
|
||||
|
@ -575,5 +716,29 @@ func SetGroupAttribute(profileOnion string, groupHandle string, key string, valu
|
|||
}
|
||||
}
|
||||
|
||||
//export c_ShutdownCwtch
|
||||
func c_ShutdownCwtch() {
|
||||
ShutdownCwtch()
|
||||
}
|
||||
|
||||
// ShutdownCwtch is a safe way to shutdown any active cwtch applications and associated ACNs
|
||||
func ShutdownCwtch() {
|
||||
if application != nil && globalACN != nil {
|
||||
// Kill the isolate
|
||||
eventHandler.Push(event.NewEvent(event.Shutdown, map[event.Field]string{}))
|
||||
|
||||
// Allow for the shutdown events to go through and then purge everything else...
|
||||
log.Infof("Shutting Down Application...")
|
||||
application.Shutdown()
|
||||
log.Infof("Shutting Down ACN...")
|
||||
globalACN.Close()
|
||||
log.Infof("Library Shutdown Complete!")
|
||||
// do not remove - important for state checks elsewhere
|
||||
application = nil
|
||||
globalACN = nil
|
||||
eventHandler = nil
|
||||
}
|
||||
}
|
||||
|
||||
// Leave as is, needed by ffi
|
||||
func main() {}
|
||||
|
|
|
@ -6,7 +6,6 @@ import (
|
|||
"cwtch.im/cwtch/model"
|
||||
"cwtch.im/cwtch/model/attr"
|
||||
"cwtch.im/cwtch/protocol/connections"
|
||||
groups2 "cwtch.im/cwtch/protocol/groups"
|
||||
"encoding/json"
|
||||
"git.openprivacy.ca/flutter/libcwtch-go/constants"
|
||||
"git.openprivacy.ca/flutter/libcwtch-go/features/groups"
|
||||
|
@ -24,20 +23,31 @@ type EventHandler struct {
|
|||
app app.Application
|
||||
appBusQueue event.Queue
|
||||
profileEvents chan EventProfileEnvelope
|
||||
|
||||
profileQueues map[string]event.Queue
|
||||
}
|
||||
|
||||
func NewEventHandler(application app.Application) *EventHandler {
|
||||
appBusQueue := event.NewQueue()
|
||||
application.GetPrimaryBus().Subscribe(event.NewPeer, appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.PeerError, appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.AppError, appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.ACNStatus, appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.ReloadDone, appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.ACNVersion, appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(UpdateGlobalSettings, appBusQueue)
|
||||
return &EventHandler{app: application, appBusQueue: appBusQueue, profileQueues: make(map[string]event.Queue), profileEvents: make(chan EventProfileEnvelope)}
|
||||
func NewEventHandler() *EventHandler {
|
||||
eh := &EventHandler{app: nil, appBusQueue: event.NewQueue(), profileEvents: make(chan EventProfileEnvelope)}
|
||||
return eh
|
||||
}
|
||||
|
||||
// PublishAppEvent is a way for libCwtch-go to publish an event for consumption by a UI before a Cwtch app has been initialized
|
||||
// Main use: to signal an error before a cwtch app could be created
|
||||
func (eh *EventHandler) PublishAppEvent(event event.Event) {
|
||||
eh.appBusQueue.Publish(event)
|
||||
}
|
||||
|
||||
func (eh *EventHandler) HandleApp(application app.Application) {
|
||||
eh.app = application
|
||||
application.GetPrimaryBus().Subscribe(event.NewPeer, eh.appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.PeerError, eh.appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.PeerDeleted, eh.appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.Shutdown, eh.appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.AppError, eh.appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.ACNStatus, eh.appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.ReloadDone, eh.appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(event.ACNVersion, eh.appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(UpdateGlobalSettings, eh.appBusQueue)
|
||||
application.GetPrimaryBus().Subscribe(CwtchStarted, eh.appBusQueue)
|
||||
}
|
||||
|
||||
func (eh *EventHandler) GetNextEvent() string {
|
||||
|
@ -54,6 +64,7 @@ func (eh *EventHandler) GetNextEvent() string {
|
|||
// handleAppBusEvent enriches AppBus events so they are usable with out further data fetches
|
||||
func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
|
||||
log.Debugf("New AppBus Event to Handle: %v", e)
|
||||
if eh.app != nil {
|
||||
switch e.EventType {
|
||||
case event.ACNStatus:
|
||||
if e.Data[event.Progress] == "100" {
|
||||
|
@ -67,10 +78,23 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
|
|||
onion := e.Data[event.Identity]
|
||||
profile := eh.app.GetPeer(e.Data[event.Identity])
|
||||
log.Debug("New Peer Event: %v", e)
|
||||
|
||||
if e.Data["Reload"] != event.True {
|
||||
eh.startHandlingPeer(onion)
|
||||
}
|
||||
|
||||
tag,isTagged := profile.GetAttribute(app.AttributeTag)
|
||||
if isTagged {
|
||||
e.Data[app.AttributeTag] = tag
|
||||
} else {
|
||||
// Assume encrypted for non-tagged profiles - this isn't always true, but all post-beta profiles
|
||||
// are tagged on creation.
|
||||
e.Data[app.AttributeTag] = constants.ProfileTypeV1Password
|
||||
}
|
||||
|
||||
if e.Data[event.Created] == event.True {
|
||||
profile.SetAttribute(attr.GetPublicScope(constants.Name), profile.GetName())
|
||||
name, _ := profile.GetAttribute(attr.GetLocalScope(constants.Name))
|
||||
profile.SetAttribute(attr.GetPublicScope(constants.Name), name)
|
||||
profile.SetAttribute(attr.GetPublicScope(constants.Picture), ImageToString(NewImage(RandomProfileImage(onion), TypeImageDistro)))
|
||||
}
|
||||
if e.Data[event.Status] != event.StorageRunning || e.Data[event.Created] == event.True {
|
||||
|
@ -159,6 +183,12 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
|
|||
// We compile and send the groups regardless of the experiment flag, and hide them in the UI
|
||||
for _, groupId := range profile.GetGroups() {
|
||||
group := profile.GetGroup(groupId)
|
||||
|
||||
// Check that the group is cryptographically valid
|
||||
if !group.CheckGroup() {
|
||||
continue
|
||||
}
|
||||
|
||||
ph := NewPeerHelper(profile)
|
||||
cpicPath := ph.GetProfilePic(groupId)
|
||||
|
||||
|
@ -189,7 +219,8 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
|
|||
serversListBytes, _ := json.Marshal(servers)
|
||||
e.Data[groups.ServerList] = string(serversListBytes)
|
||||
|
||||
log.Infof("contactsJson %v", e.Data["ContactsJson"])
|
||||
log.Debugf("contactsJson %v", e.Data["ContactsJson"])
|
||||
}
|
||||
}
|
||||
|
||||
json, _ := json.Marshal(e)
|
||||
|
@ -198,13 +229,17 @@ func (eh *EventHandler) handleAppBusEvent(e *event.Event) string {
|
|||
|
||||
// handleProfileEvent enriches Profile events so they are usable with out further data fetches
|
||||
func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
|
||||
|
||||
if eh.app == nil {
|
||||
log.Errorf("eh.app == nil in handleProfileEvent... this shouldnt happen?")
|
||||
} else {
|
||||
peer := eh.app.GetPeer(ev.Profile)
|
||||
ph := NewPeerHelper(peer)
|
||||
log.Debugf("New Profile Event to Handle: %v", ev)
|
||||
switch ev.Event.EventType {
|
||||
|
||||
/*case event.NetworkStatus:
|
||||
/*
|
||||
TODO: still handle this somewhere - network info from plugin Network check
|
||||
case event.NetworkStatus:
|
||||
online, _ := peer.GetAttribute(attr.GetLocalScope(constants.PeerOnline))
|
||||
if e.Data[event.Status] == plugins.NetworkCheckSuccess && online == event.False {
|
||||
peer.SetAttribute(attr.GetLocalScope(constants.PeerOnline), event.True)
|
||||
|
@ -216,54 +251,40 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
|
|||
}*/
|
||||
|
||||
case event.NewMessageFromPeer: //event.TimestampReceived, event.RemotePeer, event.Data
|
||||
// I Don't think we need to enrich
|
||||
|
||||
// TODO: deprecate and move to dart
|
||||
/*func (p *PeerHelper) updateLastReadTime(id string) {
|
||||
lastRead, _ := time.Now().MarshalText()
|
||||
if p.IsGroup(id) {
|
||||
p.peer.SetGroupAttribute(id, attr.GetLocalScope(constants.LastRead), string(lastRead))
|
||||
} else {
|
||||
p.peer.SetContactAttribute(id, attr.GetLocalScope(constants.LastRead), string(lastRead))
|
||||
}
|
||||
}*/
|
||||
|
||||
// legacy
|
||||
//ts, _ := time.Parse(time.RFC3339Nano, e.Data[event.TimestampReceived])
|
||||
|
||||
// only needs contact nickname and picture, for displaying on popup notifications
|
||||
ev.Event.Data["Nick"] = ph.GetNick(ev.Event.Data["RemotePeer"])
|
||||
ev.Event.Data["Picture"] = ph.GetProfilePic(ev.Event.Data["RemotePeer"])
|
||||
case event.NewMessageFromGroup:
|
||||
// only needs contact nickname and picture, for displaying on popup notifications
|
||||
ev.Event.Data["Nick"] = ph.GetNick(ev.Event.Data[event.GroupID])
|
||||
ev.Event.Data["Picture"] = ph.GetProfilePic(ev.Event.Data[event.GroupID])
|
||||
case event.PeerAcknowledgement:
|
||||
// No enrichement required
|
||||
//Acknowledge(ev.Event.Data[event.RemotePeer], ev.Event.Data[event.EventID])
|
||||
/*
|
||||
case event.NewMessageFromGroup: //event.TimestampReceived, event.TimestampSent, event.Data, event.GroupID, event.RemotePeer
|
||||
ts, _ := time.Parse(time.RFC3339Nano, e.Data[event.TimestampSent])
|
||||
uiManager.AddMessage(e.Data[event.GroupID], e.Data[event.RemotePeer], e.Data[event.Data], e.Data[event.RemotePeer] == peer.GetOnion(), hex.EncodeToString([]byte(e.Data[event.Signature])), ts, true)
|
||||
|
||||
case event.NewGroupInvite:
|
||||
gid, err := peer.ProcessInvite(e.Data[event.GroupInvite], e.Data[event.RemotePeer])
|
||||
group := peer.GetGroup(gid)
|
||||
if err == nil && group != nil {
|
||||
uiManager.AddContact(gid)
|
||||
}
|
||||
*/
|
||||
case event.PeerCreated:
|
||||
handle := ev.Event.Data[event.RemotePeer]
|
||||
err := EnrichNewPeer(handle, ph, ev)
|
||||
if err != nil {
|
||||
return ""
|
||||
}
|
||||
/*
|
||||
case event.SendMessageToGroupError:
|
||||
uiManager.AddSendMessageError(e.Data[event.GroupServer], e.Data[event.Signature], e.Data[event.Error])
|
||||
case event.SendMessageToPeerError:
|
||||
uiManager.AddSendMessageError(e.Data[event.RemotePeer], e.Data[event.EventID], e.Data[event.Error])
|
||||
*/
|
||||
case event.NewGroupInvite:
|
||||
var invite = groups2.GroupInvite{}
|
||||
json.Unmarshal([]byte(ev.Event.Data[event.GroupInvite]), &invite)
|
||||
case event.GroupCreated:
|
||||
// This event should only happen after we have validated the invite, as such the error
|
||||
// condition *should* never happen.
|
||||
|
||||
groupPic := ph.GetProfilePic(ev.Event.Data[event.GroupID])
|
||||
ev.Event.Data["PicturePath"] = groupPic
|
||||
ev.Event.Data["GroupName"] = ph.GetNick(ev.Event.Data[event.GroupID])
|
||||
|
||||
case event.NewGroup:
|
||||
// This event should only happen after we have validated the invite, as such the error
|
||||
// condition *should* never happen.
|
||||
serializedInvite := ev.Event.Data[event.GroupInvite]
|
||||
if invite, err := model.ValidateInvite(serializedInvite); err == nil {
|
||||
groupPic := ph.GetProfilePic(invite.GroupID)
|
||||
ev.Event.Data["PicturePath"] = groupPic
|
||||
|
||||
} else {
|
||||
log.Errorf("received a new group event which contained an invalid invite %v. this should never happen and likely means there is a bug in cwtch. Please file a ticket @ https://git.openprivcy.ca/cwtch.im/cwtch", err)
|
||||
return ""
|
||||
}
|
||||
case event.PeerStateChange:
|
||||
cxnState := connections.ConnectionStateToType()[ev.Event.Data[event.ConnectionState]]
|
||||
contact := peer.GetContact(ev.Event.Data[event.RemotePeer])
|
||||
|
@ -283,45 +304,21 @@ func (eh *EventHandler) handleProfileEvent(ev *EventProfileEnvelope) string {
|
|||
}
|
||||
}
|
||||
|
||||
/*case event.NewRetValMessageFromPeer:
|
||||
onion := e.Data[event.RemotePeer]
|
||||
scope := e.Data[event.Scope]
|
||||
path := e.Data[event.Path]
|
||||
val := e.Data[event.Data]
|
||||
exists, _ := strconv.ParseBool(e.Data[event.Exists])
|
||||
case event.NewRetValMessageFromPeer:
|
||||
// auto handled event means the setting is already done, we're just deciding if we need to tell the UI
|
||||
onion := ev.Event.Data[event.RemotePeer]
|
||||
scope := ev.Event.Data[event.Scope]
|
||||
path := ev.Event.Data[event.Path]
|
||||
//val := ev.Event.Data[event.Data]
|
||||
exists, _ := strconv.ParseBool(ev.Event.Data[event.Exists])
|
||||
|
||||
if exists && scope == attr.PublicScope {
|
||||
switch path {
|
||||
case constants.Name:
|
||||
peer.SetContactAttribute(onion, attr.GetPeerScope(constants.Name), val)
|
||||
uiManager.UpdateContactDisplayName(onion)
|
||||
case constants.Picture:
|
||||
peer.SetContactAttribute(onion, attr.GetPeerScope(constants.Picture), val)
|
||||
uiManager.UpdateContactPicture(onion)
|
||||
if _, exists := peer.GetContactAttribute(onion, attr.GetLocalScope(path)); exists {
|
||||
// we have a locally set ovverride, don't pass this remote set public scope update to UI
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
case event.ServerStateChange:
|
||||
serverOnion := e.Data[event.GroupServer]
|
||||
state := connections.ConnectionStateToType[e.Data[event.ConnectionState]]
|
||||
groups := peer.GetGroups()
|
||||
for _, groupID := range groups {
|
||||
group := peer.GetGroup(groupID)
|
||||
if group != nil && group.GroupServer == serverOnion {
|
||||
group.State = e.Data[event.ConnectionState]
|
||||
loading := false
|
||||
if state == connections.AUTHENTICATED {
|
||||
loading = true
|
||||
}
|
||||
uiManager.UpdateContactStatus(groupID, int(state), loading)
|
||||
uiManager.UpdateContactStatus(serverOnion, int(state), loading)
|
||||
}
|
||||
}
|
||||
case event.DeletePeer:
|
||||
log.Infof("PeerHandler got DeletePeer, SHUTTING down!\n")
|
||||
uiManager.ReloadProfiles()
|
||||
return
|
||||
*/
|
||||
}
|
||||
|
||||
json, _ := json.Marshal(unwrap(ev))
|
||||
|
@ -339,10 +336,16 @@ func (eh *EventHandler) startHandlingPeer(onion string) {
|
|||
q := event.NewQueue()
|
||||
eventBus.Subscribe(event.NewMessageFromPeer, q)
|
||||
eventBus.Subscribe(event.PeerAcknowledgement, q)
|
||||
eventBus.Subscribe(event.DeleteContact, q)
|
||||
eventBus.Subscribe(event.AppError, q)
|
||||
eventBus.Subscribe(event.IndexedAcknowledgement, q)
|
||||
eventBus.Subscribe(event.IndexedFailure, q)
|
||||
eventBus.Subscribe(event.NewMessageFromGroup, q)
|
||||
eventBus.Subscribe(event.NewGroupInvite, q)
|
||||
eventBus.Subscribe(event.GroupCreated, q)
|
||||
eventBus.Subscribe(event.NewGroup, q)
|
||||
eventBus.Subscribe(event.AcceptGroupInvite, q)
|
||||
eventBus.Subscribe(event.SetGroupAttribute, q)
|
||||
eventBus.Subscribe(event.DeleteGroup, q)
|
||||
eventBus.Subscribe(event.SendMessageToGroupError, q)
|
||||
eventBus.Subscribe(event.SendMessageToPeerError, q)
|
||||
eventBus.Subscribe(event.ServerStateChange, q)
|
||||
|
@ -353,18 +356,21 @@ func (eh *EventHandler) startHandlingPeer(onion string) {
|
|||
eventBus.Subscribe(event.ChangePasswordError, q)
|
||||
eventBus.Subscribe(event.NewRetValMessageFromPeer, q)
|
||||
eventBus.Subscribe(event.SetAttribute, q)
|
||||
eh.profileQueues[onion] = q
|
||||
|
||||
go eh.forwardProfileMessages(onion, q)
|
||||
|
||||
}
|
||||
|
||||
func (eh *EventHandler) forwardProfileMessages(onion string, q event.Queue) {
|
||||
log.Infof("Launching Forwarding Goroutine for %v", onion)
|
||||
// TODO: graceful shutdown, via an injected event of special QUIT type exiting loop/go routine
|
||||
for {
|
||||
e := q.Next()
|
||||
ev := EventProfileEnvelope{Event: e, Profile: onion}
|
||||
eh.profileEvents <- ev
|
||||
if ev.Event.EventType == event.Shutdown {
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -87,6 +87,8 @@ func (p *PeerHelper) GetNick(id string) string {
|
|||
nick, exists = p.peer.GetContactAttribute(id, attr.GetPeerScope(constants.Name))
|
||||
if !exists {
|
||||
nick = "[" + id + "]"
|
||||
// re-request
|
||||
p.peer.SendGetValToPeer(id, attr.PublicScope, constants.Name)
|
||||
}
|
||||
}
|
||||
return nick
|
||||
|
@ -284,8 +286,8 @@ func EnrichNewPeer(handle string, ph *PeerHelper, ev *EventProfileEnvelope) erro
|
|||
}
|
||||
} else {
|
||||
// could be a server?
|
||||
log.Errorf("sorry, unable to handle AddContact(%v)", handle)
|
||||
return errors.New("Not a peer or group")
|
||||
log.Debugf("sorry, unable to handle AddContact(%v)", handle)
|
||||
return errors.New("not a peer or group")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -12,6 +12,8 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
CwtchStarted = event.Type("CwtchStarted")
|
||||
CwtchStartError = event.Type("CwtchStartError")
|
||||
UpdateGlobalSettings = event.Type("UpdateGlobalSettings")
|
||||
)
|
||||
|
||||
|
@ -29,17 +31,21 @@ type GlobalSettings struct {
|
|||
BlockUnknownConnections bool
|
||||
StateRootPane int
|
||||
FirstTime bool
|
||||
UIColumnModePortrait string
|
||||
UIColumnModeLandscape string
|
||||
}
|
||||
|
||||
var DefaultGlobalSettings = GlobalSettings{
|
||||
Locale: "en",
|
||||
Theme: "light",
|
||||
Theme: "dark",
|
||||
PreviousPid: -1,
|
||||
ExperimentsEnabled: false,
|
||||
Experiments: make(map[string]bool),
|
||||
StateRootPane: 0,
|
||||
FirstTime: true,
|
||||
BlockUnknownConnections: false,
|
||||
UIColumnModePortrait: "DualpaneMode.Single",
|
||||
UIColumnModeLandscape: "DualpaneMode.CopyPortrait",
|
||||
}
|
||||
|
||||
func InitGlobalSettingsFile(directory string, password string) error {
|
||||
|
|
Loading…
Reference in New Issue