first pass of server functionality API

This commit is contained in:
Dan Ballard 2021-10-07 17:11:50 -07:00
parent 4529984e45
commit a237314d5f
5 changed files with 157 additions and 174 deletions

View File

@ -1,26 +0,0 @@
package constants
import "cwtch.im/cwtch/event"
// The server manager defines its own events, most should be self-explanatory:
const (
NewServer = event.Type("NewServer")
// Force a UI update
ListServers = event.Type("ListServers")
// Takes an Onion, used to toggle off/on Server availability
StartServer = event.Type("StartServer")
StopServer = event.Type("StopServer")
// Takes an Onion and a AutoStartEnabled boolean
AutoStart = event.Type("AutoStart")
// Get the status of a particular server (takes an Onion)
CheckServerStatus = event.Type("CheckServerStatus")
ServerStatusUpdate = event.Type("ServerStatusUpdate")
)
const (
AutoStartEnabled = event.Field("AutoStartEnabled")
)

1
go.mod
View File

@ -4,6 +4,7 @@ go 1.15
require (
cwtch.im/cwtch v0.13.0
git.openprivacy.ca/cwtch.im/server v1.1.2
git.openprivacy.ca/openprivacy/connectivity v1.5.0
git.openprivacy.ca/openprivacy/log v1.0.3
golang.org/x/mobile v0.0.0-20210716004757-34ab1303b554 // indirect

15
go.sum
View File

@ -1,3 +1,4 @@
cwtch.im/cwtch v0.8.5/go.mod h1:5GHxaaeVnKeXSU64IvtCKzkqhU8DRiLoVM+tiBT8kkc=
cwtch.im/cwtch v0.11.2 h1:a38zZLSNsKJzLStBDOIoYKKIL56V9ueQvOZfnIEVc5I=
cwtch.im/cwtch v0.11.2/go.mod h1:QpTkQK7MqNt0dQK9/pBk5VpkvFhy6xuoxJIn401B8fM=
cwtch.im/cwtch v0.12.0 h1:hEMee2/2s4kUwukGCTBpGww/KfrsE84e9tOLnM8lM78=
@ -8,12 +9,18 @@ cwtch.im/cwtch v0.12.2 h1:I+ndKadCRCITw4SPbd+1cpRv+z/7iHjjTUv8OzRwTrE=
cwtch.im/cwtch v0.12.2/go.mod h1:QpTkQK7MqNt0dQK9/pBk5VpkvFhy6xuoxJIn401B8fM=
filippo.io/edwards25519 v1.0.0-rc.1 h1:m0VOOB23frXZvAOK44usCgLWvtsxIoMCTBGJZlpmGfU=
filippo.io/edwards25519 v1.0.0-rc.1/go.mod h1:N1IkdkCkiLB6tki+MYJoSx2JTY9NUlxZE7eHn5EwJns=
git.openprivacy.ca/cwtch.im/server v1.1.2/go.mod h1:F0+c77ptKgn5olYsHS0R/AfhjiU5e2HbUIcRc9NASnU=
git.openprivacy.ca/cwtch.im/tapir v0.4.2/go.mod h1:eH6dZxXrhW0C4KZX18ksUa6XJCrEvtg8cJJ/Fy6gv+E=
git.openprivacy.ca/cwtch.im/tapir v0.4.4/go.mod h1:qMFTdmDZITc1BLP1jSW0gVpLmvpg+Zjsh5ek8StwbFE=
git.openprivacy.ca/cwtch.im/tapir v0.4.9 h1:LXonlztwvI1F1++0IyomIcDH1/Bxzo+oN8YjGonNvjM=
git.openprivacy.ca/cwtch.im/tapir v0.4.9/go.mod h1:p4bHo3DAO8wwimU6JAeZXbfPQ4jnoA2bV+4YvknWTNQ=
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.4.3/go.mod h1:bR0Myx9nm2YzWtsThRelkNMV4Pp7sPDa123O1qsAbVo=
git.openprivacy.ca/openprivacy/connectivity v1.4.5/go.mod h1:JVRCIdL+lAG6ohBFWiKeC/MN42nnC0sfFszR9XG6vPQ=
git.openprivacy.ca/openprivacy/connectivity v1.5.0 h1:ZxsR/ZaVKXIkD2x6FlajZn62ciNQjamrI4i/5xIpdoQ=
git.openprivacy.ca/openprivacy/connectivity v1.5.0/go.mod h1:UjQiGBnWbotmBzIw59B8H6efwDadjkKzm3RPT1UaIRw=
git.openprivacy.ca/openprivacy/log v1.0.1/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
git.openprivacy.ca/openprivacy/log v1.0.2/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
git.openprivacy.ca/openprivacy/log v1.0.3 h1:E/PMm4LY+Q9s3aDpfySfEDq/vYQontlvNj/scrPaga0=
git.openprivacy.ca/openprivacy/log v1.0.3/go.mod h1:gGYK8xHtndRLDymFtmjkG26GaMQNgyhioNS82m812Iw=
@ -32,6 +39,8 @@ 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=
github.com/mattn/go-sqlite3 v1.14.7 h1:fxWBnXkxfM6sRiuH3bqJ4CfzZojMOLVc0UTsTglEghA=
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643 h1:hLDRPB66XQT/8+wG9WsDpiCvZf1yKO7sz7scAjSlBa0=
github.com/mimoo/StrobeGo v0.0.0-20181016162300-f8f6d4d2b643/go.mod h1:43+3pMjjKimDBf5Kr4ZFNGbLql1zKkbImw+fZbw3geM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
@ -42,6 +51,9 @@ 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/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/go.mod h1:pWBlW3YuSwRl6h7R5KbvA4N8oOqe9LjaKW5CwT1SPjI=
github.com/struCoder/pidusage v0.2.1 h1:dFiEgUDkubeIj0XA1NpQ6+8LQmKrLi7NiIQl86E6BoY=
github.com/struCoder/pidusage v0.2.1/go.mod h1:bewtP2KUA1TBUyza5+/PCpSQ6sc/H6jJbIKAzqW86BA=
github.com/yuin/goldmark v1.3.5 h1:dPmz1Snjq0kmkz159iL7S6WzdahUTHnHB5M56WFVifs=
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=
@ -57,10 +69,12 @@ golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9t
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-20210508222113-6edffad5e616/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-20210716004757-34ab1303b554 h1:3In5TnfvnuXTF/uflgpYxSCEGP2NdYT37KsPh3VjZYU=
golang.org/x/mobile v0.0.0-20210716004757-34ab1303b554/go.mod h1:jFTmtFYCV0MFtXBU+J5V/+5AUeVS0ON/0WkE/KSrl6E=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0 h1:UG21uOlmZabA4fW5i7ZX6bjw1xELEGg/ZLgZq9auk/Q=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
@ -90,6 +104,7 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.1.2 h1:kRBLX7v7Af8W7Gdbbc908OJcdgtK8bOz9Uaj8/F1ACA=
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=

143
lib.go
View File

@ -10,6 +10,8 @@ import (
"crypto/rand"
"encoding/json"
"fmt"
"git.openprivacy.ca/cwtch.im/libcwtch-go/features/servers"
"git.openprivacy.ca/cwtch.im/server"
"os/user"
"runtime"
"strconv"
@ -45,6 +47,7 @@ const (
)
var application app.Application
var globalAppDir string
var eventHandler *utils.EventHandler
var globalACN connectivity.ACN
@ -86,7 +89,8 @@ func StartCwtch(appDir string, torPath string) int {
if runtime.GOOS == "android" {
log.SetUseColor(false)
}
log.SetLevel(log.LevelInfo)
log.AddEverythingFromPattern("libcwtch-go")
if logLevel := os.Getenv("LOG_LEVEL"); strings.ToLower(logLevel) == "debug" {
log.SetLevel(log.LevelDebug)
}
@ -181,8 +185,10 @@ func _startCwtch(appDir string, torPath string) {
eventHandler.PublishAppEvent(event.NewEventList(utils.CwtchStartError, event.Error, fmt.Sprintf("Error connecting to Tor: %v", err)))
return
}
globalAppDir = appDir
globalACN = acn
newApp := app.NewApp(acn, appDir)
servers.InitServers(acn, appDir)
eventHandler.HandleApp(newApp)
@ -304,8 +310,18 @@ func SendAppEvent(eventJson string) {
log.Debugf("New Settings %v", globalSettings)
utils.WriteGlobalSettings(globalSettings)
settings := utils.ReadGlobalSettings()
serverHandler, err := servers.ExperimentGate(settings.Experiments)
if err == nil {
serverHandler.LoadServers(constants.DefactoPasswordForUnencryptedProfiles)
serverHandler.LaunchServers()
} else {
servers.DeactivateServers()
}
// Group Experiment Refresh
groupHandler, err := groups.ExperimentGate(utils.ReadGlobalSettings().Experiments)
groupHandler, err := groups.ExperimentGate(settings.Experiments)
if err == nil {
for _, profileOnion := range application.ListProfiles() {
serverListForOnion := groupHandler.GetServerInfoList(application.GetPeer(profileOnion))
@ -316,7 +332,7 @@ func SendAppEvent(eventJson string) {
// Explicitly toggle blocking/unblocking of unknown connections for profiles
// that have been loaded.
if utils.ReadGlobalSettings().BlockUnknownConnections {
if settings.BlockUnknownConnections {
for _, onion := range application.ListProfiles() {
application.GetPeer(onion).BlockUnknownConnections()
}
@ -938,5 +954,126 @@ func ShutdownCwtch() {
}
}
//***** Server APIs *****
//export c_LoadServers
func c_LoadServers(passwordPtr *C.char, passwordLen C.int) {
LoadServers(C.GoStringN(passwordPtr, passwordLen))
}
func LoadServers(password string) {
serversHandler, err := servers.ExperimentGate(utils.ReadGlobalSettings().Experiments)
if err == nil {
serversList, err := serversHandler.LoadServers(password)
if err != nil {
log.Errorf("Error attempting to load servers :%s\n", err)
application.GetPrimaryBus().Publish(event.NewEventList(servers.ZeroServersLoaded))
} else if len(serversList) == 0 {
application.GetPrimaryBus().Publish(event.NewEventList(servers.ZeroServersLoaded))
} else {
for _, serverOnion := range serversList {
json := serversHandler.SeverToJson(serverOnion)
application.GetPrimaryBus().Publish(event.NewEventList(servers.NewServer, event.Data, json))
}
}
}
}
//export c_CreateServer
func c_CreateServer(passwordPtr *C.char, passwordLen C.int) {
CreateServer(C.GoStringN(passwordPtr, passwordLen))
}
func CreateServer(password string) {
serversHandler, err := servers.ExperimentGate(utils.ReadGlobalSettings().Experiments)
if err == nil {
server, err := serversHandler.CreateServer(password)
if err != nil {
log.Errorf("Could not create new server: %s\n", err)
} else {
json := serversHandler.SeverToJson(server.Onion())
application.GetPrimaryBus().Publish(event.NewEventList(servers.NewServer, event.Data, json))
}
}
}
//export c_DeleteServer
func c_DeleteServer(onionPtr *C.char, onionLen C.int, currentPasswordPtr *C.char, currentPasswordLen C.int) {
DeleteServer(C.GoStringN(onionPtr, onionLen), C.GoStringN(currentPasswordPtr, currentPasswordLen))
}
func DeleteServer(onion string, currentPassword string) {
serversHandler, err := servers.ExperimentGate(utils.ReadGlobalSettings().Experiments)
if err == nil {
serversHandler.ShutdownServer(onion)
application.GetPrimaryBus().Publish(event.NewEventList(servers.ServerIntentUpdate, servers.Intent, servers.IntentDisabled))
serversHandler.DeleteServer(onion, currentPassword)
// TODO HANDLE err from DeletServer?
}
}
//export c_LaunchServers
func c_LaunchServers() {
LaunchServers()
}
func LaunchServers() {
serversHandler, err := servers.ExperimentGate(utils.ReadGlobalSettings().Experiments)
if err == nil {
for _, onion := range serversHandler.ListServers() {
autostart := false
if s := serversHandler.GetServer(onion); s != nil {
autostart = s.GetAttribute(server.AttrAutostart) == "true"
}
if autostart {
LaunchServer(onion)
}
}
}
}
//export c_LaunchServer
func c_LaunchServer(onionPtr *C.char, onionLen C.int) {
LaunchServer(C.GoStringN(onionPtr, onionLen))
}
func LaunchServer(onion string) {
serversHandler, err := servers.ExperimentGate(utils.ReadGlobalSettings().Experiments)
if err == nil {
serversHandler.LaunchServer(onion)
application.GetPrimaryBus().Publish(event.NewEventList(servers.ServerIntentUpdate, servers.Intent, servers.IntentEnabled))
}
}
//export c_ShutdownServer
func c_ShutdownServer(onionPtr *C.char, onionLen C.int) {
ShutdownServer(C.GoStringN(onionPtr, onionLen))
}
func ShutdownServer(onion string) {
serversHandler, err := servers.ExperimentGate(utils.ReadGlobalSettings().Experiments)
if err == nil {
serversHandler.ShutdownServer(onion)
application.GetPrimaryBus().Publish(event.NewEventList(servers.ServerIntentUpdate, servers.Intent, servers.IntentDisabled))
}
}
//export c_ShutdownServers
func c_ShutdownServers() {
ShutdownServers()
}
func ShutdownServers() {
serversHandler, err := servers.ExperimentGate(utils.ReadGlobalSettings().Experiments)
if err == nil {
for _, onion := range serversHandler.ListServers() {
ShutdownServer(onion)
}
}
}
// ***** END Server APIs *****
// Leave as is, needed by ffi
func main() {}

View File

@ -202,74 +202,6 @@ func getLastMessageTime(tl *model.Timeline) int {
return int(tl.Messages[len(tl.Messages)-1].Timestamp.Unix())
}
/*
// AddProfile adds a new profile to the UI
func AddProfile(gcd *GrandCentralDispatcher, handle string) {
p := the.CwtchApp.GetPeer(handle)
if p != nil {
nick, exists := p.GetAttribute(attr.GetPublicScope(constants.Name))
if !exists {
nick = handle
}
picVal, ok := p.GetAttribute(attr.GetPublicScope(constants.Picture))
if !ok {
picVal = ImageToString(NewImage(RandomProfileImage(handle), TypeImageDistro))
}
pic, err := StringToImage(picVal)
if err != nil {
pic = NewImage(RandomProfileImage(handle), TypeImageDistro)
}
picPath := getPicturePath(pic)
tag, _ := p.GetAttribute(app.AttributeTag)
online, _ := p.GetAttribute(attr.GetLocalScope(constants.PeerOnline))
log.Debugf("AddProfile %v %v %v %v %v\n", handle, nick, picPath, tag, online)
gcd.AddProfile(handle, nick, picPath, tag, online == event.True)
}
}*/
/*
type manager struct {
gcd *GrandCentralDispatcher
profile string
}
// Manager is a middleware helper for entities like peer event listeners wishing to trigger ui changes (via the gcd)
// each manager is for one profile/peer
// manager takes minimal arguments and builds the full struct of data (usually pulled from a cwtch peer) required to call the GCD to perform the ui action
// manager also performs call filtering based on UI state: users of manager can safely always call it on events and not have to worry about weather the relevant ui is active
// ie: you can always safely call AddMessage even if in the ui a different profile is selected. manager will check with gcd, and if the correct conditions are not met, it will not call on gcd to update the ui incorrectly
type Manager interface {
Acknowledge(handle, mID string)
AddContact(Handle string)
AddSendMessageError(peer string, signature string, err string)
AddMessage(handle string, from string, message string, fromMe bool, messageID string, timestamp time.Time, Acknowledged bool)
ReloadProfiles()
UpdateContactDisplayName(handle string)
UpdateContactPicture(handle string)
UpdateContactStatus(handle string, status int, loading bool)
UpdateContactAttribute(handle, key, value string)
ChangePasswordResponse(error bool)
AboutToAddMessage()
MessageJustAdded()
StoreAndNotify(peer.CwtchPeer, string, string, time.Time, string)
UpdateNetworkStatus(online bool)
}
// NewManager returns a new Manager interface for a profile to the gcd
func NewManager(profile string, gcd *GrandCentralDispatcher) Manager {
return &manager{gcd: gcd, profile: profile}
}
*/
// EnrichNewPeer populates required data for use by frontend
// uiManager.AddContact(onion)
// (handle string, displayName string, image string, badge int, status int, authorization string, loading bool, lastMsgTime int)
@ -316,80 +248,4 @@ func EnrichNewPeer(handle string, ph *PeerHelper, ev *EventProfileEnvelope) erro
return errors.New("not a peer or group")
}
return nil
}
/*
// AddSendMessageError adds an error not and icon to a message in a conversation in the ui for the message identified by the peer/sig combo
func (this *manager) AddSendMessageError(peer string, signature string, err string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.DoIfConversation(peer, func() {
log.Debugf("Received Error Sending Message: %v", err)
// FIXME: Sometimes, for the first Peer message we send our error beats our message to the UI
time.Sleep(time.Second * 1)
this.gcd.GroupSendError(signature, err)
})
})
}
func (this *manager) AboutToAddMessage() {
this.gcd.TimelineInterface.AddMessage(this.gcd.TimelineInterface.num())
}
func (this *manager) MessageJustAdded() {
this.gcd.TimelineInterface.RequestEIR()
}*/
/*
// AddMessage adds a message to the message pane for the supplied conversation if it is active
func (this *manager) AddMessage(handle string, from string, message string, fromMe bool, messageID string, timestamp time.Time, Acknowledged bool) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.DoIfConversation(handle, func() {
updateLastReadTime(handle)
// If the message is not from the user then add it, otherwise, just acknowledge.
if !fromMe || !Acknowledged {
this.gcd.TimelineInterface.AddMessage(this.gcd.TimelineInterface.num() - 1)
this.gcd.TimelineInterface.RequestEIR()
} else {
this.gcd.Acknowledged(messageID)
}
})
this.gcd.IncContactUnreadCount(handle)
})
if !fromMe {
this.gcd.Notify(handle)
}
}
func (this *manager) ReloadProfiles() {
this.gcd.reloadProfileList()
}
// UpdateContactDisplayName updates a contact's display name in the contact list and conversations
func (this *manager) UpdateContactDisplayName(handle string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.UpdateContactDisplayName(handle, GetNick(handle))
})
}
// UpdateContactPicture updates a contact's picture in the contact list and conversations
func (this *manager) UpdateContactPicture(handle string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.UpdateContactPicture(handle, GetProfilePic(handle))
})
}
// UpdateContactAttribute update's a contacts attribute in the ui
func (this *manager) UpdateContactAttribute(handle, key, value string) {
this.gcd.DoIfProfile(this.profile, func() {
this.gcd.UpdateContactAttribute(handle, key, value)
})
}
func (this *manager) ChangePasswordResponse(error bool) {
this.gcd.ChangePasswordResponse(error)
}
func (this *manager) UpdateNetworkStatus(online bool) {
this.gcd.UpdateProfileNetworkStatus(this.profile, online)
}
*/
}