From e464e11ab924e8009dda37ebea60082e7671cd59 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Tue, 24 Jan 2023 13:41:03 +0100 Subject: [PATCH 001/130] GODT-2224: Refactor bridge sync to use less memory Updates go-proton-api and Gluon to includes memory reduction changes and modify the sync process to take into account how much memory is used during the sync stage. The sync process now has an extra stage which first download the message metada to ensure that we only download up to `syncMaxDownloadRequesMem` messages or 250 messages total. This allows for scaling the download request automatically to accommodate many small or few very large messages. The IDs are then sent to a download go-routine which downloads the message and its attachments. The result is then forwarded to another go-routine which builds the actual message. This stage tries to ensure that we don't use more than `syncMaxMessageBuildingMem` to build these messages. Finally the result is sent to a last go-routine which applies the changes to Gluon and waits for them to be completed. The new process is currently limited to 2GB. Dynamic scaling will be implemented in a follow up. For systems with less than 2GB of memory we limit the values to a set of values that is known to work. --- COPYING_NOTES.md | 2 + go.mod | 6 +- go.sum | 12 +- internal/app/app.go | 26 ++- internal/app/migration.go | 8 - internal/app/migration_test.go | 2 - internal/bridge/api.go | 2 - internal/bridge/api_default.go | 3 +- internal/bridge/api_qa.go | 3 +- internal/bridge/bridge.go | 2 +- internal/bridge/imap.go | 1 - internal/bridge/user.go | 1 - internal/user/events.go | 9 +- internal/user/imap.go | 4 +- internal/user/sync.go | 360 ++++++++++++++++++++++++++----- internal/user/sync_build.go | 8 +- internal/user/sync_flusher.go | 63 ------ internal/user/types.go | 5 + internal/user/user.go | 3 - internal/user/user_test.go | 2 +- internal/vault/settings.go | 24 --- internal/vault/settings_test.go | 9 - internal/vault/types_settings.go | 21 -- pkg/message/build.go | 208 ++++++++++-------- 24 files changed, 481 insertions(+), 303 deletions(-) delete mode 100644 internal/user/sync_flusher.go diff --git a/COPYING_NOTES.md b/COPYING_NOTES.md index 2269bf30..ce628759 100644 --- a/COPYING_NOTES.md +++ b/COPYING_NOTES.md @@ -53,6 +53,7 @@ Proton Mail Bridge includes the following 3rd party software: * [html2text](https://github.com/jaytaylor/html2text) available under [license](https://github.com/jaytaylor/html2text/blob/master/LICENSE) * [go-keychain](https://github.com/keybase/go-keychain) available under [license](https://github.com/keybase/go-keychain/blob/master/LICENSE) * [dns](https://github.com/miekg/dns) available under [license](https://github.com/miekg/dns/blob/master/LICENSE) +* [memory](https://github.com/pbnjay/memory) available under [license](https://github.com/pbnjay/memory/blob/master/LICENSE) * [errors](https://github.com/pkg/errors) available under [license](https://github.com/pkg/errors/blob/master/LICENSE) * [profile](https://github.com/pkg/profile) available under [license](https://github.com/pkg/profile/blob/master/LICENSE) * [logrus](https://github.com/sirupsen/logrus) available under [license](https://github.com/sirupsen/logrus/blob/master/LICENSE) @@ -114,6 +115,7 @@ Proton Mail Bridge includes the following 3rd party software: * [reflect2](https://github.com/modern-go/reflect2) available under [license](https://github.com/modern-go/reflect2/blob/master/LICENSE) * [tablewriter](https://github.com/olekukonko/tablewriter) available under [license](https://github.com/olekukonko/tablewriter/blob/master/LICENSE) * [go-toml](https://github.com/pelletier/go-toml/v2) available under [license](https://github.com/pelletier/go-toml/v2/blob/master/LICENSE) +* [lz4](https://github.com/pierrec/lz4/v4) available under [license](https://github.com/pierrec/lz4/v4/blob/master/LICENSE) * [go-difflib](https://github.com/pmezard/go-difflib) available under [license](https://github.com/pmezard/go-difflib/blob/master/LICENSE) * [procfs](https://github.com/prometheus/procfs) available under [license](https://github.com/prometheus/procfs/blob/master/LICENSE) * [uniseg](https://github.com/rivo/uniseg) available under [license](https://github.com/rivo/uniseg/blob/master/LICENSE) diff --git a/go.mod b/go.mod index 00cc0a86..06393d87 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,9 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230127085305-bc2d818d9d13 + github.com/ProtonMail/gluon v0.14.2-0.20230130104154-2c64e59b8f54 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.3.1-0.20230126112849-3c1ac277855e + github.com/ProtonMail/go-proton-api v0.3.1-0.20230130093944-dd1190680368 github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.4.10 github.com/PuerkitoBio/goquery v1.8.0 @@ -35,6 +35,7 @@ require ( github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba github.com/keybase/go-keychain v0.0.0 github.com/miekg/dns v1.1.50 + github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/pkg/errors v0.9.1 github.com/pkg/profile v1.6.0 github.com/sirupsen/logrus v1.9.0 @@ -99,6 +100,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect github.com/pelletier/go-toml/v2 v2.0.5 // indirect + github.com/pierrec/lz4/v4 v4.1.17 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect github.com/rivo/uniseg v0.4.2 // indirect diff --git a/go.sum b/go.sum index 6456748f..7ed408bd 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230127085305-bc2d818d9d13 h1:rljNZVgfq/F1LLyJ4NmCfEzWayC/rk+l9QgJjtQTLKI= -github.com/ProtonMail/gluon v0.14.2-0.20230127085305-bc2d818d9d13/go.mod h1:z2AxLIiBCT1K+0OBHyaDI7AEaO5qI6/BEC2TE42vs4Q= +github.com/ProtonMail/gluon v0.14.2-0.20230130104154-2c64e59b8f54 h1:uUg8CDiYTMlbvGijzoN0fb72vwDJD7hMjgNTbmAHxRc= +github.com/ProtonMail/gluon v0.14.2-0.20230130104154-2c64e59b8f54/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= @@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230126112849-3c1ac277855e h1:UkfLQc44UvknNCLoBEZb1qg7zfVWVLMvCE/LtdVEcAw= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230126112849-3c1ac277855e/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230130093944-dd1190680368 h1:XWPaCK8ctgpvI+ZAYcsFiYWbuvkv3T4+WZq0o6Gnt2s= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230130093944-dd1190680368/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= @@ -314,9 +314,13 @@ github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn github.com/olekukonko/tablewriter v0.0.5 h1:P2Ga83D34wi1o9J6Wh1mRuqd4mF/x/lgBS7N7AbDhec= github.com/olekukonko/tablewriter v0.0.5/go.mod h1:hPp6KlRPjbx+hW8ykQs1w3UBbZlj6HuIJcUGPhkA7kY= github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= +github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= +github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= diff --git a/internal/app/app.go b/internal/app/app.go index 92289afa..db93442f 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -205,7 +205,7 @@ func run(c *cli.Context) error { //nolint:funlen // Ensure we are the only instance running. return withSingleInstance(locations, version, func() error { // Unlock the encrypted vault. - return WithVault(locations, func(vault *vault.Vault, insecure, corrupt bool) error { + return WithVault(locations, func(v *vault.Vault, insecure, corrupt bool) error { // Report insecure vault. if insecure { _ = reporter.ReportMessageWithContext("Vault is insecure", map[string]interface{}{}) @@ -216,27 +216,39 @@ func run(c *cli.Context) error { //nolint:funlen _ = reporter.ReportMessageWithContext("Vault is corrupt", map[string]interface{}{}) } - if !vault.Migrated() { + // Force re-sync if last version <= 3.0.12 due to chances in the gluon cache format. + if lastVersion := v.GetLastVersion(); lastVersion != nil { + versionWithLZ4Cache := semver.MustParse("3.0.13") + if lastVersion.LessThan(versionWithLZ4Cache) { + if err := v.ForUser(1, func(user *vault.User) error { + return user.ClearSyncStatus() + }); err != nil { + logrus.WithError(err).Error("Failed to force resync on user") + } + } + } + + if !v.Migrated() { // Migrate old settings into the vault. - if err := migrateOldSettings(vault); err != nil { + if err := migrateOldSettings(v); err != nil { logrus.WithError(err).Error("Failed to migrate old settings") } // Migrate old accounts into the vault. - if err := migrateOldAccounts(locations, vault); err != nil { + if err := migrateOldAccounts(locations, v); err != nil { logrus.WithError(err).Error("Failed to migrate old accounts") } // The vault has been migrated. - if err := vault.SetMigrated(); err != nil { + if err := v.SetMigrated(); err != nil { logrus.WithError(err).Error("Failed to mark vault as migrated") } } // Load the cookies from the vault. - return withCookieJar(vault, func(cookieJar http.CookieJar) error { + return withCookieJar(v, func(cookieJar http.CookieJar) error { // Create a new bridge instance. - return withBridge(c, exe, locations, version, identifier, crashHandler, reporter, vault, cookieJar, func(b *bridge.Bridge, eventCh <-chan events.Event) error { + return withBridge(c, exe, locations, version, identifier, crashHandler, reporter, v, cookieJar, func(b *bridge.Bridge, eventCh <-chan events.Event) error { if insecure { logrus.Warn("The vault key could not be retrieved; the vault will not be encrypted") b.PushError(bridge.ErrVaultInsecure) diff --git a/internal/app/migration.go b/internal/app/migration.go index 1124de9b..7f187b1b 100644 --- a/internal/app/migration.go +++ b/internal/app/migration.go @@ -265,14 +265,6 @@ func migratePrefsToVault(vault *vault.Vault, b []byte) error { errs = multierror.Append(errs, fmt.Errorf("failed to migrate show all mail: %w", err)) } - if err := vault.SetSyncWorkers(prefs.FetchWorkers); err != nil { - errs = multierror.Append(errs, fmt.Errorf("failed to migrate sync workers: %w", err)) - } - - if err := vault.SetSyncAttPool(prefs.AttachmentWorkers); err != nil { - errs = multierror.Append(errs, fmt.Errorf("failed to migrate sync attachment pool: %w", err)) - } - if err := vault.SetCookies([]byte(prefs.Cookies)); err != nil { errs = multierror.Append(errs, fmt.Errorf("failed to migrate cookies: %w", err)) } diff --git a/internal/app/migration_test.go b/internal/app/migration_test.go index a9e128e9..fd0b41e1 100644 --- a/internal/app/migration_test.go +++ b/internal/app/migration_test.go @@ -68,8 +68,6 @@ func TestMigratePrefsToVault(t *testing.T) { require.True(t, vault.GetAutostart()) // Check that the other app settings have been migrated. - require.Equal(t, 16, vault.SyncWorkers()) - require.Equal(t, 16, vault.SyncAttPool()) require.False(t, vault.GetProxyAllowed()) require.False(t, vault.GetShowAllMail()) diff --git a/internal/bridge/api.go b/internal/bridge/api.go index 1f0edaca..cbe2f2be 100644 --- a/internal/bridge/api.go +++ b/internal/bridge/api.go @@ -32,14 +32,12 @@ func defaultAPIOptions( version *semver.Version, cookieJar http.CookieJar, transport http.RoundTripper, - poolSize int, ) []proton.Option { return []proton.Option{ proton.WithHostURL(apiURL), proton.WithAppVersion(constants.AppVersion(version.Original())), proton.WithCookieJar(cookieJar), proton.WithTransport(transport), - proton.WithAttPoolSize(poolSize), proton.WithLogger(logrus.StandardLogger()), } } diff --git a/internal/bridge/api_default.go b/internal/bridge/api_default.go index a71433cc..6f800d77 100644 --- a/internal/bridge/api_default.go +++ b/internal/bridge/api_default.go @@ -32,7 +32,6 @@ func newAPIOptions( version *semver.Version, cookieJar http.CookieJar, transport http.RoundTripper, - poolSize int, ) []proton.Option { - return defaultAPIOptions(apiURL, version, cookieJar, transport, poolSize) + return defaultAPIOptions(apiURL, version, cookieJar, transport) } diff --git a/internal/bridge/api_qa.go b/internal/bridge/api_qa.go index cf182330..618ce42e 100644 --- a/internal/bridge/api_qa.go +++ b/internal/bridge/api_qa.go @@ -33,9 +33,8 @@ func newAPIOptions( version *semver.Version, cookieJar http.CookieJar, transport http.RoundTripper, - poolSize int, ) []proton.Option { - opt := defaultAPIOptions(apiURL, version, cookieJar, transport, poolSize) + opt := defaultAPIOptions(apiURL, version, cookieJar, transport) if host := os.Getenv("BRIDGE_API_HOST"); host != "" { opt = append(opt, proton.WithHostURL(host)) diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index 886c740b..1a6de766 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -145,7 +145,7 @@ func New( //nolint:funlen logSMTP bool, // whether to log SMTP activity ) (*Bridge, <-chan events.Event, error) { // api is the user's API manager. - api := proton.New(newAPIOptions(apiURL, curVersion, cookieJar, roundTripper, vault.SyncAttPool())...) + api := proton.New(newAPIOptions(apiURL, curVersion, cookieJar, roundTripper)...) // tasks holds all the bridge's background tasks. tasks := async.NewGroup(context.Background(), crashHandler) diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index 928f852f..b9fd540f 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -310,7 +310,6 @@ func (*storeBuilder) New(path, userID string, passphrase []byte) (store.Store, e return store.NewOnDiskStore( filepath.Join(path, userID), passphrase, - store.WithCompressor(new(store.GZipCompressor)), ) } diff --git a/internal/bridge/user.go b/internal/bridge/user.go index 25a697b7..fa86a313 100644 --- a/internal/bridge/user.go +++ b/internal/bridge/user.go @@ -461,7 +461,6 @@ func (bridge *Bridge) addUserWithVault( bridge.reporter, apiUser, bridge.crashHandler, - bridge.vault.SyncWorkers(), bridge.vault.GetShowAllMail(), ) if err != nil { diff --git a/internal/user/events.go b/internal/user/events.go index 1f75c043..5311c8bd 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -18,6 +18,7 @@ package user import ( + "bytes" "context" "errors" "fmt" @@ -502,7 +503,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto } func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.MessageEvent) ([]imap.Update, error) { - full, err := user.client.GetFullMessage(ctx, event.Message.ID) + full, err := user.client.GetFullMessage(ctx, event.Message.ID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) if err != nil { // If the message is not found, it means that it has been deleted before we could fetch it. if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status == http.StatusUnprocessableEntity { @@ -521,7 +522,7 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.Mes var update imap.Update if err := withAddrKR(user.apiUser, user.apiAddrs[event.Message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error { - res := buildRFC822(user.apiLabels, full, addrKR) + res := buildRFC822(user.apiLabels, full, addrKR, new(bytes.Buffer)) if res.err != nil { user.log.WithError(err).Error("Failed to build RFC822 message") @@ -599,7 +600,7 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event proton.Messa "subject": logging.Sensitive(event.Message.Subject), }).Info("Handling draft updated event") - full, err := user.client.GetFullMessage(ctx, event.Message.ID) + full, err := user.client.GetFullMessage(ctx, event.Message.ID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) if err != nil { // If the message is not found, it means that it has been deleted before we could fetch it. if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status == http.StatusUnprocessableEntity { @@ -613,7 +614,7 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event proton.Messa var update imap.Update if err := withAddrKR(user.apiUser, user.apiAddrs[event.Message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error { - res := buildRFC822(user.apiLabels, full, addrKR) + res := buildRFC822(user.apiLabels, full, addrKR, new(bytes.Buffer)) if res.err != nil { logrus.WithError(err).Error("Failed to build RFC822 message") diff --git a/internal/user/imap.go b/internal/user/imap.go index ab17f2f8..9de879e2 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -336,7 +336,7 @@ func (conn *imapConnector) CreateMessage( } func (conn *imapConnector) GetMessageLiteral(ctx context.Context, id imap.MessageID) ([]byte, error) { - msg, err := conn.client.GetFullMessage(ctx, string(id)) + msg, err := conn.client.GetFullMessage(ctx, string(id), newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) if err != nil { return nil, err } @@ -538,7 +538,7 @@ func (conn *imapConnector) importMessage( var err error - if full, err = conn.client.GetFullMessage(ctx, messageID); err != nil { + if full, err = conn.client.GetFullMessage(ctx, messageID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()); err != nil { return fmt.Errorf("failed to fetch message: %w", err) } diff --git a/internal/user/sync.go b/internal/user/sync.go index 6e4faeea..0735ed83 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -18,6 +18,7 @@ package user import ( + "bytes" "context" "fmt" "runtime" @@ -25,6 +26,7 @@ import ( "time" "github.com/ProtonMail/gluon/imap" + "github.com/ProtonMail/gluon/logging" "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/go-proton-api" @@ -35,16 +37,12 @@ import ( "github.com/bradenaw/juniper/parallel" "github.com/bradenaw/juniper/xslices" "github.com/google/uuid" + "github.com/pbnjay/memory" "github.com/sirupsen/logrus" "golang.org/x/exp/maps" "golang.org/x/exp/slices" ) -const ( - maxUpdateSize = 1 << 27 // 128 MiB - maxBatchSize = 1 << 8 // 256 -) - // doSync begins syncing the users data. // It first ensures the latest event ID is known; if not, it fetches it. // It sends a SyncStarted event and then either SyncFinished or SyncFailed @@ -143,7 +141,6 @@ func (user *User) sync(ctx context.Context) error { addrKRs, user.updateCh, user.eventCh, - user.syncWorkers, ); err != nil { return fmt.Errorf("failed to sync messages: %w", err) } @@ -212,7 +209,15 @@ func syncLabels(ctx context.Context, apiLabels map[string]proton.Label, updateCh return nil } -// nolint:funlen +const Kilobyte = uint64(1024) +const Megabyte = 1024 * Kilobyte +const Gigabyte = 1024 * Megabyte + +func toMB(v uint64) float64 { + return float64(v) / float64(Megabyte) +} + +// nolint:funlen,gocyclo func syncMessages( ctx context.Context, userID string, @@ -224,7 +229,6 @@ func syncMessages( addrKRs map[string]*crypto.KeyRing, updateCh map[string]*queue.QueuedChannel[imap.Update], eventCh *queue.QueuedChannel[events.Event], - syncWorkers int, ) error { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -235,78 +239,319 @@ func syncMessages( logrus.WithFields(logrus.Fields{ "messages": len(messageIDs), - "workers": syncWorkers, "numCPU": runtime.NumCPU(), }).Info("Starting message sync") // Create the flushers, one per update channel. - flushers := make(map[string]*flusher, len(updateCh)) - - for addrID, updateCh := range updateCh { - flushers[addrID] = newFlusher(updateCh, maxUpdateSize) - } // Create a reporter to report sync progress updates. syncReporter := newSyncReporter(userID, eventCh, len(messageIDs), time.Second) defer syncReporter.done() - type flushUpdate struct { - messageID string - pushedUpdates []imap.Update - batchLen int + // Expected mem usage for this whole process should be the sum of MaxMessageBuildingMem and MaxDownloadRequestMem + // times x due to pipeline and all additional memory used by network requests and compression+io. + + // There's no point in using more than 128MB of download data per stage, after that we reach a point of diminishing + // returns as we can't keep the pipeline fed fast enough. + const MaxDownloadRequestMem = 128 * Megabyte + + // Any lower than this and we may fail to download messages. + const MinDownloadRequestMem = 40 * Megabyte + + // This value can be increased to your hearts content. The more system memory the user has, the more messages + // we can build in parallel. + const MaxMessageBuildingMem = 128 * Megabyte + const MinMessageBuildingMem = 64 * Megabyte + + // Maximum recommend value for parallel downloads by the API team. + const maxParallelDownloads = 20 + + totalMemory := memory.TotalMemory() + logrus.Debugf("Total System Memory: %v", toMB(totalMemory)) + + syncMaxDownloadRequestMem := MaxDownloadRequestMem + syncMaxMessageBuildingMem := MaxMessageBuildingMem + + // If less than 2GB available try and limit max memory to 512 MB + if totalMemory < 2*Gigabyte { + if totalMemory < 800*Megabyte { + logrus.Warnf("System has less than 800MB of memory, you may experience issues sycing large mailboxes") + } + syncMaxDownloadRequestMem = MinDownloadRequestMem + syncMaxMessageBuildingMem = MinMessageBuildingMem + } else { + // Increasing the max download capacity has very little effect on sync speed. We could increase the download + // memory but the user would see less sync notifications. A smaller value here leads to more frequent + // updates. Additionally, most of ot sync time is spent in the message building. + syncMaxDownloadRequestMem = MaxDownloadRequestMem + // Currently limited so that if a user has multiple accounts active it also doesn't cause excessive memory usage. + syncMaxMessageBuildingMem = MaxMessageBuildingMem } + logrus.Debugf("Max memory usage for sync Download=%vMB Building=%vMB Predicted Max Total=%vMB", + toMB(syncMaxDownloadRequestMem), + toMB(syncMaxMessageBuildingMem), + toMB((syncMaxMessageBuildingMem*4)+(syncMaxDownloadRequestMem*4)), + ) + + type flushUpdate struct { + messageID string + err error + batchLen int + } + + type downloadRequest struct { + ids []string + expectedSize uint64 + err error + } + + type downloadedMessageBatch struct { + batch []proton.FullMessage + } + + type builtMessageBatch struct { + batch []*buildRes + } + + downloadCh := make(chan downloadRequest) + + buildCh := make(chan downloadedMessageBatch) + // The higher this value, the longer we can continue our download iteration before being blocked on channel writes // to the update flushing goroutine. - flushCh := make(chan []*buildRes, 2) + flushCh := make(chan builtMessageBatch) - // Allow up to 4 batched wait requests. - flushUpdateCh := make(chan flushUpdate, 4) + flushUpdateCh := make(chan flushUpdate) - errorCh := make(chan error, syncWorkers) + errorCh := make(chan error, maxParallelDownloads+2) + + // Go routine in charge of downloading message metadata + logging.GoAnnotated(ctx, func(ctx context.Context) { + defer close(downloadCh) + const MetadataDataPageSize = 150 + + var downloadReq downloadRequest + downloadReq.ids = make([]string, 0, MetadataDataPageSize) + + metadataChunks := xslices.Chunk(messageIDs, MetadataDataPageSize) + for i, metadataChunk := range metadataChunks { + logrus.Debugf("Metadata Request (%v of %v), previous: %v", i, len(metadataChunks), len(downloadReq.ids)) + metadata, err := client.GetMessageMetadataPage(ctx, 0, len(metadataChunk), proton.MessageFilter{ID: metadataChunk}) + if err != nil { + downloadReq.err = err + downloadCh <- downloadReq + return + } + + if ctx.Err() != nil { + downloadReq.err = err + downloadCh <- downloadReq + return + } + + // Build look up table so that messages are processed in the same order. + metadataMap := make(map[string]int, len(metadata)) + for i, v := range metadata { + metadataMap[v.ID] = i + } + + for i, id := range metadataChunk { + m := &metadata[metadataMap[id]] + nextSize := downloadReq.expectedSize + uint64(m.Size) + if nextSize >= syncMaxDownloadRequestMem || len(downloadReq.ids) >= 256 { + logrus.Debugf("Download Request Sent at %v of %v", i, len(metadata)) + select { + case downloadCh <- downloadReq: + + case <-ctx.Done(): + return + } + downloadReq.expectedSize = 0 + downloadReq.ids = make([]string, 0, MetadataDataPageSize) + nextSize = uint64(m.Size) + } + downloadReq.ids = append(downloadReq.ids, id) + downloadReq.expectedSize = nextSize + } + } + + if len(downloadReq.ids) != 0 { + logrus.Debugf("Sending remaining download request") + select { + case downloadCh <- downloadReq: + + case <-ctx.Done(): + return + } + } + }, logging.Labels{"sync-stage": "meta-data"}) // Goroutine in charge of downloading and building messages in maxBatchSize batches. - go func() { - defer close(flushCh) + logging.GoAnnotated(ctx, func(ctx context.Context) { + defer close(buildCh) defer close(errorCh) + defer func() { + logrus.Debugf("sync downloader exit") + }() + + for request := range downloadCh { + logrus.Debugf("Download request: %v MB:%v", len(request.ids), toMB(request.expectedSize)) + if request.err != nil { + errorCh <- request.err + return + } - for _, batch := range xslices.Chunk(messageIDs, maxBatchSize) { if ctx.Err() != nil { errorCh <- ctx.Err() return } - result, err := parallel.MapContext(ctx, syncWorkers, batch, func(ctx context.Context, id string) (*buildRes, error) { - msg, err := client.GetFullMessage(ctx, id) + result, err := parallel.MapContext(ctx, maxParallelDownloads, request.ids, func(ctx context.Context, id string) (proton.FullMessage, error) { + var result proton.FullMessage + + msg, err := client.GetMessage(ctx, id) if err != nil { - return nil, err + return proton.FullMessage{}, err } - if ctx.Err() != nil { - return nil, ctx.Err() + var attachmentSize int64 + for _, a := range msg.Attachments { + attachmentSize += a.Size } - return buildRFC822(apiLabels, msg, addrKRs[msg.AddressID]), nil + // allocate attachment data. + result.AttData = make([][]byte, len(msg.Attachments)) + + for i, a := range msg.Attachments { + var buffer bytes.Buffer + buffer.Grow(int(a.Size)) + if err := client.GetAttachmentInto(ctx, a.ID, &buffer); err != nil { + return proton.FullMessage{}, err + } + + result.AttData[i] = buffer.Bytes() + } + + result.Message = msg + + return result, nil }) if err != nil { errorCh <- err return } + select { + case buildCh <- downloadedMessageBatch{ + batch: result, + }: + + case <-ctx.Done(): + return + } + } + }, logging.Labels{"sync-stage": "download"}) + + // Goroutine which builds messages after they have been downloaded + logging.GoAnnotated(ctx, func(ctx context.Context) { + defer close(flushCh) + defer func() { + logrus.Debugf("sync builder exit") + }() + + maxMessagesInParallel := runtime.NumCPU() + + for buildBatch := range buildCh { if ctx.Err() != nil { - errorCh <- ctx.Err() return } - flushCh <- result + var expectedMemUsage uint64 + var chunks [][]proton.FullMessage + + { + var lastIndex int + var index int + for _, v := range buildBatch.batch { + var dataSize uint64 + for _, a := range v.Attachments { + dataSize += uint64(a.Size) + } + + // 2x increase for attachment due to extra memory needed for decrypting and writing + // in memory buffer. + dataSize *= 2 + dataSize += uint64(len(v.Body)) + + nextMemSize := expectedMemUsage + dataSize + if nextMemSize >= syncMaxMessageBuildingMem { + chunks = append(chunks, buildBatch.batch[lastIndex:index]) + lastIndex = index + expectedMemUsage = dataSize + } else { + expectedMemUsage = nextMemSize + } + + index++ + } + + if index < len(buildBatch.batch) { + chunks = append(chunks, buildBatch.batch[index:]) + } else if index == len(buildBatch.batch) && len(chunks) == 0 { + chunks = [][]proton.FullMessage{buildBatch.batch} + } + } + + for index, chunk := range chunks { + result, err := parallel.MapContext(ctx, maxMessagesInParallel, chunk, func(ctx context.Context, msg proton.FullMessage) (*buildRes, error) { + return buildRFC822(apiLabels, msg, addrKRs[msg.AddressID], new(bytes.Buffer)), nil + }) + if err != nil { + return + } + + logrus.Debugf("Build request: %v of %v", index, len(chunks)) + + select { + case flushCh <- builtMessageBatch{result}: + + case <-ctx.Done(): + return + } + } } - }() + }, logging.Labels{"sync-stage": "builder"}) // Goroutine which converts the messages into updates and builds a waitable structure for progress tracking. - go func() { + logging.GoAnnotated(ctx, func(ctx context.Context) { defer close(flushUpdateCh) - for batch := range flushCh { - for _, res := range batch { + defer func() { + logrus.Debugf("sync flush exit") + }() + + type updateTargetInfo struct { + queueIndex int + ch *queue.QueuedChannel[imap.Update] + } + + pendingUpdates := make([][]*imap.MessageCreated, len(updateCh)) + addressToIndex := make(map[string]updateTargetInfo) + + { + i := 0 + for addrID, updateCh := range updateCh { + addressToIndex[addrID] = updateTargetInfo{ + ch: updateCh, + queueIndex: i, + } + i++ + } + } + + for downloadBatch := range flushCh { + logrus.Debugf("Flush batch: %v", len(downloadBatch.batch)) + for _, res := range downloadBatch.batch { if res.err != nil { if err := vault.AddFailedMessageID(res.messageID); err != nil { logrus.WithError(err).Error("Failed to add failed message ID") @@ -327,31 +572,38 @@ func syncMessages( } } - flushers[res.addressID].push(res.update) + targetInfo := addressToIndex[res.addressID] + pendingUpdates[targetInfo.queueIndex] = append(pendingUpdates[targetInfo.queueIndex], res.update) } - var pushedUpdates []imap.Update - for _, flusher := range flushers { - flusher.flush() - pushedUpdates = append(pushedUpdates, flusher.collectPushedUpdates()...) + for _, info := range addressToIndex { + up := imap.NewMessagesCreated(true, pendingUpdates[info.queueIndex]...) + info.ch.Enqueue(up) + + err, ok := up.WaitContext(ctx) + if ok && err != nil { + flushUpdateCh <- flushUpdate{ + err: fmt.Errorf("failed to apply sync update to gluon %v: %w", up.String(), err), + } + return + } + + pendingUpdates[info.queueIndex] = pendingUpdates[info.queueIndex][:0] } - flushUpdateCh <- flushUpdate{ - messageID: batch[0].messageID, - pushedUpdates: pushedUpdates, - batchLen: len(batch), + select { + case flushUpdateCh <- flushUpdate{ + messageID: downloadBatch.batch[0].messageID, + err: nil, + batchLen: len(downloadBatch.batch), + }: + case <-ctx.Done(): + return } } - }() + }, logging.Labels{"sync-stage": "flush"}) for flushUpdate := range flushUpdateCh { - for _, up := range flushUpdate.pushedUpdates { - err, ok := up.WaitContext(ctx) - if ok && err != nil { - return fmt.Errorf("failed to apply sync update to gluon %v: %w", up.String(), err) - } - } - if err := vault.SetLastMessageID(flushUpdate.messageID); err != nil { return fmt.Errorf("failed to set last synced message ID: %w", err) } diff --git a/internal/user/sync_build.go b/internal/user/sync_build.go index e3d87a5e..93309c35 100644 --- a/internal/user/sync_build.go +++ b/internal/user/sync_build.go @@ -48,16 +48,18 @@ func defaultJobOpts() message.JobOptions { } } -func buildRFC822(apiLabels map[string]proton.Label, full proton.FullMessage, addrKR *crypto.KeyRing) *buildRes { +func buildRFC822(apiLabels map[string]proton.Label, full proton.FullMessage, addrKR *crypto.KeyRing, buffer *bytes.Buffer) *buildRes { var ( update *imap.MessageCreated err error ) - if literal, buildErr := message.BuildRFC822(addrKR, full.Message, full.AttData, defaultJobOpts()); buildErr != nil { + buffer.Grow(full.Size) + + if buildErr := message.BuildRFC822Into(addrKR, full.Message, full.AttData, defaultJobOpts(), buffer); buildErr != nil { update = newMessageCreatedFailedUpdate(apiLabels, full.MessageMetadata, buildErr) err = buildErr - } else if created, parseErr := newMessageCreatedUpdate(apiLabels, full.MessageMetadata, literal); parseErr != nil { + } else if created, parseErr := newMessageCreatedUpdate(apiLabels, full.MessageMetadata, buffer.Bytes()); parseErr != nil { update = newMessageCreatedFailedUpdate(apiLabels, full.MessageMetadata, parseErr) err = parseErr } else { diff --git a/internal/user/sync_flusher.go b/internal/user/sync_flusher.go deleted file mode 100644 index 0c0dd2dd..00000000 --- a/internal/user/sync_flusher.go +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) 2023 Proton AG -// -// This file is part of Proton Mail Bridge. -// -// Proton Mail Bridge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Proton Mail Bridge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Proton Mail Bridge. If not, see . - -package user - -import ( - "github.com/ProtonMail/gluon/imap" - "github.com/ProtonMail/gluon/queue" -) - -type flusher struct { - updateCh *queue.QueuedChannel[imap.Update] - updates []*imap.MessageCreated - pushedUpdates []imap.Update - - maxUpdateSize int - curChunkSize int -} - -func newFlusher(updateCh *queue.QueuedChannel[imap.Update], maxUpdateSize int) *flusher { - return &flusher{ - updateCh: updateCh, - maxUpdateSize: maxUpdateSize, - } -} - -func (f *flusher) push(update *imap.MessageCreated) { - f.updates = append(f.updates, update) - - if f.curChunkSize += len(update.Literal); f.curChunkSize >= f.maxUpdateSize { - f.flush() - } -} - -func (f *flusher) flush() { - if len(f.updates) > 0 { - update := imap.NewMessagesCreated(true, f.updates...) - f.updateCh.Enqueue(update) - f.updates = nil - f.curChunkSize = 0 - f.pushedUpdates = append(f.pushedUpdates, update) - } -} - -func (f *flusher) collectPushedUpdates() []imap.Update { - updates := f.pushedUpdates - f.pushedUpdates = nil - return updates -} diff --git a/internal/user/types.go b/internal/user/types.go index 254bf8b9..09478f5e 100644 --- a/internal/user/types.go +++ b/internal/user/types.go @@ -20,6 +20,7 @@ package user import ( "fmt" "reflect" + "runtime" "strings" "github.com/ProtonMail/go-proton-api" @@ -91,3 +92,7 @@ func sortSlice[Item any](items []Item, less func(Item, Item) bool) []Item { return sorted } + +func newProtonAPIScheduler() proton.Scheduler { + return proton.NewParallelScheduler(runtime.NumCPU() / 2) +} diff --git a/internal/user/user.go b/internal/user/user.go index 2c48c97d..abdef220 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -84,7 +84,6 @@ type User struct { pollAPIEventsCh chan chan struct{} goPollAPIEvents func(wait bool) - syncWorkers int showAllMail uint32 } @@ -98,7 +97,6 @@ func New( reporter reporter.Reporter, apiUser proton.User, crashHandler async.PanicHandler, - syncWorkers int, showAllMail bool, ) (*User, error) { //nolint:funlen logrus.WithField("userID", apiUser.ID).Info("Creating new user") @@ -142,7 +140,6 @@ func New( tasks: async.NewGroup(context.Background(), crashHandler), pollAPIEventsCh: make(chan chan struct{}), - syncWorkers: syncWorkers, showAllMail: b32(showAllMail), } diff --git a/internal/user/user_test.go b/internal/user/user_test.go index a1dcd786..13efde1c 100644 --- a/internal/user/user_test.go +++ b/internal/user/user_test.go @@ -216,7 +216,7 @@ func withUser(tb testing.TB, ctx context.Context, _ *server.Server, m *proton.Ma vaultUser, err := vault.AddUser(apiUser.ID, username, username+"@pm.me", apiAuth.UID, apiAuth.RefreshToken, saltedKeyPass) require.NoError(tb, err) - user, err := New(ctx, vaultUser, client, nil, apiUser, nil, vault.SyncWorkers(), true) + user, err := New(ctx, vaultUser, client, nil, apiUser, nil, true) require.NoError(tb, err) defer user.Close() diff --git a/internal/vault/settings.go b/internal/vault/settings.go index c067b33f..904b0374 100644 --- a/internal/vault/settings.go +++ b/internal/vault/settings.go @@ -189,27 +189,3 @@ func (vault *Vault) SetFirstStart(firstStart bool) error { data.Settings.FirstStart = firstStart }) } - -// SyncWorkers returns the number of workers to use for syncing. -func (vault *Vault) SyncWorkers() int { - return vault.get().Settings.SyncWorkers -} - -// SetSyncWorkers sets the number of workers to use for syncing. -func (vault *Vault) SetSyncWorkers(workers int) error { - return vault.mod(func(data *Data) { - data.Settings.SyncWorkers = workers - }) -} - -// SyncAttPool returns the size of the attachment pool. -func (vault *Vault) SyncAttPool() int { - return vault.get().Settings.SyncAttPool -} - -// SetSyncAttPool sets the size of the attachment pool. -func (vault *Vault) SetSyncAttPool(pool int) error { - return vault.mod(func(data *Data) { - data.Settings.SyncAttPool = pool - }) -} diff --git a/internal/vault/settings_test.go b/internal/vault/settings_test.go index 7a661309..4b90b3ba 100644 --- a/internal/vault/settings_test.go +++ b/internal/vault/settings_test.go @@ -202,12 +202,3 @@ func TestVault_Settings_FirstStart(t *testing.T) { // Check the new first start value. require.Equal(t, false, s.GetFirstStart()) } - -func TestVault_Settings_SyncWorkers(t *testing.T) { - // create a new test vault. - s := newVault(t) - - syncWorkers := vault.GetDefaultSyncWorkerCount() - require.Equal(t, syncWorkers, s.SyncWorkers()) - require.Equal(t, syncWorkers, s.SyncAttPool()) -} diff --git a/internal/vault/types_settings.go b/internal/vault/types_settings.go index 47c70654..4ba00f7e 100644 --- a/internal/vault/types_settings.go +++ b/internal/vault/types_settings.go @@ -19,7 +19,6 @@ package vault import ( "math/rand" - "runtime" "github.com/ProtonMail/proton-bridge/v3/internal/updater" ) @@ -43,26 +42,9 @@ type Settings struct { LastVersion string FirstStart bool - - SyncWorkers int - SyncAttPool int -} - -func GetDefaultSyncWorkerCount() int { - const minSyncWorkers = 16 - - syncWorkers := runtime.NumCPU() * 4 - - if syncWorkers < minSyncWorkers { - syncWorkers = minSyncWorkers - } - - return syncWorkers } func newDefaultSettings(gluonDir string) Settings { - syncWorkers := GetDefaultSyncWorkerCount() - return Settings{ GluonDir: gluonDir, @@ -82,8 +64,5 @@ func newDefaultSettings(gluonDir string) Settings { LastVersion: "0.0.0", FirstStart: true, - - SyncWorkers: syncWorkers, - SyncAttPool: syncWorkers, } } diff --git a/pkg/message/build.go b/pkg/message/build.go index f31b20f7..4811b48e 100644 --- a/pkg/message/build.go +++ b/pkg/message/build.go @@ -20,6 +20,7 @@ package message import ( "bytes" "encoding/base64" + "io" "mime" "net/mail" "strings" @@ -46,65 +47,73 @@ var ( const InternalIDDomain = `protonmail.internalid` func BuildRFC822(kr *crypto.KeyRing, msg proton.Message, attData [][]byte, opts JobOptions) ([]byte, error) { - switch { - case len(msg.Attachments) > 0: - return buildMultipartRFC822(kr, msg, attData, opts) - - case msg.MIMEType == "multipart/mixed": - return buildPGPRFC822(kr, msg, opts) - - default: - return buildSimpleRFC822(kr, msg, opts) - } -} - -func buildSimpleRFC822(kr *crypto.KeyRing, msg proton.Message, opts JobOptions) ([]byte, error) { - dec, err := msg.Decrypt(kr) - if err != nil { - if !opts.IgnoreDecryptionErrors { - return nil, errors.Wrap(ErrDecryptionFailed, err.Error()) - } - - return buildMultipartRFC822(kr, msg, nil, opts) - } - - hdr := getTextPartHeader(getMessageHeader(msg, opts), dec, msg.MIMEType) - buf := new(bytes.Buffer) - - w, err := message.CreateWriter(buf, hdr) - if err != nil { - return nil, err - } - - if _, err := w.Write(dec); err != nil { - return nil, err - } - - if err := w.Close(); err != nil { + if err := BuildRFC822Into(kr, msg, attData, opts, buf); err != nil { return nil, err } return buf.Bytes(), nil } +func BuildRFC822Into(kr *crypto.KeyRing, msg proton.Message, attData [][]byte, opts JobOptions, buf *bytes.Buffer) error { + switch { + case len(msg.Attachments) > 0: + return buildMultipartRFC822(kr, msg, attData, opts, buf) + + case msg.MIMEType == "multipart/mixed": + return buildPGPRFC822(kr, msg, opts, buf) + + default: + return buildSimpleRFC822(kr, msg, opts, buf) + } +} + +func buildSimpleRFC822(kr *crypto.KeyRing, msg proton.Message, opts JobOptions, buf *bytes.Buffer) error { + var decrypted bytes.Buffer + decrypted.Grow(len(msg.Body)) + + if err := msg.DecryptInto(kr, &decrypted); err != nil { + if !opts.IgnoreDecryptionErrors { + return errors.Wrap(ErrDecryptionFailed, err.Error()) + } + + return buildMultipartRFC822(kr, msg, nil, opts, buf) + } + + hdr := getTextPartHeader(getMessageHeader(msg, opts), decrypted.Bytes(), msg.MIMEType) + + w, err := message.CreateWriter(buf, hdr) + if err != nil { + return err + } + + if _, err := w.Write(decrypted.Bytes()); err != nil { + return err + } + + if err := w.Close(); err != nil { + return err + } + + return nil +} + func buildMultipartRFC822( kr *crypto.KeyRing, msg proton.Message, attData [][]byte, opts JobOptions, -) ([]byte, error) { + buf *bytes.Buffer, +) error { boundary := newBoundary(msg.ID) hdr := getMessageHeader(msg, opts) hdr.SetContentType("multipart/mixed", map[string]string{"boundary": boundary.gen()}) - buf := new(bytes.Buffer) - w, err := message.CreateWriter(buf, hdr) if err != nil { - return nil, err + return err } var ( @@ -126,23 +135,23 @@ func buildMultipartRFC822( if len(inlineAtts) > 0 { if err := writeRelatedParts(w, kr, boundary, msg, inlineAtts, inlineData, opts); err != nil { - return nil, err + return err } } else if err := writeTextPart(w, kr, msg, opts); err != nil { - return nil, err + return err } for i, att := range attachAtts { if err := writeAttachmentPart(w, kr, att, attachData[i], opts); err != nil { - return nil, err + return err } } if err := w.Close(); err != nil { - return nil, err + return err } - return buf.Bytes(), nil + return nil } func writeTextPart( @@ -151,8 +160,10 @@ func writeTextPart( msg proton.Message, opts JobOptions, ) error { - dec, err := msg.Decrypt(kr) - if err != nil { + var decrypted bytes.Buffer + decrypted.Grow(len(msg.Body)) + + if err := msg.DecryptInto(kr, &decrypted); err != nil { if !opts.IgnoreDecryptionErrors { return errors.Wrap(ErrDecryptionFailed, err.Error()) } @@ -160,7 +171,7 @@ func writeTextPart( return writeCustomTextPart(w, msg, err) } - return writePart(w, getTextPartHeader(message.Header{}, dec, msg.MIMEType), dec) + return writePart(w, getTextPartHeader(message.Header{}, decrypted.Bytes(), msg.MIMEType), decrypted.Bytes()) } func writeAttachmentPart( @@ -175,9 +186,10 @@ func writeAttachmentPart( return err } - msg := crypto.NewPGPSplitMessage(kps, attData).GetPGPMessage() + // Use io.Multi + attachmentReader := io.MultiReader(bytes.NewReader(kps), bytes.NewReader(attData)) - dec, err := kr.Decrypt(msg, nil, crypto.GetUnixTime()) + stream, err := kr.DecryptStream(attachmentReader, nil, crypto.GetUnixTime()) if err != nil { if !opts.IgnoreDecryptionErrors { return errors.Wrap(ErrDecryptionFailed, err.Error()) @@ -186,12 +198,38 @@ func writeAttachmentPart( log. WithField("attID", att.ID). WithError(err). - Warn("Attachment decryption failed") + Warn("Attachment decryption failed - construct") - return writeCustomAttachmentPart(w, att, msg, err) + var pgpMessageBuffer bytes.Buffer + pgpMessageBuffer.Grow(len(kps) + len(attData)) + pgpMessageBuffer.Write(kps) + pgpMessageBuffer.Write(attData) + + return writeCustomAttachmentPart(w, att, &crypto.PGPMessage{Data: pgpMessageBuffer.Bytes()}, err) } - return writePart(w, getAttachmentPartHeader(att), dec.GetBinary()) + var decryptBuffer bytes.Buffer + decryptBuffer.Grow(len(kps) + len(attData)) + + if _, err := decryptBuffer.ReadFrom(stream); err != nil { + if !opts.IgnoreDecryptionErrors { + return errors.Wrap(ErrDecryptionFailed, err.Error()) + } + + log. + WithField("attID", att.ID). + WithError(err). + Warn("Attachment decryption failed - stream") + + var pgpMessageBuffer bytes.Buffer + pgpMessageBuffer.Grow(len(kps) + len(attData)) + pgpMessageBuffer.Write(kps) + pgpMessageBuffer.Write(attData) + + return writeCustomAttachmentPart(w, att, &crypto.PGPMessage{Data: pgpMessageBuffer.Bytes()}, err) + } + + return writePart(w, getAttachmentPartHeader(att), decryptBuffer.Bytes()) } func writeRelatedParts( @@ -222,14 +260,16 @@ func writeRelatedParts( }) } -func buildPGPRFC822(kr *crypto.KeyRing, msg proton.Message, opts JobOptions) ([]byte, error) { - dec, err := msg.Decrypt(kr) - if err != nil { +func buildPGPRFC822(kr *crypto.KeyRing, msg proton.Message, opts JobOptions, buf *bytes.Buffer) error { + var decrypted bytes.Buffer + decrypted.Grow(len(msg.Body)) + + if err := msg.DecryptInto(kr, &decrypted); err != nil { if !opts.IgnoreDecryptionErrors { - return nil, errors.Wrap(ErrDecryptionFailed, err.Error()) + return errors.Wrap(ErrDecryptionFailed, err.Error()) } - return buildPGPMIMEFallbackRFC822(msg, opts) + return buildPGPMIMEFallbackRFC822(msg, opts, buf) } hdr := getMessageHeader(msg, opts) @@ -240,13 +280,13 @@ func buildPGPRFC822(kr *crypto.KeyRing, msg proton.Message, opts JobOptions) ([] } if len(sigs) > 0 { - return writeMultipartSignedRFC822(hdr, dec, sigs[0]) + return writeMultipartSignedRFC822(hdr, decrypted.Bytes(), sigs[0], buf) } - return writeMultipartEncryptedRFC822(hdr, dec) + return writeMultipartEncryptedRFC822(hdr, decrypted.Bytes(), buf) } -func buildPGPMIMEFallbackRFC822(msg proton.Message, opts JobOptions) ([]byte, error) { +func buildPGPMIMEFallbackRFC822(msg proton.Message, opts JobOptions, buf *bytes.Buffer) error { hdr := getMessageHeader(msg, opts) hdr.SetContentType("multipart/encrypted", map[string]string{ @@ -254,11 +294,9 @@ func buildPGPMIMEFallbackRFC822(msg proton.Message, opts JobOptions) ([]byte, er "protocol": "application/pgp-encrypted", }) - buf := new(bytes.Buffer) - w, err := message.CreateWriter(buf, hdr) if err != nil { - return nil, err + return err } var encHdr message.Header @@ -267,7 +305,7 @@ func buildPGPMIMEFallbackRFC822(msg proton.Message, opts JobOptions) ([]byte, er encHdr.Set("Content-Description", "PGP/MIME version identification") if err := writePart(w, encHdr, []byte("Version: 1")); err != nil { - return nil, err + return err } var dataHdr message.Header @@ -277,19 +315,17 @@ func buildPGPMIMEFallbackRFC822(msg proton.Message, opts JobOptions) ([]byte, er dataHdr.Set("Content-Description", "OpenPGP encrypted message") if err := writePart(w, dataHdr, []byte(msg.Body)); err != nil { - return nil, err + return err } if err := w.Close(); err != nil { - return nil, err + return err } - return buf.Bytes(), nil + return nil } -func writeMultipartSignedRFC822(header message.Header, body []byte, sig proton.Signature) ([]byte, error) { //nolint:funlen - buf := new(bytes.Buffer) - +func writeMultipartSignedRFC822(header message.Header, body []byte, sig proton.Signature, buf *bytes.Buffer) error { //nolint:funlen boundary := newBoundary("").gen() header.SetContentType("multipart/signed", map[string]string{ @@ -299,27 +335,27 @@ func writeMultipartSignedRFC822(header message.Header, body []byte, sig proton.S }) if err := textproto.WriteHeader(buf, header.Header); err != nil { - return nil, err + return err } mw := textproto.NewMultipartWriter(buf) if err := mw.SetBoundary(boundary); err != nil { - return nil, err + return err } bodyHeader, bodyData, err := readHeaderBody(body) if err != nil { - return nil, err + return err } bodyPart, err := mw.CreatePart(*bodyHeader) if err != nil { - return nil, err + return err } if _, err := bodyPart.Write(bodyData); err != nil { - return nil, err + return err } var sigHeader message.Header @@ -330,31 +366,29 @@ func writeMultipartSignedRFC822(header message.Header, body []byte, sig proton.S sigPart, err := mw.CreatePart(sigHeader.Header) if err != nil { - return nil, err + return err } sigData, err := sig.Data.GetArmored() if err != nil { - return nil, err + return err } if _, err := sigPart.Write([]byte(sigData)); err != nil { - return nil, err + return err } if err := mw.Close(); err != nil { - return nil, err + return err } - return buf.Bytes(), nil + return nil } -func writeMultipartEncryptedRFC822(header message.Header, body []byte) ([]byte, error) { - buf := new(bytes.Buffer) - +func writeMultipartEncryptedRFC822(header message.Header, body []byte, buf *bytes.Buffer) error { bodyHeader, bodyData, err := readHeaderBody(body) if err != nil { - return nil, err + return err } // Remove old content type header as it is non-standard. Ensure that messages @@ -371,14 +405,14 @@ func writeMultipartEncryptedRFC822(header message.Header, body []byte) ([]byte, } if err := textproto.WriteHeader(buf, header.Header); err != nil { - return nil, err + return err } if _, err := buf.Write(bodyData); err != nil { - return nil, err + return err } - return buf.Bytes(), nil + return nil } func addressEmpty(address *mail.Address) bool { From 0182e2c0bc968261c90c619ee14c1e1eeeece25d Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 30 Jan 2023 13:40:38 +0100 Subject: [PATCH 002/130] GODT-2287: Add code coverage to artifacts and pipeline. --- .gitlab-ci.yml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 6841984f..8a7cc133 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -54,6 +54,18 @@ stages: allow_failure: true - when: never +.after-script-code-coverage: + after_script: + - go get github.com/boumenot/gocover-cobertura + - go run github.com/boumenot/gocover-cobertura < /tmp/coverage.out > coverage.xml + - "go tool cover -func=/tmp/coverage.out | grep total:" + coverage: '/total:.*\(statements\).*\d+\.\d+%/' + artifacts: + reports: + coverage_report: + coverage_format: cobertura + path: coverage.xml + # Stage: TEST lint: @@ -69,6 +81,7 @@ test-linux: stage: test extends: - .rules-branch-manual-MR-always + - .after-script-code-coverage script: - make test tags: @@ -106,6 +119,8 @@ dependency-updates: script: - make updates + + # Stage: BUILD .build-base: From ce03bfbf0fb4a0bb1fa0058e4ac8ff0d61cee3ae Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Mon, 30 Jan 2023 20:12:41 +0100 Subject: [PATCH 003/130] GODT-1804: Preserve MIME parameters when uploading attachments --- internal/user/smtp.go | 3 ++- pkg/message/parser.go | 2 ++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/user/smtp.go b/internal/user/smtp.go index c16d2d27..09080e54 100644 --- a/internal/user/smtp.go +++ b/internal/user/smtp.go @@ -23,6 +23,7 @@ import ( "encoding/base64" "fmt" "io" + "mime" "net/mail" "runtime" "strings" @@ -419,7 +420,7 @@ func createAttachments( attachment, err := client.UploadAttachment(ctx, addrKR, proton.CreateAttachmentReq{ Filename: att.Name, MessageID: draftID, - MIMEType: rfc822.MIMEType(att.MIMEType), + MIMEType: rfc822.MIMEType(mime.FormatMediaType(att.MIMEType, att.MIMEParams)), Disposition: att.Disposition, ContentID: att.ContentID, Body: att.Data, diff --git a/pkg/message/parser.go b/pkg/message/parser.go index e0aa9445..6d5ee23c 100644 --- a/pkg/message/parser.go +++ b/pkg/message/parser.go @@ -66,6 +66,7 @@ type Attachment struct { Name string ContentID string MIMEType string + MIMEParams map[string]string Disposition proton.Disposition Data []byte } @@ -523,6 +524,7 @@ func parseAttachment(h message.Header, body []byte) (Attachment, error) { return Attachment{}, err } att.MIMEType = mimeType + att.MIMEParams = mimeTypeParams // Prefer attachment name from filename param in content disposition. // If not available, try to get it from name param in content type. From c8065c8092dbb7516ad571364086d8fa6b14be9d Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Mon, 30 Jan 2023 15:18:44 +0100 Subject: [PATCH 004/130] GODT-2312: used space is properly updated. --- go.mod | 2 +- go.sum | 4 +- internal/events/user.go | 13 + .../bridge-gui-tester/Tabs/UsersTab.cpp | 37 +- .../bridge-gui-tester/Tabs/UsersTab.h | 1 + .../bridge-gui-tester/Tabs/UsersTab.ui | 46 + .../bridge-gui/bridge-gui/UserList.cpp | 15 + .../frontend/bridge-gui/bridge-gui/UserList.h | 1 + .../bridgepp/bridgepp/GRPC/EventFactory.cpp | 14 + .../bridgepp/bridgepp/GRPC/EventFactory.h | 1 + .../bridgepp/bridgepp/GRPC/GRPCClient.cpp | 8 + .../bridgepp/bridgepp/GRPC/GRPCClient.h | 1 + .../bridgepp/bridgepp/GRPC/bridge.pb.cc | 584 ++++++++--- .../bridgepp/bridgepp/GRPC/bridge.pb.h | 342 ++++++- internal/frontend/grpc/bridge.pb.go | 946 ++++++++++-------- internal/frontend/grpc/bridge.proto | 6 + internal/frontend/grpc/event_factory.go | 4 + internal/frontend/grpc/service.go | 3 + internal/frontend/grpc/service_stream.go | 1 + internal/user/events.go | 18 + 20 files changed, 1484 insertions(+), 563 deletions(-) diff --git a/go.mod b/go.mod index 06393d87..e01a6075 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/gluon v0.14.2-0.20230130104154-2c64e59b8f54 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.3.1-0.20230130093944-dd1190680368 + github.com/ProtonMail/go-proton-api v0.3.1-0.20230130144605-4b05f1e5c427 github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.4.10 github.com/PuerkitoBio/goquery v1.8.0 diff --git a/go.sum b/go.sum index 7ed408bd..3e164c8b 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230130093944-dd1190680368 h1:XWPaCK8ctgpvI+ZAYcsFiYWbuvkv3T4+WZq0o6Gnt2s= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230130093944-dd1190680368/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230130144605-4b05f1e5c427 h1:M/sTrpruuxBtkeVFPoMd9WM2Kg36XlCTvYuv4q0urkg= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230130144605-4b05f1e5c427/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= diff --git a/internal/events/user.go b/internal/events/user.go index 216069f6..cbcf5a72 100644 --- a/internal/events/user.go +++ b/internal/events/user.go @@ -156,3 +156,16 @@ type AddressModeChanged struct { func (event AddressModeChanged) String() string { return fmt.Sprintf("AddressModeChanged: UserID: %s, AddressMode: %s", event.UserID, event.AddressMode) } + +// UsedSpaceChanged is emitted when the storage space used by the user has changed. +type UsedSpaceChanged struct { + eventBase + + UserID string + + UsedSpace int +} + +func (event UsedSpaceChanged) String() string { + return fmt.Sprintf("UsedSpaceChanged: UserID: %s, UsedSpace: %v", event.UserID, event.UsedSpace) +} diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp index 6bce0797..e970e90e 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp @@ -52,6 +52,7 @@ UsersTab::UsersTab(QWidget *parent) connect(ui_.tableUserList, &QTableView::doubleClicked, this, &UsersTab::onEditUserButton); connect(ui_.buttonRemoveUser, &QPushButton::clicked, this, &UsersTab::onRemoveUserButton); connect(ui_.buttonUserBadEvent, &QPushButton::clicked, this, &UsersTab::onSendUserBadEvent); + connect(ui_.buttonUsedBytesChanged, &QPushButton::clicked, this, &UsersTab::onSendUsedBytesChangedEvent); connect(ui_.checkUsernamePasswordError, &QCheckBox::toggled, this, &UsersTab::updateGUIState); users_.append(randomUser()); @@ -158,16 +159,50 @@ void UsersTab::onSendUserBadEvent() { } +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +void UsersTab::onSendUsedBytesChangedEvent() { + SPUser const user = selectedUser(); + int const index = this->selectedIndex(); + + if (!user) { + app().log().error(QString("%1 failed. Unkown user.").arg(__FUNCTION__)); + return; + } + + if (UserState::Connected != user->state()) { + app().log().error(QString("%1 failed. User is not connected").arg(__FUNCTION__)); + } + + qint64 const usedBytes = qint64(ui_.spinUsedBytes->value()); + user->setUsedBytes(usedBytes); + users_.touch(index); + + GRPCService &grpc = app().grpc(); + if (grpc.isStreaming()) { + QString const userID = user->id(); + grpc.sendEvent(newUsedBytesChangedEvent(userID, usedBytes)); + } + + this->updateGUIState(); +} + + //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** void UsersTab::updateGUIState() { SPUser const user = selectedUser(); bool const hasSelectedUser = user.get(); + UserState const state = user ? user->state() : UserState::SignedOut; + ui_.buttonEditUser->setEnabled(hasSelectedUser); ui_.buttonRemoveUser->setEnabled(hasSelectedUser); - ui_.groupBoxBadEvent->setEnabled(hasSelectedUser && (UserState::SignedOut != user->state())); + ui_.groupBoxBadEvent->setEnabled(hasSelectedUser && (UserState::SignedOut != state)); + ui_.groupBoxUsedSpace->setEnabled(hasSelectedUser && (UserState::Connected == state)); ui_.editUsernamePasswordError->setEnabled(ui_.checkUsernamePasswordError->isChecked()); + ui_.spinUsedBytes->setValue(user ? user->usedBytes() : 0.0); } diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h index 94258b86..0f43a418 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h @@ -61,6 +61,7 @@ private slots: void onRemoveUserButton(); ///< Remove the currently selected user. void onSelectionChanged(QItemSelection, QItemSelection); ///< Slot for the change of the selection. void onSendUserBadEvent(); ///< Slot for the 'Send Bad Event Error' button. + void onSendUsedBytesChangedEvent(); ///< Slot for the 'Send Used Bytes Changed Event' button. void updateGUIState(); ///< Update the GUI state. private: // member functions. diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui index 052e2546..34d79ad7 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui @@ -66,6 +66,52 @@ + + + + + 0 + 0 + + + + Used Bytes Changed + + + + + + + + Used Bytes + + + + + + + QAbstractSpinBox::NoButtons + + + 0 + + + 1000000000000000.000000000000000 + + + + + + + + + Send Used Bytes Changed + + + + + + diff --git a/internal/frontend/bridge-gui/bridge-gui/UserList.cpp b/internal/frontend/bridge-gui/bridge-gui/UserList.cpp index 908dbd1c..8d09a408 100644 --- a/internal/frontend/bridge-gui/bridge-gui/UserList.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/UserList.cpp @@ -38,6 +38,7 @@ void UserList::connectGRPCEvents() const { GRPCClient &client = app().grpc(); connect(&client, &GRPCClient::userChanged, this, &UserList::onUserChanged); connect(&client, &GRPCClient::toggleSplitModeFinished, this, &UserList::onToggleSplitModeFinished); + connect(&client, &GRPCClient::usedBytesChanged, this, &UserList::onUsedBytesChanged); } @@ -223,3 +224,17 @@ void UserList::onToggleSplitModeFinished(QString const &userID) { int UserList::count() const { return users_.size(); } + + +//**************************************************************************************************************************************************** +/// \param[in] userID The userID. +/// \param[in] usedBytes The used space, in bytes. +//**************************************************************************************************************************************************** +void UserList::onUsedBytesChanged(QString const &userID, qint64 usedBytes) { + int const index = this->rowOfUserID(userID); + if (index < 0) { + app().log().error(QString("Received usedBytesChanged event for unknown userID %1").arg(userID)); + return; + } + users_[index]->setUsedBytes(usedBytes); +} diff --git a/internal/frontend/bridge-gui/bridge-gui/UserList.h b/internal/frontend/bridge-gui/bridge-gui/UserList.h index 60d06c44..84c06480 100644 --- a/internal/frontend/bridge-gui/bridge-gui/UserList.h +++ b/internal/frontend/bridge-gui/bridge-gui/UserList.h @@ -59,6 +59,7 @@ public: public slots: ///< handler for signals coming from the gRPC service void onUserChanged(QString const &userID); void onToggleSplitModeFinished(QString const &userID); + void onUsedBytesChanged(QString const &userID, qint64 usedBytes); ///< Slot for usedBytesChanged events. private: // data members QList users_; ///< The user list. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp index 231a5c8e..c833f91c 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp @@ -574,6 +574,20 @@ SPStreamEvent newUserBadEvent(QString const &userID, QString const &errorMessage } +//**************************************************************************************************************************************************** +/// \param[in] userID The userID. +/// \param[in] usedBytes The number of used bytes. +//**************************************************************************************************************************************************** +SPStreamEvent newUsedBytesChangedEvent(QString const &userID, qint64 usedBytes) { + auto event = new grpc::UsedBytesChangedEvent; + event->set_userid(userID.toStdString()); + event->set_usedbytes(usedBytes); + auto userEvent = new grpc::UserEvent; + userEvent->set_allocated_usedbyteschangedevent(event); + return wrapUserEvent(userEvent); +} + + //**************************************************************************************************************************************************** /// \param[in] errorCode The error errorCode. /// \return The event. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h index ed35e712..151e17c9 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h @@ -78,6 +78,7 @@ SPStreamEvent newToggleSplitModeFinishedEvent(QString const &userID); ///< Creat SPStreamEvent newUserDisconnectedEvent(QString const &username); ///< Create a new UserDisconnectedEvent event. SPStreamEvent newUserChangedEvent(QString const &userID); ///< Create a new UserChangedEvent event. SPStreamEvent newUserBadEvent(QString const &userID, QString const& errorMessage); ///< Create a new UserBadEvent event. +SPStreamEvent newUsedBytesChangedEvent(QString const &userID, qint64 usedBytes); ///< Create a new UsedBytesChangedEvent event. // Generic error event SPStreamEvent newGenericErrorEvent(grpc::ErrorCode errorCode); ///< Create a new GenericErrrorEvent event. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp index f2bf58b1..8445fc69 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp @@ -1374,6 +1374,14 @@ void GRPCClient::processUserEvent(UserEvent const &event) { emit userBadEvent(userID, errorMessage); break; } + case UserEvent::kUsedBytesChangedEvent: { + UsedBytesChangedEvent const& e = event.usedbyteschangedevent(); + QString const userID = QString::fromStdString(e.userid()); + qint64 const usedBytes = e.usedbytes(); + this->logTrace(QString("User event received: UsedBytesChangedEvent (userID = %1, usedBytes = %2).").arg(userID).arg(usedBytes)); + emit usedBytesChanged(userID, usedBytes); + break; + } default: this->logError("Unknown User event received."); } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h index c84ee2b5..0ecd6a94 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h @@ -179,6 +179,7 @@ signals: void userDisconnected(QString const &username); void userChanged(QString const &userID); void userBadEvent(QString const &userID, QString const& errorMessage); + void usedBytesChanged(QString const &userID, qint64 usedBytes); public: // keychain related calls grpc::Status availableKeychains(QStringList &outKeychains); diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc index 096889ca..877ee0ed 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc @@ -759,6 +759,20 @@ struct UserBadEventDefaultTypeInternal { }; }; PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UserBadEventDefaultTypeInternal _UserBadEvent_default_instance_; +PROTOBUF_CONSTEXPR UsedBytesChangedEvent::UsedBytesChangedEvent( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.userid_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.usedbytes_)*/int64_t{0} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct UsedBytesChangedEventDefaultTypeInternal { + PROTOBUF_CONSTEXPR UsedBytesChangedEventDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~UsedBytesChangedEventDefaultTypeInternal() {} + union { + UsedBytesChangedEvent _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UsedBytesChangedEventDefaultTypeInternal _UsedBytesChangedEvent_default_instance_; PROTOBUF_CONSTEXPR GenericErrorEvent::GenericErrorEvent( ::_pbi::ConstantInitialized): _impl_{ /*decltype(_impl_.code_)*/0 @@ -773,7 +787,7 @@ struct GenericErrorEventDefaultTypeInternal { }; PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GenericErrorEventDefaultTypeInternal _GenericErrorEvent_default_instance_; } // namespace grpc -static ::_pb::Metadata file_level_metadata_bridge_2eproto[58]; +static ::_pb::Metadata file_level_metadata_bridge_2eproto[59]; static const ::_pb::EnumDescriptor* file_level_enum_descriptors_bridge_2eproto[7]; static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_bridge_2eproto = nullptr; @@ -1199,6 +1213,7 @@ const uint32_t TableStruct_bridge_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(p ::_pbi::kInvalidFieldOffsetTag, ::_pbi::kInvalidFieldOffsetTag, ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, PROTOBUF_FIELD_OFFSET(::grpc::UserEvent, _impl_.event_), ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::grpc::ToggleSplitModeFinishedEvent, _internal_metadata_), @@ -1230,6 +1245,14 @@ const uint32_t TableStruct_bridge_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(p PROTOBUF_FIELD_OFFSET(::grpc::UserBadEvent, _impl_.userid_), PROTOBUF_FIELD_OFFSET(::grpc::UserBadEvent, _impl_.errormessage_), ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::grpc::UsedBytesChangedEvent, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::grpc::UsedBytesChangedEvent, _impl_.userid_), + PROTOBUF_FIELD_OFFSET(::grpc::UsedBytesChangedEvent, _impl_.usedbytes_), + ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::grpc::GenericErrorEvent, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -1291,11 +1314,12 @@ static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protode { 398, -1, -1, sizeof(::grpc::AddressChangedLogoutEvent)}, { 405, -1, -1, sizeof(::grpc::ApiCertIssueEvent)}, { 411, -1, -1, sizeof(::grpc::UserEvent)}, - { 422, -1, -1, sizeof(::grpc::ToggleSplitModeFinishedEvent)}, - { 429, -1, -1, sizeof(::grpc::UserDisconnectedEvent)}, - { 436, -1, -1, sizeof(::grpc::UserChangedEvent)}, - { 443, -1, -1, sizeof(::grpc::UserBadEvent)}, - { 451, -1, -1, sizeof(::grpc::GenericErrorEvent)}, + { 423, -1, -1, sizeof(::grpc::ToggleSplitModeFinishedEvent)}, + { 430, -1, -1, sizeof(::grpc::UserDisconnectedEvent)}, + { 437, -1, -1, sizeof(::grpc::UserChangedEvent)}, + { 444, -1, -1, sizeof(::grpc::UserBadEvent)}, + { 452, -1, -1, sizeof(::grpc::UsedBytesChangedEvent)}, + { 460, -1, -1, sizeof(::grpc::GenericErrorEvent)}, }; static const ::_pb::Message* const file_default_instances[] = { @@ -1356,6 +1380,7 @@ static const ::_pb::Message* const file_default_instances[] = { &::grpc::_UserDisconnectedEvent_default_instance_._instance, &::grpc::_UserChangedEvent_default_instance_._instance, &::grpc::_UserBadEvent_default_instance_._instance, + &::grpc::_UsedBytesChangedEvent_default_instance_._instance, &::grpc::_GenericErrorEvent_default_instance_._instance, }; @@ -1477,135 +1502,138 @@ const char descriptor_table_protodef_bridge_2eproto[] PROTOBUF_SECTION_VARIABLE( "KeyForRecipientEvent\022\r\n\005email\030\001 \001(\t\"&\n\023A" "ddressChangedEvent\022\017\n\007address\030\001 \001(\t\",\n\031A" "ddressChangedLogoutEvent\022\017\n\007address\030\001 \001(" - "\t\"\023\n\021ApiCertIssueEvent\"\357\001\n\tUserEvent\022E\n\027" + "\t\"\023\n\021ApiCertIssueEvent\"\255\002\n\tUserEvent\022E\n\027" "toggleSplitModeFinished\030\001 \001(\0132\".grpc.Tog" "gleSplitModeFinishedEventH\000\0227\n\020userDisco" "nnected\030\002 \001(\0132\033.grpc.UserDisconnectedEve" "ntH\000\022-\n\013userChanged\030\003 \001(\0132\026.grpc.UserCha" "ngedEventH\000\022*\n\014userBadEvent\030\004 \001(\0132\022.grpc" - ".UserBadEventH\000B\007\n\005event\".\n\034ToggleSplitM" - "odeFinishedEvent\022\016\n\006userID\030\001 \001(\t\")\n\025User" - "DisconnectedEvent\022\020\n\010username\030\001 \001(\t\"\"\n\020U" - "serChangedEvent\022\016\n\006userID\030\001 \001(\t\"4\n\014UserB" - "adEvent\022\016\n\006userID\030\001 \001(\t\022\024\n\014errorMessage\030" - "\002 \001(\t\"2\n\021GenericErrorEvent\022\035\n\004code\030\001 \001(\016" - "2\017.grpc.ErrorCode*q\n\010LogLevel\022\r\n\tLOG_PAN" - "IC\020\000\022\r\n\tLOG_FATAL\020\001\022\r\n\tLOG_ERROR\020\002\022\014\n\010LO" - "G_WARN\020\003\022\014\n\010LOG_INFO\020\004\022\r\n\tLOG_DEBUG\020\005\022\r\n" - "\tLOG_TRACE\020\006*6\n\tUserState\022\016\n\nSIGNED_OUT\020" - "\000\022\n\n\006LOCKED\020\001\022\r\n\tCONNECTED\020\002*\242\001\n\016LoginEr" - "rorType\022\033\n\027USERNAME_PASSWORD_ERROR\020\000\022\r\n\t" - "FREE_USER\020\001\022\024\n\020CONNECTION_ERROR\020\002\022\r\n\tTFA" - "_ERROR\020\003\022\r\n\tTFA_ABORT\020\004\022\027\n\023TWO_PASSWORDS" - "_ERROR\020\005\022\027\n\023TWO_PASSWORDS_ABORT\020\006*[\n\017Upd" - "ateErrorType\022\027\n\023UPDATE_MANUAL_ERROR\020\000\022\026\n" - "\022UPDATE_FORCE_ERROR\020\001\022\027\n\023UPDATE_SILENT_E" - "RROR\020\002*k\n\022DiskCacheErrorType\022 \n\034DISK_CAC" - "HE_UNAVAILABLE_ERROR\020\000\022\036\n\032CANT_MOVE_DISK" - "_CACHE_ERROR\020\001\022\023\n\017DISK_FULL_ERROR\020\002*\335\001\n\033" - "MailServerSettingsErrorType\022\033\n\027IMAP_PORT" - "_STARTUP_ERROR\020\000\022\033\n\027SMTP_PORT_STARTUP_ER" - "ROR\020\001\022\032\n\026IMAP_PORT_CHANGE_ERROR\020\002\022\032\n\026SMT" - "P_PORT_CHANGE_ERROR\020\003\022%\n!IMAP_CONNECTION" - "_MODE_CHANGE_ERROR\020\004\022%\n!SMTP_CONNECTION_" - "MODE_CHANGE_ERROR\020\005*S\n\tErrorCode\022\021\n\rUNKN" - "OWN_ERROR\020\000\022\031\n\025TLS_CERT_EXPORT_ERROR\020\001\022\030" - "\n\024TLS_KEY_EXPORT_ERROR\020\0022\231\035\n\006Bridge\022I\n\013C" - "heckTokens\022\034.google.protobuf.StringValue" - "\032\034.google.protobuf.StringValue\022\?\n\013AddLog" - "Entry\022\030.grpc.AddLogEntryRequest\032\026.google" - ".protobuf.Empty\022:\n\010GuiReady\022\026.google.pro" - "tobuf.Empty\032\026.grpc.GuiReadyResponse\0226\n\004Q" - "uit\022\026.google.protobuf.Empty\032\026.google.pro" - "tobuf.Empty\0229\n\007Restart\022\026.google.protobuf" - ".Empty\032\026.google.protobuf.Empty\022C\n\rShowOn" - "Startup\022\026.google.protobuf.Empty\032\032.google" - ".protobuf.BoolValue\022F\n\020SetIsAutostartOn\022" - "\032.google.protobuf.BoolValue\032\026.google.pro" - "tobuf.Empty\022C\n\rIsAutostartOn\022\026.google.pr" - "otobuf.Empty\032\032.google.protobuf.BoolValue" - "\022F\n\020SetIsBetaEnabled\022\032.google.protobuf.B" - "oolValue\032\026.google.protobuf.Empty\022C\n\rIsBe" - "taEnabled\022\026.google.protobuf.Empty\032\032.goog" - "le.protobuf.BoolValue\022I\n\023SetIsAllMailVis" - "ible\022\032.google.protobuf.BoolValue\032\026.googl" - "e.protobuf.Empty\022F\n\020IsAllMailVisible\022\026.g" - "oogle.protobuf.Empty\032\032.google.protobuf.B" - "oolValue\022<\n\004GoOs\022\026.google.protobuf.Empty" - "\032\034.google.protobuf.StringValue\022>\n\014Trigge" - "rReset\022\026.google.protobuf.Empty\032\026.google." - "protobuf.Empty\022\?\n\007Version\022\026.google.proto" - "buf.Empty\032\034.google.protobuf.StringValue\022" - "@\n\010LogsPath\022\026.google.protobuf.Empty\032\034.go" - "ogle.protobuf.StringValue\022C\n\013LicensePath" + ".UserBadEventH\000\022<\n\025usedBytesChangedEvent" + "\030\005 \001(\0132\033.grpc.UsedBytesChangedEventH\000B\007\n" + "\005event\".\n\034ToggleSplitModeFinishedEvent\022\016" + "\n\006userID\030\001 \001(\t\")\n\025UserDisconnectedEvent\022" + "\020\n\010username\030\001 \001(\t\"\"\n\020UserChangedEvent\022\016\n" + "\006userID\030\001 \001(\t\"4\n\014UserBadEvent\022\016\n\006userID\030" + "\001 \001(\t\022\024\n\014errorMessage\030\002 \001(\t\":\n\025UsedBytes" + "ChangedEvent\022\016\n\006userID\030\001 \001(\t\022\021\n\tusedByte" + "s\030\002 \001(\003\"2\n\021GenericErrorEvent\022\035\n\004code\030\001 \001" + "(\0162\017.grpc.ErrorCode*q\n\010LogLevel\022\r\n\tLOG_P" + "ANIC\020\000\022\r\n\tLOG_FATAL\020\001\022\r\n\tLOG_ERROR\020\002\022\014\n\010" + "LOG_WARN\020\003\022\014\n\010LOG_INFO\020\004\022\r\n\tLOG_DEBUG\020\005\022" + "\r\n\tLOG_TRACE\020\006*6\n\tUserState\022\016\n\nSIGNED_OU" + "T\020\000\022\n\n\006LOCKED\020\001\022\r\n\tCONNECTED\020\002*\242\001\n\016Login" + "ErrorType\022\033\n\027USERNAME_PASSWORD_ERROR\020\000\022\r" + "\n\tFREE_USER\020\001\022\024\n\020CONNECTION_ERROR\020\002\022\r\n\tT" + "FA_ERROR\020\003\022\r\n\tTFA_ABORT\020\004\022\027\n\023TWO_PASSWOR" + "DS_ERROR\020\005\022\027\n\023TWO_PASSWORDS_ABORT\020\006*[\n\017U" + "pdateErrorType\022\027\n\023UPDATE_MANUAL_ERROR\020\000\022" + "\026\n\022UPDATE_FORCE_ERROR\020\001\022\027\n\023UPDATE_SILENT" + "_ERROR\020\002*k\n\022DiskCacheErrorType\022 \n\034DISK_C" + "ACHE_UNAVAILABLE_ERROR\020\000\022\036\n\032CANT_MOVE_DI" + "SK_CACHE_ERROR\020\001\022\023\n\017DISK_FULL_ERROR\020\002*\335\001" + "\n\033MailServerSettingsErrorType\022\033\n\027IMAP_PO" + "RT_STARTUP_ERROR\020\000\022\033\n\027SMTP_PORT_STARTUP_" + "ERROR\020\001\022\032\n\026IMAP_PORT_CHANGE_ERROR\020\002\022\032\n\026S" + "MTP_PORT_CHANGE_ERROR\020\003\022%\n!IMAP_CONNECTI" + "ON_MODE_CHANGE_ERROR\020\004\022%\n!SMTP_CONNECTIO" + "N_MODE_CHANGE_ERROR\020\005*S\n\tErrorCode\022\021\n\rUN" + "KNOWN_ERROR\020\000\022\031\n\025TLS_CERT_EXPORT_ERROR\020\001" + "\022\030\n\024TLS_KEY_EXPORT_ERROR\020\0022\231\035\n\006Bridge\022I\n" + "\013CheckTokens\022\034.google.protobuf.StringVal" + "ue\032\034.google.protobuf.StringValue\022\?\n\013AddL" + "ogEntry\022\030.grpc.AddLogEntryRequest\032\026.goog" + "le.protobuf.Empty\022:\n\010GuiReady\022\026.google.p" + "rotobuf.Empty\032\026.grpc.GuiReadyResponse\0226\n" + "\004Quit\022\026.google.protobuf.Empty\032\026.google.p" + "rotobuf.Empty\0229\n\007Restart\022\026.google.protob" + "uf.Empty\032\026.google.protobuf.Empty\022C\n\rShow" + "OnStartup\022\026.google.protobuf.Empty\032\032.goog" + "le.protobuf.BoolValue\022F\n\020SetIsAutostartO" + "n\022\032.google.protobuf.BoolValue\032\026.google.p" + "rotobuf.Empty\022C\n\rIsAutostartOn\022\026.google." + "protobuf.Empty\032\032.google.protobuf.BoolVal" + "ue\022F\n\020SetIsBetaEnabled\022\032.google.protobuf" + ".BoolValue\032\026.google.protobuf.Empty\022C\n\rIs" + "BetaEnabled\022\026.google.protobuf.Empty\032\032.go" + "ogle.protobuf.BoolValue\022I\n\023SetIsAllMailV" + "isible\022\032.google.protobuf.BoolValue\032\026.goo" + "gle.protobuf.Empty\022F\n\020IsAllMailVisible\022\026" + ".google.protobuf.Empty\032\032.google.protobuf" + ".BoolValue\022<\n\004GoOs\022\026.google.protobuf.Emp" + "ty\032\034.google.protobuf.StringValue\022>\n\014Trig" + "gerReset\022\026.google.protobuf.Empty\032\026.googl" + "e.protobuf.Empty\022\?\n\007Version\022\026.google.pro" + "tobuf.Empty\032\034.google.protobuf.StringValu" + "e\022@\n\010LogsPath\022\026.google.protobuf.Empty\032\034." + "google.protobuf.StringValue\022C\n\013LicensePa" + "th\022\026.google.protobuf.Empty\032\034.google.prot" + "obuf.StringValue\022L\n\024ReleaseNotesPageLink" "\022\026.google.protobuf.Empty\032\034.google.protob" - "uf.StringValue\022L\n\024ReleaseNotesPageLink\022\026" - ".google.protobuf.Empty\032\034.google.protobuf" - ".StringValue\022N\n\026DependencyLicensesLink\022\026" - ".google.protobuf.Empty\032\034.google.protobuf" - ".StringValue\022G\n\017LandingPageLink\022\026.google" - ".protobuf.Empty\032\034.google.protobuf.String" - "Value\022J\n\022SetColorSchemeName\022\034.google.pro" - "tobuf.StringValue\032\026.google.protobuf.Empt" - "y\022G\n\017ColorSchemeName\022\026.google.protobuf.E" - "mpty\032\034.google.protobuf.StringValue\022J\n\022Cu" - "rrentEmailClient\022\026.google.protobuf.Empty" - "\032\034.google.protobuf.StringValue\022;\n\tReport" - "Bug\022\026.grpc.ReportBugRequest\032\026.google.pro" - "tobuf.Empty\022M\n\025ExportTLSCertificates\022\034.g" - "oogle.protobuf.StringValue\032\026.google.prot" - "obuf.Empty\022E\n\rForceLauncher\022\034.google.pro" - "tobuf.StringValue\032\026.google.protobuf.Empt" - "y\022I\n\021SetMainExecutable\022\034.google.protobuf" - ".StringValue\032\026.google.protobuf.Empty\0223\n\005" - "Login\022\022.grpc.LoginRequest\032\026.google.proto" - "buf.Empty\0226\n\010Login2FA\022\022.grpc.LoginReques" - "t\032\026.google.protobuf.Empty\022=\n\017Login2Passw" - "ords\022\022.grpc.LoginRequest\032\026.google.protob" - "uf.Empty\022=\n\nLoginAbort\022\027.grpc.LoginAbort" - "Request\032\026.google.protobuf.Empty\022=\n\013Check" - "Update\022\026.google.protobuf.Empty\032\026.google." - "protobuf.Empty\022\?\n\rInstallUpdate\022\026.google" - ".protobuf.Empty\032\026.google.protobuf.Empty\022" - "L\n\026SetIsAutomaticUpdateOn\022\032.google.proto" - "buf.BoolValue\032\026.google.protobuf.Empty\022I\n" - "\023IsAutomaticUpdateOn\022\026.google.protobuf.E" - "mpty\032\032.google.protobuf.BoolValue\022E\n\rDisk" - "CachePath\022\026.google.protobuf.Empty\032\034.goog" - "le.protobuf.StringValue\022H\n\020SetDiskCacheP" - "ath\022\034.google.protobuf.StringValue\032\026.goog" - "le.protobuf.Empty\022E\n\017SetIsDoHEnabled\022\032.g" - "oogle.protobuf.BoolValue\032\026.google.protob" - "uf.Empty\022B\n\014IsDoHEnabled\022\026.google.protob" - "uf.Empty\032\032.google.protobuf.BoolValue\022D\n\022" - "MailServerSettings\022\026.google.protobuf.Emp" - "ty\032\026.grpc.ImapSmtpSettings\022G\n\025SetMailSer" - "verSettings\022\026.grpc.ImapSmtpSettings\032\026.go" - "ogle.protobuf.Empty\022@\n\010Hostname\022\026.google" - ".protobuf.Empty\032\034.google.protobuf.String" - "Value\022E\n\nIsPortFree\022\033.google.protobuf.In" - "t32Value\032\032.google.protobuf.BoolValue\022N\n\022" - "AvailableKeychains\022\026.google.protobuf.Emp" - "ty\032 .grpc.AvailableKeychainsResponse\022J\n\022" - "SetCurrentKeychain\022\034.google.protobuf.Str" - "ingValue\032\026.google.protobuf.Empty\022G\n\017Curr" - "entKeychain\022\026.google.protobuf.Empty\032\034.go" - "ogle.protobuf.StringValue\022=\n\013GetUserList" - "\022\026.google.protobuf.Empty\032\026.grpc.UserList" - "Response\0223\n\007GetUser\022\034.google.protobuf.St" - "ringValue\032\n.grpc.User\022F\n\020SetUserSplitMod" - "e\022\032.grpc.UserSplitModeRequest\032\026.google.p" - "rotobuf.Empty\022B\n\nLogoutUser\022\034.google.pro" - "tobuf.StringValue\032\026.google.protobuf.Empt" - "y\022B\n\nRemoveUser\022\034.google.protobuf.String" - "Value\032\026.google.protobuf.Empty\022Q\n\026Configu" - "reUserAppleMail\022\037.grpc.ConfigureAppleMai" - "lRequest\032\026.google.protobuf.Empty\022\?\n\016RunE" - "ventStream\022\030.grpc.EventStreamRequest\032\021.g" - "rpc.StreamEvent0\001\022A\n\017StopEventStream\022\026.g" - "oogle.protobuf.Empty\032\026.google.protobuf.E" - "mptyB6Z4github.com/ProtonMail/proton-bri" - "dge/v3/internal/grpcb\006proto3" + "uf.StringValue\022N\n\026DependencyLicensesLink" + "\022\026.google.protobuf.Empty\032\034.google.protob" + "uf.StringValue\022G\n\017LandingPageLink\022\026.goog" + "le.protobuf.Empty\032\034.google.protobuf.Stri" + "ngValue\022J\n\022SetColorSchemeName\022\034.google.p" + "rotobuf.StringValue\032\026.google.protobuf.Em" + "pty\022G\n\017ColorSchemeName\022\026.google.protobuf" + ".Empty\032\034.google.protobuf.StringValue\022J\n\022" + "CurrentEmailClient\022\026.google.protobuf.Emp" + "ty\032\034.google.protobuf.StringValue\022;\n\tRepo" + "rtBug\022\026.grpc.ReportBugRequest\032\026.google.p" + "rotobuf.Empty\022M\n\025ExportTLSCertificates\022\034" + ".google.protobuf.StringValue\032\026.google.pr" + "otobuf.Empty\022E\n\rForceLauncher\022\034.google.p" + "rotobuf.StringValue\032\026.google.protobuf.Em" + "pty\022I\n\021SetMainExecutable\022\034.google.protob" + "uf.StringValue\032\026.google.protobuf.Empty\0223" + "\n\005Login\022\022.grpc.LoginRequest\032\026.google.pro" + "tobuf.Empty\0226\n\010Login2FA\022\022.grpc.LoginRequ" + "est\032\026.google.protobuf.Empty\022=\n\017Login2Pas" + "swords\022\022.grpc.LoginRequest\032\026.google.prot" + "obuf.Empty\022=\n\nLoginAbort\022\027.grpc.LoginAbo" + "rtRequest\032\026.google.protobuf.Empty\022=\n\013Che" + "ckUpdate\022\026.google.protobuf.Empty\032\026.googl" + "e.protobuf.Empty\022\?\n\rInstallUpdate\022\026.goog" + "le.protobuf.Empty\032\026.google.protobuf.Empt" + "y\022L\n\026SetIsAutomaticUpdateOn\022\032.google.pro" + "tobuf.BoolValue\032\026.google.protobuf.Empty\022" + "I\n\023IsAutomaticUpdateOn\022\026.google.protobuf" + ".Empty\032\032.google.protobuf.BoolValue\022E\n\rDi" + "skCachePath\022\026.google.protobuf.Empty\032\034.go" + "ogle.protobuf.StringValue\022H\n\020SetDiskCach" + "ePath\022\034.google.protobuf.StringValue\032\026.go" + "ogle.protobuf.Empty\022E\n\017SetIsDoHEnabled\022\032" + ".google.protobuf.BoolValue\032\026.google.prot" + "obuf.Empty\022B\n\014IsDoHEnabled\022\026.google.prot" + "obuf.Empty\032\032.google.protobuf.BoolValue\022D" + "\n\022MailServerSettings\022\026.google.protobuf.E" + "mpty\032\026.grpc.ImapSmtpSettings\022G\n\025SetMailS" + "erverSettings\022\026.grpc.ImapSmtpSettings\032\026." + "google.protobuf.Empty\022@\n\010Hostname\022\026.goog" + "le.protobuf.Empty\032\034.google.protobuf.Stri" + "ngValue\022E\n\nIsPortFree\022\033.google.protobuf." + "Int32Value\032\032.google.protobuf.BoolValue\022N" + "\n\022AvailableKeychains\022\026.google.protobuf.E" + "mpty\032 .grpc.AvailableKeychainsResponse\022J" + "\n\022SetCurrentKeychain\022\034.google.protobuf.S" + "tringValue\032\026.google.protobuf.Empty\022G\n\017Cu" + "rrentKeychain\022\026.google.protobuf.Empty\032\034." + "google.protobuf.StringValue\022=\n\013GetUserLi" + "st\022\026.google.protobuf.Empty\032\026.grpc.UserLi" + "stResponse\0223\n\007GetUser\022\034.google.protobuf." + "StringValue\032\n.grpc.User\022F\n\020SetUserSplitM" + "ode\022\032.grpc.UserSplitModeRequest\032\026.google" + ".protobuf.Empty\022B\n\nLogoutUser\022\034.google.p" + "rotobuf.StringValue\032\026.google.protobuf.Em" + "pty\022B\n\nRemoveUser\022\034.google.protobuf.Stri" + "ngValue\032\026.google.protobuf.Empty\022Q\n\026Confi" + "gureUserAppleMail\022\037.grpc.ConfigureAppleM" + "ailRequest\032\026.google.protobuf.Empty\022\?\n\016Ru" + "nEventStream\022\030.grpc.EventStreamRequest\032\021" + ".grpc.StreamEvent0\001\022A\n\017StopEventStream\022\026" + ".google.protobuf.Empty\032\026.google.protobuf" + ".EmptyB6Z4github.com/ProtonMail/proton-b" + "ridge/v3/internal/grpcb\006proto3" ; static const ::_pbi::DescriptorTable* const descriptor_table_bridge_2eproto_deps[2] = { &::descriptor_table_google_2fprotobuf_2fempty_2eproto, @@ -1613,9 +1641,9 @@ static const ::_pbi::DescriptorTable* const descriptor_table_bridge_2eproto_deps }; static ::_pbi::once_flag descriptor_table_bridge_2eproto_once; const ::_pbi::DescriptorTable descriptor_table_bridge_2eproto = { - false, false, 9828, descriptor_table_protodef_bridge_2eproto, + false, false, 9950, descriptor_table_protodef_bridge_2eproto, "bridge.proto", - &descriptor_table_bridge_2eproto_once, descriptor_table_bridge_2eproto_deps, 2, 58, + &descriptor_table_bridge_2eproto_once, descriptor_table_bridge_2eproto_deps, 2, 59, schemas, file_default_instances, TableStruct_bridge_2eproto::offsets, file_level_metadata_bridge_2eproto, file_level_enum_descriptors_bridge_2eproto, file_level_service_descriptors_bridge_2eproto, @@ -12378,6 +12406,7 @@ class UserEvent::_Internal { static const ::grpc::UserDisconnectedEvent& userdisconnected(const UserEvent* msg); static const ::grpc::UserChangedEvent& userchanged(const UserEvent* msg); static const ::grpc::UserBadEvent& userbadevent(const UserEvent* msg); + static const ::grpc::UsedBytesChangedEvent& usedbyteschangedevent(const UserEvent* msg); }; const ::grpc::ToggleSplitModeFinishedEvent& @@ -12396,6 +12425,10 @@ const ::grpc::UserBadEvent& UserEvent::_Internal::userbadevent(const UserEvent* msg) { return *msg->_impl_.event_.userbadevent_; } +const ::grpc::UsedBytesChangedEvent& +UserEvent::_Internal::usedbyteschangedevent(const UserEvent* msg) { + return *msg->_impl_.event_.usedbyteschangedevent_; +} void UserEvent::set_allocated_togglesplitmodefinished(::grpc::ToggleSplitModeFinishedEvent* togglesplitmodefinished) { ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); clear_event(); @@ -12456,6 +12489,21 @@ void UserEvent::set_allocated_userbadevent(::grpc::UserBadEvent* userbadevent) { } // @@protoc_insertion_point(field_set_allocated:grpc.UserEvent.userBadEvent) } +void UserEvent::set_allocated_usedbyteschangedevent(::grpc::UsedBytesChangedEvent* usedbyteschangedevent) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + clear_event(); + if (usedbyteschangedevent) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(usedbyteschangedevent); + if (message_arena != submessage_arena) { + usedbyteschangedevent = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, usedbyteschangedevent, submessage_arena); + } + set_has_usedbyteschangedevent(); + _impl_.event_.usedbyteschangedevent_ = usedbyteschangedevent; + } + // @@protoc_insertion_point(field_set_allocated:grpc.UserEvent.usedBytesChangedEvent) +} UserEvent::UserEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned) : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { @@ -12493,6 +12541,11 @@ UserEvent::UserEvent(const UserEvent& from) from._internal_userbadevent()); break; } + case kUsedBytesChangedEvent: { + _this->_internal_mutable_usedbyteschangedevent()->::grpc::UsedBytesChangedEvent::MergeFrom( + from._internal_usedbyteschangedevent()); + break; + } case EVENT_NOT_SET: { break; } @@ -12559,6 +12612,12 @@ void UserEvent::clear_event() { } break; } + case kUsedBytesChangedEvent: { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.event_.usedbyteschangedevent_; + } + break; + } case EVENT_NOT_SET: { break; } @@ -12615,6 +12674,14 @@ const char* UserEvent::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx } else goto handle_unusual; continue; + // .grpc.UsedBytesChangedEvent usedBytesChangedEvent = 5; + case 5: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 42)) { + ptr = ctx->ParseMessage(_internal_mutable_usedbyteschangedevent(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; default: goto handle_unusual; } // switch @@ -12672,6 +12739,13 @@ uint8_t* UserEvent::_InternalSerialize( _Internal::userbadevent(this).GetCachedSize(), target, stream); } + // .grpc.UsedBytesChangedEvent usedBytesChangedEvent = 5; + if (_internal_has_usedbyteschangedevent()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(5, _Internal::usedbyteschangedevent(this), + _Internal::usedbyteschangedevent(this).GetCachedSize(), target, stream); + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); @@ -12717,6 +12791,13 @@ size_t UserEvent::ByteSizeLong() const { *_impl_.event_.userbadevent_); break; } + // .grpc.UsedBytesChangedEvent usedBytesChangedEvent = 5; + case kUsedBytesChangedEvent: { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.event_.usedbyteschangedevent_); + break; + } case EVENT_NOT_SET: { break; } @@ -12760,6 +12841,11 @@ void UserEvent::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROT from._internal_userbadevent()); break; } + case kUsedBytesChangedEvent: { + _this->_internal_mutable_usedbyteschangedevent()->::grpc::UsedBytesChangedEvent::MergeFrom( + from._internal_usedbyteschangedevent()); + break; + } case EVENT_NOT_SET: { break; } @@ -13655,6 +13741,236 @@ void UserBadEvent::InternalSwap(UserBadEvent* other) { // =================================================================== +class UsedBytesChangedEvent::_Internal { + public: +}; + +UsedBytesChangedEvent::UsedBytesChangedEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:grpc.UsedBytesChangedEvent) +} +UsedBytesChangedEvent::UsedBytesChangedEvent(const UsedBytesChangedEvent& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + UsedBytesChangedEvent* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.userid_){} + , decltype(_impl_.usedbytes_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.userid_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.userid_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_userid().empty()) { + _this->_impl_.userid_.Set(from._internal_userid(), + _this->GetArenaForAllocation()); + } + _this->_impl_.usedbytes_ = from._impl_.usedbytes_; + // @@protoc_insertion_point(copy_constructor:grpc.UsedBytesChangedEvent) +} + +inline void UsedBytesChangedEvent::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.userid_){} + , decltype(_impl_.usedbytes_){int64_t{0}} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.userid_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.userid_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +UsedBytesChangedEvent::~UsedBytesChangedEvent() { + // @@protoc_insertion_point(destructor:grpc.UsedBytesChangedEvent) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void UsedBytesChangedEvent::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.userid_.Destroy(); +} + +void UsedBytesChangedEvent::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void UsedBytesChangedEvent::Clear() { +// @@protoc_insertion_point(message_clear_start:grpc.UsedBytesChangedEvent) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.userid_.ClearToEmpty(); + _impl_.usedbytes_ = int64_t{0}; + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* UsedBytesChangedEvent::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string userID = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 10)) { + auto str = _internal_mutable_userid(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "grpc.UsedBytesChangedEvent.userID")); + } else + goto handle_unusual; + continue; + // int64 usedBytes = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 16)) { + _impl_.usedbytes_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* UsedBytesChangedEvent::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:grpc.UsedBytesChangedEvent) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string userID = 1; + if (!this->_internal_userid().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_userid().data(), static_cast(this->_internal_userid().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "grpc.UsedBytesChangedEvent.userID"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_userid(), target); + } + + // int64 usedBytes = 2; + if (this->_internal_usedbytes() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt64ToArray(2, this->_internal_usedbytes(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:grpc.UsedBytesChangedEvent) + return target; +} + +size_t UsedBytesChangedEvent::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:grpc.UsedBytesChangedEvent) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string userID = 1; + if (!this->_internal_userid().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_userid()); + } + + // int64 usedBytes = 2; + if (this->_internal_usedbytes() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne(this->_internal_usedbytes()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData UsedBytesChangedEvent::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + UsedBytesChangedEvent::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*UsedBytesChangedEvent::GetClassData() const { return &_class_data_; } + + +void UsedBytesChangedEvent::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:grpc.UsedBytesChangedEvent) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_userid().empty()) { + _this->_internal_set_userid(from._internal_userid()); + } + if (from._internal_usedbytes() != 0) { + _this->_internal_set_usedbytes(from._internal_usedbytes()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void UsedBytesChangedEvent::CopyFrom(const UsedBytesChangedEvent& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:grpc.UsedBytesChangedEvent) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool UsedBytesChangedEvent::IsInitialized() const { + return true; +} + +void UsedBytesChangedEvent::InternalSwap(UsedBytesChangedEvent* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.userid_, lhs_arena, + &other->_impl_.userid_, rhs_arena + ); + swap(_impl_.usedbytes_, other->_impl_.usedbytes_); +} + +::PROTOBUF_NAMESPACE_ID::Metadata UsedBytesChangedEvent::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_bridge_2eproto_getter, &descriptor_table_bridge_2eproto_once, + file_level_metadata_bridge_2eproto[57]); +} + +// =================================================================== + class GenericErrorEvent::_Internal { public: }; @@ -13831,7 +14147,7 @@ void GenericErrorEvent::InternalSwap(GenericErrorEvent* other) { ::PROTOBUF_NAMESPACE_ID::Metadata GenericErrorEvent::GetMetadata() const { return ::_pbi::AssignDescriptors( &descriptor_table_bridge_2eproto_getter, &descriptor_table_bridge_2eproto_once, - file_level_metadata_bridge_2eproto[57]); + file_level_metadata_bridge_2eproto[58]); } // @@protoc_insertion_point(namespace_scope) @@ -14065,6 +14381,10 @@ template<> PROTOBUF_NOINLINE ::grpc::UserBadEvent* Arena::CreateMaybeMessage< ::grpc::UserBadEvent >(Arena* arena) { return Arena::CreateMessageInternal< ::grpc::UserBadEvent >(arena); } +template<> PROTOBUF_NOINLINE ::grpc::UsedBytesChangedEvent* +Arena::CreateMaybeMessage< ::grpc::UsedBytesChangedEvent >(Arena* arena) { + return Arena::CreateMessageInternal< ::grpc::UsedBytesChangedEvent >(arena); +} template<> PROTOBUF_NOINLINE ::grpc::GenericErrorEvent* Arena::CreateMaybeMessage< ::grpc::GenericErrorEvent >(Arena* arena) { return Arena::CreateMessageInternal< ::grpc::GenericErrorEvent >(arena); diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h index dc39e892..e39d8cd8 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h @@ -202,6 +202,9 @@ extern UpdateSilentRestartNeededDefaultTypeInternal _UpdateSilentRestartNeeded_d class UpdateVersionChanged; struct UpdateVersionChangedDefaultTypeInternal; extern UpdateVersionChangedDefaultTypeInternal _UpdateVersionChanged_default_instance_; +class UsedBytesChangedEvent; +struct UsedBytesChangedEventDefaultTypeInternal; +extern UsedBytesChangedEventDefaultTypeInternal _UsedBytesChangedEvent_default_instance_; class User; struct UserDefaultTypeInternal; extern UserDefaultTypeInternal _User_default_instance_; @@ -276,6 +279,7 @@ template<> ::grpc::UpdateManualReadyEvent* Arena::CreateMaybeMessage<::grpc::Upd template<> ::grpc::UpdateManualRestartNeededEvent* Arena::CreateMaybeMessage<::grpc::UpdateManualRestartNeededEvent>(Arena*); template<> ::grpc::UpdateSilentRestartNeeded* Arena::CreateMaybeMessage<::grpc::UpdateSilentRestartNeeded>(Arena*); template<> ::grpc::UpdateVersionChanged* Arena::CreateMaybeMessage<::grpc::UpdateVersionChanged>(Arena*); +template<> ::grpc::UsedBytesChangedEvent* Arena::CreateMaybeMessage<::grpc::UsedBytesChangedEvent>(Arena*); template<> ::grpc::User* Arena::CreateMaybeMessage<::grpc::User>(Arena*); template<> ::grpc::UserBadEvent* Arena::CreateMaybeMessage<::grpc::UserBadEvent>(Arena*); template<> ::grpc::UserChangedEvent* Arena::CreateMaybeMessage<::grpc::UserChangedEvent>(Arena*); @@ -9077,6 +9081,7 @@ class UserEvent final : kUserDisconnected = 2, kUserChanged = 3, kUserBadEvent = 4, + kUsedBytesChangedEvent = 5, EVENT_NOT_SET = 0, }; @@ -9162,6 +9167,7 @@ class UserEvent final : kUserDisconnectedFieldNumber = 2, kUserChangedFieldNumber = 3, kUserBadEventFieldNumber = 4, + kUsedBytesChangedEventFieldNumber = 5, }; // .grpc.ToggleSplitModeFinishedEvent toggleSplitModeFinished = 1; bool has_togglesplitmodefinished() const; @@ -9235,6 +9241,24 @@ class UserEvent final : ::grpc::UserBadEvent* userbadevent); ::grpc::UserBadEvent* unsafe_arena_release_userbadevent(); + // .grpc.UsedBytesChangedEvent usedBytesChangedEvent = 5; + bool has_usedbyteschangedevent() const; + private: + bool _internal_has_usedbyteschangedevent() const; + public: + void clear_usedbyteschangedevent(); + const ::grpc::UsedBytesChangedEvent& usedbyteschangedevent() const; + PROTOBUF_NODISCARD ::grpc::UsedBytesChangedEvent* release_usedbyteschangedevent(); + ::grpc::UsedBytesChangedEvent* mutable_usedbyteschangedevent(); + void set_allocated_usedbyteschangedevent(::grpc::UsedBytesChangedEvent* usedbyteschangedevent); + private: + const ::grpc::UsedBytesChangedEvent& _internal_usedbyteschangedevent() const; + ::grpc::UsedBytesChangedEvent* _internal_mutable_usedbyteschangedevent(); + public: + void unsafe_arena_set_allocated_usedbyteschangedevent( + ::grpc::UsedBytesChangedEvent* usedbyteschangedevent); + ::grpc::UsedBytesChangedEvent* unsafe_arena_release_usedbyteschangedevent(); + void clear_event(); EventCase event_case() const; // @@protoc_insertion_point(class_scope:grpc.UserEvent) @@ -9244,6 +9268,7 @@ class UserEvent final : void set_has_userdisconnected(); void set_has_userchanged(); void set_has_userbadevent(); + void set_has_usedbyteschangedevent(); inline bool has_event() const; inline void clear_has_event(); @@ -9259,6 +9284,7 @@ class UserEvent final : ::grpc::UserDisconnectedEvent* userdisconnected_; ::grpc::UserChangedEvent* userchanged_; ::grpc::UserBadEvent* userbadevent_; + ::grpc::UsedBytesChangedEvent* usedbyteschangedevent_; } event_; mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; uint32_t _oneof_case_[1]; @@ -9897,6 +9923,170 @@ class UserBadEvent final : }; // ------------------------------------------------------------------- +class UsedBytesChangedEvent final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:grpc.UsedBytesChangedEvent) */ { + public: + inline UsedBytesChangedEvent() : UsedBytesChangedEvent(nullptr) {} + ~UsedBytesChangedEvent() override; + explicit PROTOBUF_CONSTEXPR UsedBytesChangedEvent(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + UsedBytesChangedEvent(const UsedBytesChangedEvent& from); + UsedBytesChangedEvent(UsedBytesChangedEvent&& from) noexcept + : UsedBytesChangedEvent() { + *this = ::std::move(from); + } + + inline UsedBytesChangedEvent& operator=(const UsedBytesChangedEvent& from) { + CopyFrom(from); + return *this; + } + inline UsedBytesChangedEvent& operator=(UsedBytesChangedEvent&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const UsedBytesChangedEvent& default_instance() { + return *internal_default_instance(); + } + static inline const UsedBytesChangedEvent* internal_default_instance() { + return reinterpret_cast( + &_UsedBytesChangedEvent_default_instance_); + } + static constexpr int kIndexInFileMessages = + 57; + + friend void swap(UsedBytesChangedEvent& a, UsedBytesChangedEvent& b) { + a.Swap(&b); + } + inline void Swap(UsedBytesChangedEvent* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(UsedBytesChangedEvent* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + UsedBytesChangedEvent* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const UsedBytesChangedEvent& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const UsedBytesChangedEvent& from) { + UsedBytesChangedEvent::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(UsedBytesChangedEvent* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "grpc.UsedBytesChangedEvent"; + } + protected: + explicit UsedBytesChangedEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUserIDFieldNumber = 1, + kUsedBytesFieldNumber = 2, + }; + // string userID = 1; + void clear_userid(); + const std::string& userid() const; + template + void set_userid(ArgT0&& arg0, ArgT... args); + std::string* mutable_userid(); + PROTOBUF_NODISCARD std::string* release_userid(); + void set_allocated_userid(std::string* userid); + private: + const std::string& _internal_userid() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_userid(const std::string& value); + std::string* _internal_mutable_userid(); + public: + + // int64 usedBytes = 2; + void clear_usedbytes(); + int64_t usedbytes() const; + void set_usedbytes(int64_t value); + private: + int64_t _internal_usedbytes() const; + void _internal_set_usedbytes(int64_t value); + public: + + // @@protoc_insertion_point(class_scope:grpc.UsedBytesChangedEvent) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr userid_; + int64_t usedbytes_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_bridge_2eproto; +}; +// ------------------------------------------------------------------- + class GenericErrorEvent final : public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:grpc.GenericErrorEvent) */ { public: @@ -9945,7 +10135,7 @@ class GenericErrorEvent final : &_GenericErrorEvent_default_instance_); } static constexpr int kIndexInFileMessages = - 57; + 58; friend void swap(GenericErrorEvent& a, GenericErrorEvent& b) { a.Swap(&b); @@ -15728,6 +15918,80 @@ inline ::grpc::UserBadEvent* UserEvent::mutable_userbadevent() { return _msg; } +// .grpc.UsedBytesChangedEvent usedBytesChangedEvent = 5; +inline bool UserEvent::_internal_has_usedbyteschangedevent() const { + return event_case() == kUsedBytesChangedEvent; +} +inline bool UserEvent::has_usedbyteschangedevent() const { + return _internal_has_usedbyteschangedevent(); +} +inline void UserEvent::set_has_usedbyteschangedevent() { + _impl_._oneof_case_[0] = kUsedBytesChangedEvent; +} +inline void UserEvent::clear_usedbyteschangedevent() { + if (_internal_has_usedbyteschangedevent()) { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.event_.usedbyteschangedevent_; + } + clear_has_event(); + } +} +inline ::grpc::UsedBytesChangedEvent* UserEvent::release_usedbyteschangedevent() { + // @@protoc_insertion_point(field_release:grpc.UserEvent.usedBytesChangedEvent) + if (_internal_has_usedbyteschangedevent()) { + clear_has_event(); + ::grpc::UsedBytesChangedEvent* temp = _impl_.event_.usedbyteschangedevent_; + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + _impl_.event_.usedbyteschangedevent_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::grpc::UsedBytesChangedEvent& UserEvent::_internal_usedbyteschangedevent() const { + return _internal_has_usedbyteschangedevent() + ? *_impl_.event_.usedbyteschangedevent_ + : reinterpret_cast< ::grpc::UsedBytesChangedEvent&>(::grpc::_UsedBytesChangedEvent_default_instance_); +} +inline const ::grpc::UsedBytesChangedEvent& UserEvent::usedbyteschangedevent() const { + // @@protoc_insertion_point(field_get:grpc.UserEvent.usedBytesChangedEvent) + return _internal_usedbyteschangedevent(); +} +inline ::grpc::UsedBytesChangedEvent* UserEvent::unsafe_arena_release_usedbyteschangedevent() { + // @@protoc_insertion_point(field_unsafe_arena_release:grpc.UserEvent.usedBytesChangedEvent) + if (_internal_has_usedbyteschangedevent()) { + clear_has_event(); + ::grpc::UsedBytesChangedEvent* temp = _impl_.event_.usedbyteschangedevent_; + _impl_.event_.usedbyteschangedevent_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void UserEvent::unsafe_arena_set_allocated_usedbyteschangedevent(::grpc::UsedBytesChangedEvent* usedbyteschangedevent) { + clear_event(); + if (usedbyteschangedevent) { + set_has_usedbyteschangedevent(); + _impl_.event_.usedbyteschangedevent_ = usedbyteschangedevent; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:grpc.UserEvent.usedBytesChangedEvent) +} +inline ::grpc::UsedBytesChangedEvent* UserEvent::_internal_mutable_usedbyteschangedevent() { + if (!_internal_has_usedbyteschangedevent()) { + clear_event(); + set_has_usedbyteschangedevent(); + _impl_.event_.usedbyteschangedevent_ = CreateMaybeMessage< ::grpc::UsedBytesChangedEvent >(GetArenaForAllocation()); + } + return _impl_.event_.usedbyteschangedevent_; +} +inline ::grpc::UsedBytesChangedEvent* UserEvent::mutable_usedbyteschangedevent() { + ::grpc::UsedBytesChangedEvent* _msg = _internal_mutable_usedbyteschangedevent(); + // @@protoc_insertion_point(field_mutable:grpc.UserEvent.usedBytesChangedEvent) + return _msg; +} + inline bool UserEvent::has_event() const { return event_case() != EVENT_NOT_SET; } @@ -16005,6 +16269,80 @@ inline void UserBadEvent::set_allocated_errormessage(std::string* errormessage) // ------------------------------------------------------------------- +// UsedBytesChangedEvent + +// string userID = 1; +inline void UsedBytesChangedEvent::clear_userid() { + _impl_.userid_.ClearToEmpty(); +} +inline const std::string& UsedBytesChangedEvent::userid() const { + // @@protoc_insertion_point(field_get:grpc.UsedBytesChangedEvent.userID) + return _internal_userid(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void UsedBytesChangedEvent::set_userid(ArgT0&& arg0, ArgT... args) { + + _impl_.userid_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:grpc.UsedBytesChangedEvent.userID) +} +inline std::string* UsedBytesChangedEvent::mutable_userid() { + std::string* _s = _internal_mutable_userid(); + // @@protoc_insertion_point(field_mutable:grpc.UsedBytesChangedEvent.userID) + return _s; +} +inline const std::string& UsedBytesChangedEvent::_internal_userid() const { + return _impl_.userid_.Get(); +} +inline void UsedBytesChangedEvent::_internal_set_userid(const std::string& value) { + + _impl_.userid_.Set(value, GetArenaForAllocation()); +} +inline std::string* UsedBytesChangedEvent::_internal_mutable_userid() { + + return _impl_.userid_.Mutable(GetArenaForAllocation()); +} +inline std::string* UsedBytesChangedEvent::release_userid() { + // @@protoc_insertion_point(field_release:grpc.UsedBytesChangedEvent.userID) + return _impl_.userid_.Release(); +} +inline void UsedBytesChangedEvent::set_allocated_userid(std::string* userid) { + if (userid != nullptr) { + + } else { + + } + _impl_.userid_.SetAllocated(userid, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.userid_.IsDefault()) { + _impl_.userid_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:grpc.UsedBytesChangedEvent.userID) +} + +// int64 usedBytes = 2; +inline void UsedBytesChangedEvent::clear_usedbytes() { + _impl_.usedbytes_ = int64_t{0}; +} +inline int64_t UsedBytesChangedEvent::_internal_usedbytes() const { + return _impl_.usedbytes_; +} +inline int64_t UsedBytesChangedEvent::usedbytes() const { + // @@protoc_insertion_point(field_get:grpc.UsedBytesChangedEvent.usedBytes) + return _internal_usedbytes(); +} +inline void UsedBytesChangedEvent::_internal_set_usedbytes(int64_t value) { + + _impl_.usedbytes_ = value; +} +inline void UsedBytesChangedEvent::set_usedbytes(int64_t value) { + _internal_set_usedbytes(value); + // @@protoc_insertion_point(field_set:grpc.UsedBytesChangedEvent.usedBytes) +} + +// ------------------------------------------------------------------- + // GenericErrorEvent // .grpc.ErrorCode code = 1; @@ -16144,6 +16482,8 @@ inline void GenericErrorEvent::set_code(::grpc::ErrorCode value) { // ------------------------------------------------------------------- +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/internal/frontend/grpc/bridge.pb.go b/internal/frontend/grpc/bridge.pb.go index f41b42e5..d25c8af5 100644 --- a/internal/frontend/grpc/bridge.pb.go +++ b/internal/frontend/grpc/bridge.pb.go @@ -3562,6 +3562,7 @@ type UserEvent struct { // *UserEvent_UserDisconnected // *UserEvent_UserChanged // *UserEvent_UserBadEvent + // *UserEvent_UsedBytesChangedEvent Event isUserEvent_Event `protobuf_oneof:"event"` } @@ -3632,6 +3633,13 @@ func (x *UserEvent) GetUserBadEvent() *UserBadEvent { return nil } +func (x *UserEvent) GetUsedBytesChangedEvent() *UsedBytesChangedEvent { + if x, ok := x.GetEvent().(*UserEvent_UsedBytesChangedEvent); ok { + return x.UsedBytesChangedEvent + } + return nil +} + type isUserEvent_Event interface { isUserEvent_Event() } @@ -3652,6 +3660,10 @@ type UserEvent_UserBadEvent struct { UserBadEvent *UserBadEvent `protobuf:"bytes,4,opt,name=userBadEvent,proto3,oneof"` } +type UserEvent_UsedBytesChangedEvent struct { + UsedBytesChangedEvent *UsedBytesChangedEvent `protobuf:"bytes,5,opt,name=usedBytesChangedEvent,proto3,oneof"` +} + func (*UserEvent_ToggleSplitModeFinished) isUserEvent_Event() {} func (*UserEvent_UserDisconnected) isUserEvent_Event() {} @@ -3660,6 +3672,8 @@ func (*UserEvent_UserChanged) isUserEvent_Event() {} func (*UserEvent_UserBadEvent) isUserEvent_Event() {} +func (*UserEvent_UsedBytesChangedEvent) isUserEvent_Event() {} + type ToggleSplitModeFinishedEvent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3856,6 +3870,61 @@ func (x *UserBadEvent) GetErrorMessage() string { return "" } +type UsedBytesChangedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` + UsedBytes int64 `protobuf:"varint,2,opt,name=usedBytes,proto3" json:"usedBytes,omitempty"` +} + +func (x *UsedBytesChangedEvent) Reset() { + *x = UsedBytesChangedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_bridge_proto_msgTypes[57] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *UsedBytesChangedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*UsedBytesChangedEvent) ProtoMessage() {} + +func (x *UsedBytesChangedEvent) ProtoReflect() protoreflect.Message { + mi := &file_bridge_proto_msgTypes[57] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use UsedBytesChangedEvent.ProtoReflect.Descriptor instead. +func (*UsedBytesChangedEvent) Descriptor() ([]byte, []int) { + return file_bridge_proto_rawDescGZIP(), []int{57} +} + +func (x *UsedBytesChangedEvent) GetUserID() string { + if x != nil { + return x.UserID + } + return "" +} + +func (x *UsedBytesChangedEvent) GetUsedBytes() int64 { + if x != nil { + return x.UsedBytes + } + return 0 +} + type GenericErrorEvent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3867,7 +3936,7 @@ type GenericErrorEvent struct { func (x *GenericErrorEvent) Reset() { *x = GenericErrorEvent{} if protoimpl.UnsafeEnabled { - mi := &file_bridge_proto_msgTypes[57] + mi := &file_bridge_proto_msgTypes[58] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3880,7 +3949,7 @@ func (x *GenericErrorEvent) String() string { func (*GenericErrorEvent) ProtoMessage() {} func (x *GenericErrorEvent) ProtoReflect() protoreflect.Message { - mi := &file_bridge_proto_msgTypes[57] + mi := &file_bridge_proto_msgTypes[58] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3893,7 +3962,7 @@ func (x *GenericErrorEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use GenericErrorEvent.ProtoReflect.Descriptor instead. func (*GenericErrorEvent) Descriptor() ([]byte, []int) { - return file_bridge_proto_rawDescGZIP(), []int{57} + return file_bridge_proto_rawDescGZIP(), []int{58} } func (x *GenericErrorEvent) GetCode() ErrorCode { @@ -4270,7 +4339,7 @@ var file_bridge_proto_rawDesc = []byte{ 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x13, 0x0a, 0x11, 0x41, 0x70, 0x69, 0x43, 0x65, 0x72, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x22, 0xb5, 0x02, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x5e, + 0x22, 0x8a, 0x03, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x70, 0x6c, @@ -4288,317 +4357,327 @@ var file_bridge_proto_rawDesc = []byte{ 0x61, 0x6e, 0x67, 0x65, 0x64, 0x12, 0x38, 0x0a, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x42, 0x61, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x42, 0x61, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, - 0x00, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x42, 0x61, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, - 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x36, 0x0a, 0x1c, 0x54, 0x6f, 0x67, 0x67, - 0x6c, 0x65, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, - 0x68, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, - 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, - 0x22, 0x33, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, - 0x63, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, - 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, - 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2a, 0x0a, 0x10, 0x55, 0x73, 0x65, 0x72, 0x43, 0x68, 0x61, - 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, - 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, - 0x44, 0x22, 0x4a, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x42, 0x61, 0x64, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x22, 0x0a, 0x0c, 0x65, 0x72, 0x72, - 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x38, 0x0a, - 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, - 0x32, 0x0f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, - 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x2a, 0x71, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, - 0x76, 0x65, 0x6c, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x50, 0x41, 0x4e, 0x49, 0x43, - 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, - 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, - 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x47, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x0c, - 0x0a, 0x08, 0x4c, 0x4f, 0x47, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, - 0x4c, 0x4f, 0x47, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4c, - 0x4f, 0x47, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x06, 0x2a, 0x36, 0x0a, 0x09, 0x55, 0x73, - 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x49, 0x47, 0x4e, 0x45, - 0x44, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, - 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44, - 0x10, 0x02, 0x2a, 0xa2, 0x01, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x53, 0x45, 0x52, 0x4e, 0x41, 0x4d, - 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x52, 0x45, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, - 0x01, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x46, 0x41, 0x5f, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x46, 0x41, 0x5f, 0x41, 0x42, - 0x4f, 0x52, 0x54, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x57, 0x4f, 0x5f, 0x50, 0x41, 0x53, - 0x53, 0x57, 0x4f, 0x52, 0x44, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x12, 0x17, - 0x0a, 0x13, 0x54, 0x57, 0x4f, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x53, 0x5f, - 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x06, 0x2a, 0x5b, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, - 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, - 0x52, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x4f, - 0x52, 0x43, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x55, - 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x49, 0x4c, 0x45, 0x4e, 0x54, 0x5f, 0x45, 0x52, 0x52, - 0x4f, 0x52, 0x10, 0x02, 0x2a, 0x6b, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x44, 0x49, - 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x5f, 0x55, 0x4e, 0x41, 0x56, 0x41, 0x49, 0x4c, - 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, - 0x43, 0x41, 0x4e, 0x54, 0x5f, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x43, - 0x41, 0x43, 0x48, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, - 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x46, 0x55, 0x4c, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, - 0x02, 0x2a, 0xdd, 0x01, 0x0a, 0x1b, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x53, - 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x1b, - 0x0a, 0x17, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, - 0x54, 0x55, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x49, - 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4d, 0x54, 0x50, 0x5f, - 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, - 0x52, 0x10, 0x03, 0x12, 0x25, 0x0a, 0x21, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, - 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, - 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x12, 0x25, 0x0a, 0x21, 0x53, 0x4d, - 0x54, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, - 0x44, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, - 0x05, 0x2a, 0x53, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x11, - 0x0a, 0x0d, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, - 0x00, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x5f, 0x45, 0x58, - 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, - 0x54, 0x4c, 0x53, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x32, 0x99, 0x1d, 0x0a, 0x06, 0x42, 0x72, 0x69, 0x64, 0x67, - 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, - 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3f, 0x0a, 0x0b, - 0x41, 0x64, 0x64, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x18, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3a, 0x0a, - 0x08, 0x47, 0x75, 0x69, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x75, 0x69, 0x52, 0x65, 0x61, 0x64, - 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x51, 0x75, 0x69, - 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x39, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0d, - 0x53, 0x68, 0x6f, 0x77, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x73, 0x74, - 0x61, 0x72, 0x74, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x49, 0x73, 0x41, - 0x75, 0x74, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, - 0x0a, 0x10, 0x53, 0x65, 0x74, 0x49, 0x73, 0x42, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x49, 0x73, 0x42, 0x65, 0x74, 0x61, - 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x49, 0x0a, 0x13, 0x53, - 0x65, 0x74, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x4d, 0x61, 0x69, 0x6c, 0x56, 0x69, 0x73, 0x69, 0x62, - 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x46, 0x0a, 0x10, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x4d, - 0x61, 0x69, 0x6c, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3c, - 0x0a, 0x04, 0x47, 0x6f, 0x4f, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3e, 0x0a, 0x0c, - 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x07, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, - 0x08, 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4c, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, - 0x6f, 0x74, 0x65, 0x73, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x00, 0x52, 0x0c, 0x75, 0x73, 0x65, 0x72, 0x42, 0x61, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x53, 0x0a, 0x15, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, 0x75, + 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x36, 0x0a, + 0x1c, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, + 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x33, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, + 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, + 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2a, 0x0a, 0x10, 0x55, 0x73, + 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x4a, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x42, 0x61, + 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x22, + 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, + 0x67, 0x65, 0x22, 0x4d, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x43, + 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, + 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, + 0x72, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, + 0x73, 0x22, 0x38, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x2a, 0x71, 0x0a, 0x08, 0x4c, + 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x50, + 0x41, 0x4e, 0x49, 0x43, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x46, 0x41, + 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x45, 0x52, 0x52, + 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x47, 0x5f, 0x57, 0x41, 0x52, 0x4e, + 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x47, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, + 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x05, 0x12, + 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x06, 0x2a, 0x36, + 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x53, + 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, + 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, + 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xa2, 0x01, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, + 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x53, 0x45, + 0x52, 0x4e, 0x41, 0x4d, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x52, 0x45, 0x45, 0x5f, 0x55, + 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, + 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x54, + 0x46, 0x41, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x46, + 0x41, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x57, 0x4f, + 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x57, 0x4f, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, + 0x52, 0x44, 0x53, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x06, 0x2a, 0x5b, 0x0a, 0x0f, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, + 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x5f, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x55, 0x50, 0x44, 0x41, 0x54, + 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, + 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x49, 0x4c, 0x45, 0x4e, 0x54, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0x6b, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x6b, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, + 0x0a, 0x1c, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x5f, 0x55, 0x4e, 0x41, + 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, + 0x12, 0x1e, 0x0a, 0x1a, 0x43, 0x41, 0x4e, 0x54, 0x5f, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x44, 0x49, + 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, + 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x46, 0x55, 0x4c, 0x4c, 0x5f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0xdd, 0x01, 0x0a, 0x1b, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x72, 0x72, 0x6f, + 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, + 0x52, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, + 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, + 0x53, 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, + 0x1a, 0x0a, 0x16, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x43, 0x48, 0x41, + 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, + 0x4d, 0x54, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x25, 0x0a, 0x21, 0x49, 0x4d, 0x41, 0x50, 0x5f, + 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, + 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x12, 0x25, + 0x0a, 0x21, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, + 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x10, 0x05, 0x2a, 0x53, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, + 0x64, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x45, 0x52, + 0x54, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, + 0x12, 0x18, 0x0a, 0x14, 0x54, 0x4c, 0x53, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x45, 0x58, 0x50, 0x4f, + 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x32, 0x99, 0x1d, 0x0a, 0x06, 0x42, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x6f, + 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x16, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, - 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x47, 0x0a, 0x0f, 0x4c, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x67, - 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, + 0x75, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x3f, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, + 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, + 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x3a, 0x0a, 0x08, 0x47, 0x75, 0x69, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, - 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, - 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x75, 0x69, + 0x52, 0x65, 0x61, 0x64, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, + 0x04, 0x51, 0x75, 0x69, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x43, 0x0a, 0x0d, 0x53, 0x68, 0x6f, 0x77, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, + 0x70, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, + 0x74, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, + 0x0d, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x6e, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x49, 0x73, 0x42, 0x65, 0x74, 0x61, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x49, 0x73, + 0x42, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x49, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x4d, 0x61, 0x69, 0x6c, 0x56, + 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x46, 0x0a, 0x10, 0x49, 0x73, + 0x41, 0x6c, 0x6c, 0x4d, 0x61, 0x69, 0x6c, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x47, 0x6f, 0x4f, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x4a, 0x0a, 0x12, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6d, 0x61, 0x69, 0x6c, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3b, 0x0a, 0x09, - 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4d, 0x0a, 0x15, 0x45, 0x78, 0x70, - 0x6f, 0x72, 0x74, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0d, 0x46, 0x6f, 0x72, 0x63, - 0x65, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x49, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, - 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x4c, 0x6f, - 0x67, 0x69, 0x6e, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x36, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x46, 0x41, 0x12, 0x12, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, - 0x32, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, - 0x62, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, - 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4c, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, - 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x13, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, - 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, - 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x48, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x44, 0x69, 0x73, 0x6b, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x45, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0c, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, 0x0a, 0x12, 0x4d, 0x61, - 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x12, 0x3e, 0x0a, 0x0c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, - 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x12, 0x47, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, - 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, - 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a, 0x08, 0x48, 0x6f, 0x73, - 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x49, - 0x73, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x72, 0x65, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, - 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x12, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, - 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, - 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, - 0x0a, 0x0f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, - 0x0a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x10, 0x53, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, - 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, - 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x12, 0x3f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, - 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x40, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x50, 0x61, + 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4c, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x65, + 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x16, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, + 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x4c, 0x69, 0x6e, 0x6b, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x47, 0x0a, 0x0f, 0x4c, 0x61, 0x6e, 0x64, 0x69, 0x6e, + 0x67, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, + 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x51, 0x0a, 0x16, 0x43, - 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, - 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, - 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, - 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, - 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, - 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, - 0x41, 0x0a, 0x0f, 0x53, 0x74, 0x6f, 0x70, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, + 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, + 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, - 0x2f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x4d, 0x61, 0x69, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x6e, 0x2d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x69, 0x6e, 0x74, - 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x3b, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, 0x12, 0x16, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4d, 0x0a, + 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, + 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0d, + 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x72, 0x12, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, + 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x33, + 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x46, 0x41, 0x12, + 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0f, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x12, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0a, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x43, 0x68, 0x65, + 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, + 0x61, 0x6c, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4c, 0x0a, 0x16, 0x53, 0x65, 0x74, + 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x13, 0x49, 0x73, 0x41, 0x75, 0x74, + 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x48, 0x0a, 0x10, 0x53, 0x65, 0x74, + 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, + 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0c, 0x49, 0x73, + 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, + 0x0a, 0x12, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6c, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a, + 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x45, 0x0a, 0x0a, 0x49, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x72, 0x65, 0x65, 0x12, 0x1b, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, + 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x12, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, + 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x47, + 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, + 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x47, 0x65, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x1a, 0x0a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, + 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, + 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, + 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x6f, 0x75, + 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x52, + 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x51, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x55, 0x73, 0x65, 0x72, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, + 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x74, 0x6f, 0x70, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, + 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x4d, 0x61, 0x69, 0x6c, 0x2f, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x2f, 0x76, 0x33, + 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4614,7 +4693,7 @@ func file_bridge_proto_rawDescGZIP() []byte { } var file_bridge_proto_enumTypes = make([]protoimpl.EnumInfo, 7) -var file_bridge_proto_msgTypes = make([]protoimpl.MessageInfo, 58) +var file_bridge_proto_msgTypes = make([]protoimpl.MessageInfo, 59) var file_bridge_proto_goTypes = []interface{}{ (LogLevel)(0), // 0: grpc.LogLevel (UserState)(0), // 1: grpc.UserState @@ -4680,11 +4759,12 @@ var file_bridge_proto_goTypes = []interface{}{ (*UserDisconnectedEvent)(nil), // 61: grpc.UserDisconnectedEvent (*UserChangedEvent)(nil), // 62: grpc.UserChangedEvent (*UserBadEvent)(nil), // 63: grpc.UserBadEvent - (*GenericErrorEvent)(nil), // 64: grpc.GenericErrorEvent - (*wrapperspb.StringValue)(nil), // 65: google.protobuf.StringValue - (*emptypb.Empty)(nil), // 66: google.protobuf.Empty - (*wrapperspb.BoolValue)(nil), // 67: google.protobuf.BoolValue - (*wrapperspb.Int32Value)(nil), // 68: google.protobuf.Int32Value + (*UsedBytesChangedEvent)(nil), // 64: grpc.UsedBytesChangedEvent + (*GenericErrorEvent)(nil), // 65: grpc.GenericErrorEvent + (*wrapperspb.StringValue)(nil), // 66: google.protobuf.StringValue + (*emptypb.Empty)(nil), // 67: google.protobuf.Empty + (*wrapperspb.BoolValue)(nil), // 68: google.protobuf.BoolValue + (*wrapperspb.Int32Value)(nil), // 69: google.protobuf.Int32Value } var file_bridge_proto_depIdxs = []int32{ 0, // 0: grpc.AddLogEntryRequest.level:type_name -> grpc.LogLevel @@ -4698,7 +4778,7 @@ var file_bridge_proto_depIdxs = []int32{ 50, // 8: grpc.StreamEvent.keychain:type_name -> grpc.KeychainEvent 54, // 9: grpc.StreamEvent.mail:type_name -> grpc.MailEvent 59, // 10: grpc.StreamEvent.user:type_name -> grpc.UserEvent - 64, // 11: grpc.StreamEvent.genericError:type_name -> grpc.GenericErrorEvent + 65, // 11: grpc.StreamEvent.genericError:type_name -> grpc.GenericErrorEvent 21, // 12: grpc.AppEvent.internetStatus:type_name -> grpc.InternetStatusEvent 22, // 13: grpc.AppEvent.toggleAutostartFinished:type_name -> grpc.ToggleAutostartFinishedEvent 23, // 14: grpc.AppEvent.resetFinished:type_name -> grpc.ResetFinishedEvent @@ -4741,120 +4821,121 @@ var file_bridge_proto_depIdxs = []int32{ 61, // 51: grpc.UserEvent.userDisconnected:type_name -> grpc.UserDisconnectedEvent 62, // 52: grpc.UserEvent.userChanged:type_name -> grpc.UserChangedEvent 63, // 53: grpc.UserEvent.userBadEvent:type_name -> grpc.UserBadEvent - 6, // 54: grpc.GenericErrorEvent.code:type_name -> grpc.ErrorCode - 65, // 55: grpc.Bridge.CheckTokens:input_type -> google.protobuf.StringValue - 7, // 56: grpc.Bridge.AddLogEntry:input_type -> grpc.AddLogEntryRequest - 66, // 57: grpc.Bridge.GuiReady:input_type -> google.protobuf.Empty - 66, // 58: grpc.Bridge.Quit:input_type -> google.protobuf.Empty - 66, // 59: grpc.Bridge.Restart:input_type -> google.protobuf.Empty - 66, // 60: grpc.Bridge.ShowOnStartup:input_type -> google.protobuf.Empty - 67, // 61: grpc.Bridge.SetIsAutostartOn:input_type -> google.protobuf.BoolValue - 66, // 62: grpc.Bridge.IsAutostartOn:input_type -> google.protobuf.Empty - 67, // 63: grpc.Bridge.SetIsBetaEnabled:input_type -> google.protobuf.BoolValue - 66, // 64: grpc.Bridge.IsBetaEnabled:input_type -> google.protobuf.Empty - 67, // 65: grpc.Bridge.SetIsAllMailVisible:input_type -> google.protobuf.BoolValue - 66, // 66: grpc.Bridge.IsAllMailVisible:input_type -> google.protobuf.Empty - 66, // 67: grpc.Bridge.GoOs:input_type -> google.protobuf.Empty - 66, // 68: grpc.Bridge.TriggerReset:input_type -> google.protobuf.Empty - 66, // 69: grpc.Bridge.Version:input_type -> google.protobuf.Empty - 66, // 70: grpc.Bridge.LogsPath:input_type -> google.protobuf.Empty - 66, // 71: grpc.Bridge.LicensePath:input_type -> google.protobuf.Empty - 66, // 72: grpc.Bridge.ReleaseNotesPageLink:input_type -> google.protobuf.Empty - 66, // 73: grpc.Bridge.DependencyLicensesLink:input_type -> google.protobuf.Empty - 66, // 74: grpc.Bridge.LandingPageLink:input_type -> google.protobuf.Empty - 65, // 75: grpc.Bridge.SetColorSchemeName:input_type -> google.protobuf.StringValue - 66, // 76: grpc.Bridge.ColorSchemeName:input_type -> google.protobuf.Empty - 66, // 77: grpc.Bridge.CurrentEmailClient:input_type -> google.protobuf.Empty - 9, // 78: grpc.Bridge.ReportBug:input_type -> grpc.ReportBugRequest - 65, // 79: grpc.Bridge.ExportTLSCertificates:input_type -> google.protobuf.StringValue - 65, // 80: grpc.Bridge.ForceLauncher:input_type -> google.protobuf.StringValue - 65, // 81: grpc.Bridge.SetMainExecutable:input_type -> google.protobuf.StringValue - 10, // 82: grpc.Bridge.Login:input_type -> grpc.LoginRequest - 10, // 83: grpc.Bridge.Login2FA:input_type -> grpc.LoginRequest - 10, // 84: grpc.Bridge.Login2Passwords:input_type -> grpc.LoginRequest - 11, // 85: grpc.Bridge.LoginAbort:input_type -> grpc.LoginAbortRequest - 66, // 86: grpc.Bridge.CheckUpdate:input_type -> google.protobuf.Empty - 66, // 87: grpc.Bridge.InstallUpdate:input_type -> google.protobuf.Empty - 67, // 88: grpc.Bridge.SetIsAutomaticUpdateOn:input_type -> google.protobuf.BoolValue - 66, // 89: grpc.Bridge.IsAutomaticUpdateOn:input_type -> google.protobuf.Empty - 66, // 90: grpc.Bridge.DiskCachePath:input_type -> google.protobuf.Empty - 65, // 91: grpc.Bridge.SetDiskCachePath:input_type -> google.protobuf.StringValue - 67, // 92: grpc.Bridge.SetIsDoHEnabled:input_type -> google.protobuf.BoolValue - 66, // 93: grpc.Bridge.IsDoHEnabled:input_type -> google.protobuf.Empty - 66, // 94: grpc.Bridge.MailServerSettings:input_type -> google.protobuf.Empty - 12, // 95: grpc.Bridge.SetMailServerSettings:input_type -> grpc.ImapSmtpSettings - 66, // 96: grpc.Bridge.Hostname:input_type -> google.protobuf.Empty - 68, // 97: grpc.Bridge.IsPortFree:input_type -> google.protobuf.Int32Value - 66, // 98: grpc.Bridge.AvailableKeychains:input_type -> google.protobuf.Empty - 65, // 99: grpc.Bridge.SetCurrentKeychain:input_type -> google.protobuf.StringValue - 66, // 100: grpc.Bridge.CurrentKeychain:input_type -> google.protobuf.Empty - 66, // 101: grpc.Bridge.GetUserList:input_type -> google.protobuf.Empty - 65, // 102: grpc.Bridge.GetUser:input_type -> google.protobuf.StringValue - 15, // 103: grpc.Bridge.SetUserSplitMode:input_type -> grpc.UserSplitModeRequest - 65, // 104: grpc.Bridge.LogoutUser:input_type -> google.protobuf.StringValue - 65, // 105: grpc.Bridge.RemoveUser:input_type -> google.protobuf.StringValue - 17, // 106: grpc.Bridge.ConfigureUserAppleMail:input_type -> grpc.ConfigureAppleMailRequest - 18, // 107: grpc.Bridge.RunEventStream:input_type -> grpc.EventStreamRequest - 66, // 108: grpc.Bridge.StopEventStream:input_type -> google.protobuf.Empty - 65, // 109: grpc.Bridge.CheckTokens:output_type -> google.protobuf.StringValue - 66, // 110: grpc.Bridge.AddLogEntry:output_type -> google.protobuf.Empty - 8, // 111: grpc.Bridge.GuiReady:output_type -> grpc.GuiReadyResponse - 66, // 112: grpc.Bridge.Quit:output_type -> google.protobuf.Empty - 66, // 113: grpc.Bridge.Restart:output_type -> google.protobuf.Empty - 67, // 114: grpc.Bridge.ShowOnStartup:output_type -> google.protobuf.BoolValue - 66, // 115: grpc.Bridge.SetIsAutostartOn:output_type -> google.protobuf.Empty - 67, // 116: grpc.Bridge.IsAutostartOn:output_type -> google.protobuf.BoolValue - 66, // 117: grpc.Bridge.SetIsBetaEnabled:output_type -> google.protobuf.Empty - 67, // 118: grpc.Bridge.IsBetaEnabled:output_type -> google.protobuf.BoolValue - 66, // 119: grpc.Bridge.SetIsAllMailVisible:output_type -> google.protobuf.Empty - 67, // 120: grpc.Bridge.IsAllMailVisible:output_type -> google.protobuf.BoolValue - 65, // 121: grpc.Bridge.GoOs:output_type -> google.protobuf.StringValue - 66, // 122: grpc.Bridge.TriggerReset:output_type -> google.protobuf.Empty - 65, // 123: grpc.Bridge.Version:output_type -> google.protobuf.StringValue - 65, // 124: grpc.Bridge.LogsPath:output_type -> google.protobuf.StringValue - 65, // 125: grpc.Bridge.LicensePath:output_type -> google.protobuf.StringValue - 65, // 126: grpc.Bridge.ReleaseNotesPageLink:output_type -> google.protobuf.StringValue - 65, // 127: grpc.Bridge.DependencyLicensesLink:output_type -> google.protobuf.StringValue - 65, // 128: grpc.Bridge.LandingPageLink:output_type -> google.protobuf.StringValue - 66, // 129: grpc.Bridge.SetColorSchemeName:output_type -> google.protobuf.Empty - 65, // 130: grpc.Bridge.ColorSchemeName:output_type -> google.protobuf.StringValue - 65, // 131: grpc.Bridge.CurrentEmailClient:output_type -> google.protobuf.StringValue - 66, // 132: grpc.Bridge.ReportBug:output_type -> google.protobuf.Empty - 66, // 133: grpc.Bridge.ExportTLSCertificates:output_type -> google.protobuf.Empty - 66, // 134: grpc.Bridge.ForceLauncher:output_type -> google.protobuf.Empty - 66, // 135: grpc.Bridge.SetMainExecutable:output_type -> google.protobuf.Empty - 66, // 136: grpc.Bridge.Login:output_type -> google.protobuf.Empty - 66, // 137: grpc.Bridge.Login2FA:output_type -> google.protobuf.Empty - 66, // 138: grpc.Bridge.Login2Passwords:output_type -> google.protobuf.Empty - 66, // 139: grpc.Bridge.LoginAbort:output_type -> google.protobuf.Empty - 66, // 140: grpc.Bridge.CheckUpdate:output_type -> google.protobuf.Empty - 66, // 141: grpc.Bridge.InstallUpdate:output_type -> google.protobuf.Empty - 66, // 142: grpc.Bridge.SetIsAutomaticUpdateOn:output_type -> google.protobuf.Empty - 67, // 143: grpc.Bridge.IsAutomaticUpdateOn:output_type -> google.protobuf.BoolValue - 65, // 144: grpc.Bridge.DiskCachePath:output_type -> google.protobuf.StringValue - 66, // 145: grpc.Bridge.SetDiskCachePath:output_type -> google.protobuf.Empty - 66, // 146: grpc.Bridge.SetIsDoHEnabled:output_type -> google.protobuf.Empty - 67, // 147: grpc.Bridge.IsDoHEnabled:output_type -> google.protobuf.BoolValue - 12, // 148: grpc.Bridge.MailServerSettings:output_type -> grpc.ImapSmtpSettings - 66, // 149: grpc.Bridge.SetMailServerSettings:output_type -> google.protobuf.Empty - 65, // 150: grpc.Bridge.Hostname:output_type -> google.protobuf.StringValue - 67, // 151: grpc.Bridge.IsPortFree:output_type -> google.protobuf.BoolValue - 13, // 152: grpc.Bridge.AvailableKeychains:output_type -> grpc.AvailableKeychainsResponse - 66, // 153: grpc.Bridge.SetCurrentKeychain:output_type -> google.protobuf.Empty - 65, // 154: grpc.Bridge.CurrentKeychain:output_type -> google.protobuf.StringValue - 16, // 155: grpc.Bridge.GetUserList:output_type -> grpc.UserListResponse - 14, // 156: grpc.Bridge.GetUser:output_type -> grpc.User - 66, // 157: grpc.Bridge.SetUserSplitMode:output_type -> google.protobuf.Empty - 66, // 158: grpc.Bridge.LogoutUser:output_type -> google.protobuf.Empty - 66, // 159: grpc.Bridge.RemoveUser:output_type -> google.protobuf.Empty - 66, // 160: grpc.Bridge.ConfigureUserAppleMail:output_type -> google.protobuf.Empty - 19, // 161: grpc.Bridge.RunEventStream:output_type -> grpc.StreamEvent - 66, // 162: grpc.Bridge.StopEventStream:output_type -> google.protobuf.Empty - 109, // [109:163] is the sub-list for method output_type - 55, // [55:109] is the sub-list for method input_type - 55, // [55:55] is the sub-list for extension type_name - 55, // [55:55] is the sub-list for extension extendee - 0, // [0:55] is the sub-list for field type_name + 64, // 54: grpc.UserEvent.usedBytesChangedEvent:type_name -> grpc.UsedBytesChangedEvent + 6, // 55: grpc.GenericErrorEvent.code:type_name -> grpc.ErrorCode + 66, // 56: grpc.Bridge.CheckTokens:input_type -> google.protobuf.StringValue + 7, // 57: grpc.Bridge.AddLogEntry:input_type -> grpc.AddLogEntryRequest + 67, // 58: grpc.Bridge.GuiReady:input_type -> google.protobuf.Empty + 67, // 59: grpc.Bridge.Quit:input_type -> google.protobuf.Empty + 67, // 60: grpc.Bridge.Restart:input_type -> google.protobuf.Empty + 67, // 61: grpc.Bridge.ShowOnStartup:input_type -> google.protobuf.Empty + 68, // 62: grpc.Bridge.SetIsAutostartOn:input_type -> google.protobuf.BoolValue + 67, // 63: grpc.Bridge.IsAutostartOn:input_type -> google.protobuf.Empty + 68, // 64: grpc.Bridge.SetIsBetaEnabled:input_type -> google.protobuf.BoolValue + 67, // 65: grpc.Bridge.IsBetaEnabled:input_type -> google.protobuf.Empty + 68, // 66: grpc.Bridge.SetIsAllMailVisible:input_type -> google.protobuf.BoolValue + 67, // 67: grpc.Bridge.IsAllMailVisible:input_type -> google.protobuf.Empty + 67, // 68: grpc.Bridge.GoOs:input_type -> google.protobuf.Empty + 67, // 69: grpc.Bridge.TriggerReset:input_type -> google.protobuf.Empty + 67, // 70: grpc.Bridge.Version:input_type -> google.protobuf.Empty + 67, // 71: grpc.Bridge.LogsPath:input_type -> google.protobuf.Empty + 67, // 72: grpc.Bridge.LicensePath:input_type -> google.protobuf.Empty + 67, // 73: grpc.Bridge.ReleaseNotesPageLink:input_type -> google.protobuf.Empty + 67, // 74: grpc.Bridge.DependencyLicensesLink:input_type -> google.protobuf.Empty + 67, // 75: grpc.Bridge.LandingPageLink:input_type -> google.protobuf.Empty + 66, // 76: grpc.Bridge.SetColorSchemeName:input_type -> google.protobuf.StringValue + 67, // 77: grpc.Bridge.ColorSchemeName:input_type -> google.protobuf.Empty + 67, // 78: grpc.Bridge.CurrentEmailClient:input_type -> google.protobuf.Empty + 9, // 79: grpc.Bridge.ReportBug:input_type -> grpc.ReportBugRequest + 66, // 80: grpc.Bridge.ExportTLSCertificates:input_type -> google.protobuf.StringValue + 66, // 81: grpc.Bridge.ForceLauncher:input_type -> google.protobuf.StringValue + 66, // 82: grpc.Bridge.SetMainExecutable:input_type -> google.protobuf.StringValue + 10, // 83: grpc.Bridge.Login:input_type -> grpc.LoginRequest + 10, // 84: grpc.Bridge.Login2FA:input_type -> grpc.LoginRequest + 10, // 85: grpc.Bridge.Login2Passwords:input_type -> grpc.LoginRequest + 11, // 86: grpc.Bridge.LoginAbort:input_type -> grpc.LoginAbortRequest + 67, // 87: grpc.Bridge.CheckUpdate:input_type -> google.protobuf.Empty + 67, // 88: grpc.Bridge.InstallUpdate:input_type -> google.protobuf.Empty + 68, // 89: grpc.Bridge.SetIsAutomaticUpdateOn:input_type -> google.protobuf.BoolValue + 67, // 90: grpc.Bridge.IsAutomaticUpdateOn:input_type -> google.protobuf.Empty + 67, // 91: grpc.Bridge.DiskCachePath:input_type -> google.protobuf.Empty + 66, // 92: grpc.Bridge.SetDiskCachePath:input_type -> google.protobuf.StringValue + 68, // 93: grpc.Bridge.SetIsDoHEnabled:input_type -> google.protobuf.BoolValue + 67, // 94: grpc.Bridge.IsDoHEnabled:input_type -> google.protobuf.Empty + 67, // 95: grpc.Bridge.MailServerSettings:input_type -> google.protobuf.Empty + 12, // 96: grpc.Bridge.SetMailServerSettings:input_type -> grpc.ImapSmtpSettings + 67, // 97: grpc.Bridge.Hostname:input_type -> google.protobuf.Empty + 69, // 98: grpc.Bridge.IsPortFree:input_type -> google.protobuf.Int32Value + 67, // 99: grpc.Bridge.AvailableKeychains:input_type -> google.protobuf.Empty + 66, // 100: grpc.Bridge.SetCurrentKeychain:input_type -> google.protobuf.StringValue + 67, // 101: grpc.Bridge.CurrentKeychain:input_type -> google.protobuf.Empty + 67, // 102: grpc.Bridge.GetUserList:input_type -> google.protobuf.Empty + 66, // 103: grpc.Bridge.GetUser:input_type -> google.protobuf.StringValue + 15, // 104: grpc.Bridge.SetUserSplitMode:input_type -> grpc.UserSplitModeRequest + 66, // 105: grpc.Bridge.LogoutUser:input_type -> google.protobuf.StringValue + 66, // 106: grpc.Bridge.RemoveUser:input_type -> google.protobuf.StringValue + 17, // 107: grpc.Bridge.ConfigureUserAppleMail:input_type -> grpc.ConfigureAppleMailRequest + 18, // 108: grpc.Bridge.RunEventStream:input_type -> grpc.EventStreamRequest + 67, // 109: grpc.Bridge.StopEventStream:input_type -> google.protobuf.Empty + 66, // 110: grpc.Bridge.CheckTokens:output_type -> google.protobuf.StringValue + 67, // 111: grpc.Bridge.AddLogEntry:output_type -> google.protobuf.Empty + 8, // 112: grpc.Bridge.GuiReady:output_type -> grpc.GuiReadyResponse + 67, // 113: grpc.Bridge.Quit:output_type -> google.protobuf.Empty + 67, // 114: grpc.Bridge.Restart:output_type -> google.protobuf.Empty + 68, // 115: grpc.Bridge.ShowOnStartup:output_type -> google.protobuf.BoolValue + 67, // 116: grpc.Bridge.SetIsAutostartOn:output_type -> google.protobuf.Empty + 68, // 117: grpc.Bridge.IsAutostartOn:output_type -> google.protobuf.BoolValue + 67, // 118: grpc.Bridge.SetIsBetaEnabled:output_type -> google.protobuf.Empty + 68, // 119: grpc.Bridge.IsBetaEnabled:output_type -> google.protobuf.BoolValue + 67, // 120: grpc.Bridge.SetIsAllMailVisible:output_type -> google.protobuf.Empty + 68, // 121: grpc.Bridge.IsAllMailVisible:output_type -> google.protobuf.BoolValue + 66, // 122: grpc.Bridge.GoOs:output_type -> google.protobuf.StringValue + 67, // 123: grpc.Bridge.TriggerReset:output_type -> google.protobuf.Empty + 66, // 124: grpc.Bridge.Version:output_type -> google.protobuf.StringValue + 66, // 125: grpc.Bridge.LogsPath:output_type -> google.protobuf.StringValue + 66, // 126: grpc.Bridge.LicensePath:output_type -> google.protobuf.StringValue + 66, // 127: grpc.Bridge.ReleaseNotesPageLink:output_type -> google.protobuf.StringValue + 66, // 128: grpc.Bridge.DependencyLicensesLink:output_type -> google.protobuf.StringValue + 66, // 129: grpc.Bridge.LandingPageLink:output_type -> google.protobuf.StringValue + 67, // 130: grpc.Bridge.SetColorSchemeName:output_type -> google.protobuf.Empty + 66, // 131: grpc.Bridge.ColorSchemeName:output_type -> google.protobuf.StringValue + 66, // 132: grpc.Bridge.CurrentEmailClient:output_type -> google.protobuf.StringValue + 67, // 133: grpc.Bridge.ReportBug:output_type -> google.protobuf.Empty + 67, // 134: grpc.Bridge.ExportTLSCertificates:output_type -> google.protobuf.Empty + 67, // 135: grpc.Bridge.ForceLauncher:output_type -> google.protobuf.Empty + 67, // 136: grpc.Bridge.SetMainExecutable:output_type -> google.protobuf.Empty + 67, // 137: grpc.Bridge.Login:output_type -> google.protobuf.Empty + 67, // 138: grpc.Bridge.Login2FA:output_type -> google.protobuf.Empty + 67, // 139: grpc.Bridge.Login2Passwords:output_type -> google.protobuf.Empty + 67, // 140: grpc.Bridge.LoginAbort:output_type -> google.protobuf.Empty + 67, // 141: grpc.Bridge.CheckUpdate:output_type -> google.protobuf.Empty + 67, // 142: grpc.Bridge.InstallUpdate:output_type -> google.protobuf.Empty + 67, // 143: grpc.Bridge.SetIsAutomaticUpdateOn:output_type -> google.protobuf.Empty + 68, // 144: grpc.Bridge.IsAutomaticUpdateOn:output_type -> google.protobuf.BoolValue + 66, // 145: grpc.Bridge.DiskCachePath:output_type -> google.protobuf.StringValue + 67, // 146: grpc.Bridge.SetDiskCachePath:output_type -> google.protobuf.Empty + 67, // 147: grpc.Bridge.SetIsDoHEnabled:output_type -> google.protobuf.Empty + 68, // 148: grpc.Bridge.IsDoHEnabled:output_type -> google.protobuf.BoolValue + 12, // 149: grpc.Bridge.MailServerSettings:output_type -> grpc.ImapSmtpSettings + 67, // 150: grpc.Bridge.SetMailServerSettings:output_type -> google.protobuf.Empty + 66, // 151: grpc.Bridge.Hostname:output_type -> google.protobuf.StringValue + 68, // 152: grpc.Bridge.IsPortFree:output_type -> google.protobuf.BoolValue + 13, // 153: grpc.Bridge.AvailableKeychains:output_type -> grpc.AvailableKeychainsResponse + 67, // 154: grpc.Bridge.SetCurrentKeychain:output_type -> google.protobuf.Empty + 66, // 155: grpc.Bridge.CurrentKeychain:output_type -> google.protobuf.StringValue + 16, // 156: grpc.Bridge.GetUserList:output_type -> grpc.UserListResponse + 14, // 157: grpc.Bridge.GetUser:output_type -> grpc.User + 67, // 158: grpc.Bridge.SetUserSplitMode:output_type -> google.protobuf.Empty + 67, // 159: grpc.Bridge.LogoutUser:output_type -> google.protobuf.Empty + 67, // 160: grpc.Bridge.RemoveUser:output_type -> google.protobuf.Empty + 67, // 161: grpc.Bridge.ConfigureUserAppleMail:output_type -> google.protobuf.Empty + 19, // 162: grpc.Bridge.RunEventStream:output_type -> grpc.StreamEvent + 67, // 163: grpc.Bridge.StopEventStream:output_type -> google.protobuf.Empty + 110, // [110:164] is the sub-list for method output_type + 56, // [56:110] is the sub-list for method input_type + 56, // [56:56] is the sub-list for extension type_name + 56, // [56:56] is the sub-list for extension extendee + 0, // [0:56] is the sub-list for field type_name } func init() { file_bridge_proto_init() } @@ -5548,6 +5629,18 @@ func file_bridge_proto_init() { } } file_bridge_proto_msgTypes[57].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*UsedBytesChangedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bridge_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GenericErrorEvent); i { case 0: return &v.state @@ -5623,6 +5716,7 @@ func file_bridge_proto_init() { (*UserEvent_UserDisconnected)(nil), (*UserEvent_UserChanged)(nil), (*UserEvent_UserBadEvent)(nil), + (*UserEvent_UsedBytesChangedEvent)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -5630,7 +5724,7 @@ func file_bridge_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_bridge_proto_rawDesc, NumEnums: 7, - NumMessages: 58, + NumMessages: 59, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/frontend/grpc/bridge.proto b/internal/frontend/grpc/bridge.proto index 0c13c4d2..957ca153 100644 --- a/internal/frontend/grpc/bridge.proto +++ b/internal/frontend/grpc/bridge.proto @@ -448,6 +448,7 @@ message UserEvent { UserDisconnectedEvent userDisconnected = 2; UserChangedEvent userChanged = 3; UserBadEvent userBadEvent = 4; + UsedBytesChangedEvent usedBytesChangedEvent= 5; } } @@ -468,6 +469,11 @@ message UserBadEvent { string errorMessage = 2; } +message UsedBytesChangedEvent { + string userID = 1; + int64 usedBytes = 2; +} + //********************************************************** // Generic errors //********************************************************** diff --git a/internal/frontend/grpc/event_factory.go b/internal/frontend/grpc/event_factory.go index 29b0f11c..98644291 100644 --- a/internal/frontend/grpc/event_factory.go +++ b/internal/frontend/grpc/event_factory.go @@ -177,6 +177,10 @@ func NewUserBadEvent(userID string, errorMessage string) *StreamEvent { return userEvent(&UserEvent{Event: &UserEvent_UserBadEvent{UserBadEvent: &UserBadEvent{UserID: userID, ErrorMessage: errorMessage}}}) } +func NewUsedBytesChangedEvent(userID string, usedBytes int) *StreamEvent { + return userEvent(&UserEvent{Event: &UserEvent_UsedBytesChangedEvent{UsedBytesChangedEvent: &UsedBytesChangedEvent{UserID: userID, UsedBytes: int64(usedBytes)}}}) +} + func NewGenericErrorEvent(errorCode ErrorCode) *StreamEvent { return genericErrorEvent(&GenericErrorEvent{Code: errorCode}) } diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index e1d281a8..5857d348 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -305,6 +305,9 @@ func (s *Service) watchEvents() { case events.AddressModeChanged: _ = s.SendEvent(NewUserChangedEvent(event.UserID)) + case events.UsedSpaceChanged: + _ = s.SendEvent(NewUsedBytesChangedEvent(event.UserID, event.UsedSpace)) + case events.UserDeauth: // This is the event the GUI cares about. _ = s.SendEvent(NewUserChangedEvent(event.UserID)) diff --git a/internal/frontend/grpc/service_stream.go b/internal/frontend/grpc/service_stream.go index 5a727585..83d6c4d2 100644 --- a/internal/frontend/grpc/service_stream.go +++ b/internal/frontend/grpc/service_stream.go @@ -174,6 +174,7 @@ func (s *Service) StartEventTest() error { //nolint:funlen NewUserToggleSplitModeFinishedEvent("userID"), NewUserDisconnectedEvent("username"), NewUserChangedEvent("userID"), + NewUsedBytesChangedEvent("userID", 1000), } for _, event := range events { diff --git a/internal/user/events.go b/internal/user/events.go index 5311c8bd..b009a2f6 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -66,6 +66,10 @@ func (user *User) handleAPIEvent(ctx context.Context, event proton.Event) error } } + if event.UsedSpace != nil { + user.handleUsedSpaceChange(*event.UsedSpace) + } + return nil } @@ -655,6 +659,20 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event proton.Messa }, user.apiUserLock, user.apiAddrsLock, user.apiLabelsLock, user.updateChLock) } +func (user *User) handleUsedSpaceChange(usedSpace int) { + safe.Lock(func() { + if user.apiUser.UsedSpace == usedSpace { + return + } + + user.apiUser.UsedSpace = usedSpace + user.eventCh.Enqueue(events.UsedSpaceChanged{ + UserID: user.apiUser.ID, + UsedSpace: usedSpace, + }) + }, user.apiUserLock) +} + func getMailboxName(label proton.Label) []string { var name []string From c0aacb7d624222dd147fdc6ea838d7a90736874c Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Tue, 31 Jan 2023 09:13:41 +0100 Subject: [PATCH 005/130] GODT-2224: Allow the user to specify max sync memory usage in Vault --- internal/bridge/user.go | 1 + internal/user/sync.go | 30 +++++++++++++++++++++++++----- internal/user/user.go | 5 +++++ internal/user/user_test.go | 6 +++--- internal/vault/settings.go | 20 +++++++++++++++++++- internal/vault/settings_test.go | 8 ++++++++ internal/vault/types_settings.go | 6 ++++++ 7 files changed, 67 insertions(+), 9 deletions(-) diff --git a/internal/bridge/user.go b/internal/bridge/user.go index fa86a313..6d355d2a 100644 --- a/internal/bridge/user.go +++ b/internal/bridge/user.go @@ -462,6 +462,7 @@ func (bridge *Bridge) addUserWithVault( apiUser, bridge.crashHandler, bridge.vault.GetShowAllMail(), + bridge.vault.GetMaxSyncMemory(), ) if err != nil { return fmt.Errorf("failed to create user: %w", err) diff --git a/internal/user/sync.go b/internal/user/sync.go index 0735ed83..ccf7b06b 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -141,6 +141,7 @@ func (user *User) sync(ctx context.Context) error { addrKRs, user.updateCh, user.eventCh, + user.maxSyncMemory, ); err != nil { return fmt.Errorf("failed to sync messages: %w", err) } @@ -229,6 +230,7 @@ func syncMessages( addrKRs map[string]*crypto.KeyRing, updateCh map[string]*queue.QueuedChannel[imap.Update], eventCh *queue.QueuedChannel[events.Event], + maxSyncMemory uint64, ) error { ctx, cancel := context.WithCancel(ctx) defer cancel() @@ -267,25 +269,43 @@ func syncMessages( const maxParallelDownloads = 20 totalMemory := memory.TotalMemory() + + if maxSyncMemory >= totalMemory/2 { + logrus.Warnf("Requested max sync memory of %v MB is greater than half of system memory (%v MB), forcing to half of system memory", + maxSyncMemory, toMB(totalMemory/2)) + maxSyncMemory = totalMemory / 2 + } + + if maxSyncMemory < 800*Megabyte { + logrus.Warnf("Requested max sync memory of %v MB, but minimum recommended is 800 MB, forcing max syncMemory to 800MB", toMB(maxSyncMemory)) + maxSyncMemory = 800 * Megabyte + } + logrus.Debugf("Total System Memory: %v", toMB(totalMemory)) syncMaxDownloadRequestMem := MaxDownloadRequestMem syncMaxMessageBuildingMem := MaxMessageBuildingMem // If less than 2GB available try and limit max memory to 512 MB - if totalMemory < 2*Gigabyte { - if totalMemory < 800*Megabyte { + switch { + case maxSyncMemory < 2*Gigabyte: + if maxSyncMemory < 800*Megabyte { logrus.Warnf("System has less than 800MB of memory, you may experience issues sycing large mailboxes") } syncMaxDownloadRequestMem = MinDownloadRequestMem syncMaxMessageBuildingMem = MinMessageBuildingMem - } else { + case maxSyncMemory == 2*Gigabyte: // Increasing the max download capacity has very little effect on sync speed. We could increase the download // memory but the user would see less sync notifications. A smaller value here leads to more frequent // updates. Additionally, most of ot sync time is spent in the message building. syncMaxDownloadRequestMem = MaxDownloadRequestMem // Currently limited so that if a user has multiple accounts active it also doesn't cause excessive memory usage. syncMaxMessageBuildingMem = MaxMessageBuildingMem + default: + // Divide by 8 as download stage and build stage will use aprox. 4x the specified memory. + remainingMemory := (maxSyncMemory - 2*Gigabyte) / 8 + syncMaxDownloadRequestMem = MaxDownloadRequestMem + remainingMemory + syncMaxMessageBuildingMem = MaxMessageBuildingMem + remainingMemory } logrus.Debugf("Max memory usage for sync Download=%vMB Building=%vMB Predicted Max Total=%vMB", @@ -504,6 +524,8 @@ func syncMessages( } for index, chunk := range chunks { + logrus.Debugf("Build request: %v of %v count=%v", index, len(chunks), len(chunk)) + result, err := parallel.MapContext(ctx, maxMessagesInParallel, chunk, func(ctx context.Context, msg proton.FullMessage) (*buildRes, error) { return buildRFC822(apiLabels, msg, addrKRs[msg.AddressID], new(bytes.Buffer)), nil }) @@ -511,8 +533,6 @@ func syncMessages( return } - logrus.Debugf("Build request: %v of %v", index, len(chunks)) - select { case flushCh <- builtMessageBatch{result}: diff --git a/internal/user/user.go b/internal/user/user.go index abdef220..f1c4b9fd 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -85,6 +85,8 @@ type User struct { goPollAPIEvents func(wait bool) showAllMail uint32 + + maxSyncMemory uint64 } // New returns a new user. @@ -98,6 +100,7 @@ func New( apiUser proton.User, crashHandler async.PanicHandler, showAllMail bool, + maxSyncMemory uint64, ) (*User, error) { //nolint:funlen logrus.WithField("userID", apiUser.ID).Info("Creating new user") @@ -141,6 +144,8 @@ func New( pollAPIEventsCh: make(chan chan struct{}), showAllMail: b32(showAllMail), + + maxSyncMemory: maxSyncMemory, } // Initialize the user's update channels for its current address mode. diff --git a/internal/user/user_test.go b/internal/user/user_test.go index 13efde1c..8542bac2 100644 --- a/internal/user/user_test.go +++ b/internal/user/user_test.go @@ -209,14 +209,14 @@ func withUser(tb testing.TB, ctx context.Context, _ *server.Server, m *proton.Ma saltedKeyPass, err := salts.SaltForKey([]byte(password), apiUser.Keys.Primary().ID) require.NoError(tb, err) - vault, corrupt, err := vault.New(tb.TempDir(), tb.TempDir(), []byte("my secret key")) + v, corrupt, err := vault.New(tb.TempDir(), tb.TempDir(), []byte("my secret key")) require.NoError(tb, err) require.False(tb, corrupt) - vaultUser, err := vault.AddUser(apiUser.ID, username, username+"@pm.me", apiAuth.UID, apiAuth.RefreshToken, saltedKeyPass) + vaultUser, err := v.AddUser(apiUser.ID, username, username+"@pm.me", apiAuth.UID, apiAuth.RefreshToken, saltedKeyPass) require.NoError(tb, err) - user, err := New(ctx, vaultUser, client, nil, apiUser, nil, true) + user, err := New(ctx, vaultUser, client, nil, apiUser, nil, true, vault.DefaultMaxSyncMemory) require.NoError(tb, err) defer user.Close() diff --git a/internal/vault/settings.go b/internal/vault/settings.go index 904b0374..b452c44f 100644 --- a/internal/vault/settings.go +++ b/internal/vault/settings.go @@ -178,7 +178,7 @@ func (vault *Vault) SetLastVersion(version *semver.Version) error { }) } -// GetFirstStart sets whether this is the first time the bridge has been started. +// GetFirstStart returns whether this is the first time the bridge has been started. func (vault *Vault) GetFirstStart() bool { return vault.get().Settings.FirstStart } @@ -189,3 +189,21 @@ func (vault *Vault) SetFirstStart(firstStart bool) error { data.Settings.FirstStart = firstStart }) } + +// GetMaxSyncMemory returns the maximum amount of memory the sync process should use. +func (vault *Vault) GetMaxSyncMemory() uint64 { + v := vault.get().Settings.MaxSyncMemory + // can be zero if never written to vault before. + if v == 0 { + return DefaultMaxSyncMemory + } + + return v +} + +// SetMaxSyncMemory sets the maximum amount of memory the sync process should use. +func (vault *Vault) SetMaxSyncMemory(maxMemory uint64) error { + return vault.mod(func(data *Data) { + data.Settings.MaxSyncMemory = maxMemory + }) +} diff --git a/internal/vault/settings_test.go b/internal/vault/settings_test.go index 4b90b3ba..fa099e09 100644 --- a/internal/vault/settings_test.go +++ b/internal/vault/settings_test.go @@ -202,3 +202,11 @@ func TestVault_Settings_FirstStart(t *testing.T) { // Check the new first start value. require.Equal(t, false, s.GetFirstStart()) } + +func TestVault_Settings_MaxSyncMemory(t *testing.T) { + // create a new test vault. + s := newVault(t) + + // Check the default first start value. + require.Equal(t, vault.DefaultMaxSyncMemory, s.GetMaxSyncMemory()) +} diff --git a/internal/vault/types_settings.go b/internal/vault/types_settings.go index 4ba00f7e..bb6946a3 100644 --- a/internal/vault/types_settings.go +++ b/internal/vault/types_settings.go @@ -42,8 +42,12 @@ type Settings struct { LastVersion string FirstStart bool + + MaxSyncMemory uint64 } +const DefaultMaxSyncMemory = 2 * 1024 * uint64(1024*1024) + func newDefaultSettings(gluonDir string) Settings { return Settings{ GluonDir: gluonDir, @@ -64,5 +68,7 @@ func newDefaultSettings(gluonDir string) Settings { LastVersion: "0.0.0", FirstStart: true, + + MaxSyncMemory: DefaultMaxSyncMemory, } } From 4577a40b1e19109abf8758f97a5828b1c9abb4b0 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Tue, 31 Jan 2023 12:22:59 +0100 Subject: [PATCH 006/130] fix(GODT-2224): Restore parallel attachment download Feature was not restored in previous MR. Attachment are now download in parallel. There is a pool of maxParallelDownloads attachment downloaders shared with all message downloads. --- internal/user/sync.go | 106 +++++++++++++++++++++++++++++++++++------- 1 file changed, 90 insertions(+), 16 deletions(-) diff --git a/internal/user/sync.go b/internal/user/sync.go index ccf7b06b..af432080 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -415,6 +415,9 @@ func syncMessages( logrus.Debugf("sync downloader exit") }() + attachmentDownloader := newAttachmentDownloader(ctx, client, maxParallelDownloads) + defer attachmentDownloader.close() + for request := range downloadCh { logrus.Debugf("Download request: %v MB:%v", len(request.ids), toMB(request.expectedSize)) if request.err != nil { @@ -435,25 +438,13 @@ func syncMessages( return proton.FullMessage{}, err } - var attachmentSize int64 - for _, a := range msg.Attachments { - attachmentSize += a.Size - } - - // allocate attachment data. - result.AttData = make([][]byte, len(msg.Attachments)) - - for i, a := range msg.Attachments { - var buffer bytes.Buffer - buffer.Grow(int(a.Size)) - if err := client.GetAttachmentInto(ctx, a.ID, &buffer); err != nil { - return proton.FullMessage{}, err - } - - result.AttData[i] = buffer.Bytes() + attachments, err := attachmentDownloader.getAttachments(ctx, msg.Attachments) + if err != nil { + return proton.FullMessage{}, err } result.Message = msg + result.AttData = attachments return result, nil }) @@ -738,3 +729,86 @@ func wantLabels(apiLabels map[string]proton.Label, labelIDs []string) []string { return wantLabel(apiLabels[labelID]) }) } + +type attachmentResult struct { + attachment []byte + err error +} + +type attachmentJob struct { + id string + size int64 + result chan attachmentResult +} + +type attachmentDownloader struct { + workerCh chan attachmentJob + cancel context.CancelFunc +} + +func attachmentWorker(ctx context.Context, client *proton.Client, work <-chan attachmentJob) { + for { + select { + case <-ctx.Done(): + return + case job, ok := <-work: + if !ok { + return + } + var b bytes.Buffer + b.Grow(int(job.size)) + err := client.GetAttachmentInto(ctx, job.id, &b) + select { + case <-ctx.Done(): + close(job.result) + return + case job.result <- attachmentResult{attachment: b.Bytes(), err: err}: + close(job.result) + } + } + } +} + +func newAttachmentDownloader(ctx context.Context, client *proton.Client, workerCount int) *attachmentDownloader { + workerCh := make(chan attachmentJob, (workerCount+2)*workerCount) + ctx, cancel := context.WithCancel(ctx) + for i := 0; i < workerCount; i++ { + workerCh = make(chan attachmentJob) + logging.GoAnnotated(ctx, func(ctx context.Context) { attachmentWorker(ctx, client, workerCh) }, logging.Labels{ + "sync": fmt.Sprintf("att-downloader %v", i), + }) + } + + return &attachmentDownloader{ + workerCh: workerCh, + cancel: cancel, + } +} + +func (a *attachmentDownloader) getAttachments(ctx context.Context, attachments []proton.Attachment) ([][]byte, error) { + resultChs := make([]chan attachmentResult, len(attachments)) + for i, id := range attachments { + resultChs[i] = make(chan attachmentResult, 1) + a.workerCh <- attachmentJob{id: id.ID, result: resultChs[i], size: id.Size} + } + + result := make([][]byte, len(attachments)) + var err error + for i := 0; i < len(attachments); i++ { + select { + case <-ctx.Done(): + return nil, ctx.Err() + case r := <-resultChs[i]: + if r.err != nil { + err = fmt.Errorf("failed to get attachment %v: %w", attachments[i], r.err) + } + result[i] = r.attachment + } + } + + return result, err +} + +func (a *attachmentDownloader) close() { + a.cancel() +} From e3826871682a15b5c543c0063ef1a06e09871920 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 31 Jan 2023 11:04:19 +0100 Subject: [PATCH 007/130] fix(GODT-2318): Remove gluon DB if label sync was incomplete --- internal/bridge/imap.go | 24 +++++++++++++++++++++++- internal/user/user.go | 5 +++++ internal/vault/user.go | 5 +++++ 3 files changed, 33 insertions(+), 1 deletion(-) diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index b9fd540f..e8deded8 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -100,6 +100,8 @@ func (bridge *Bridge) closeIMAP(ctx context.Context) error { } // addIMAPUser connects the given user to gluon. +// +//nolint:funlen func (bridge *Bridge) addIMAPUser(ctx context.Context, user *user.User) error { if bridge.imapServer == nil { return fmt.Errorf("no imap server instance running") @@ -125,13 +127,33 @@ func (bridge *Bridge) addIMAPUser(ctx context.Context, user *user.User) error { return fmt.Errorf("failed to load IMAP user: %w", err) } - // If the DB was newly created, clear the sync status; gluon's DB was not found. if isNew { + // If the DB was newly created, clear the sync status; gluon's DB was not found. logrus.Warn("IMAP user DB was newly created, clearing sync status") if err := user.ClearSyncStatus(); err != nil { return fmt.Errorf("failed to clear sync status: %w", err) } + } else if status := user.GetSyncStatus(); !status.HasLabels { + // Otherwise, the DB already exists -- if the labels are not yet synced, we need to re-create the DB. + if err := bridge.imapServer.RemoveUser(ctx, gluonID, true); err != nil { + return fmt.Errorf("failed to remove old IMAP user: %w", err) + } + + if err := user.RemoveGluonID(addrID, gluonID); err != nil { + return fmt.Errorf("failed to remove old IMAP user ID: %w", err) + } + + gluonID, err := bridge.imapServer.AddUser(ctx, imapConn, user.GluonKey()) + if err != nil { + return fmt.Errorf("failed to add IMAP user: %w", err) + } + + if err := user.SetGluonID(addrID, gluonID); err != nil { + return fmt.Errorf("failed to set IMAP user ID: %w", err) + } + + log.WithField("gluonID", gluonID).Info("Re-created IMAP user") } } else { log.Info("Creating new IMAP user") diff --git a/internal/user/user.go b/internal/user/user.go index f1c4b9fd..abdbadb3 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -477,6 +477,11 @@ func (user *User) OnStatusDown(context.Context) { user.abortable.Abort() } +// GetSyncStatus returns the sync status of the user. +func (user *User) GetSyncStatus() vault.SyncStatus { + return user.vault.GetSyncStatus() +} + // ClearSyncStatus clears the sync status of the user. This triggers a resync. func (user *User) ClearSyncStatus() error { user.abortable.Abort() diff --git a/internal/vault/user.go b/internal/vault/user.go index f80011bb..1f3bf8b6 100644 --- a/internal/vault/user.go +++ b/internal/vault/user.go @@ -197,6 +197,11 @@ func (user *User) RemFailedMessageID(messageID string) error { }) } +// GetSyncStatus returns the user's sync status. +func (user *User) GetSyncStatus() SyncStatus { + return user.vault.getUser(user.userID).SyncStatus +} + // ClearSyncStatus clears the user's sync status. func (user *User) ClearSyncStatus() error { return user.vault.modUser(user.userID, func(data *UserData) { From 342a2a5568f82725de038a13ed26d51f897db32e Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Tue, 31 Jan 2023 15:35:03 +0100 Subject: [PATCH 008/130] fix(GODT-2272): use shorter filename for gRPC file socket. --- README.md | 2 +- internal/frontend/grpc/service.go | 10 +++++++++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c6903c55..466f514e 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,6 @@ There are now three types of system folders which Bridge recognises: | gluon messages | sata | gluon/backend/store | | Update files | data | updates | | sentry cache | data | sentry_cache | -| Mac/Linux File Socket | temp | bridge_{RANDOM_UUID}.sock | +| Mac/Linux File Socket | temp | bridge{4_DIGITS} | diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index 5857d348..f65ee84e 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -25,6 +25,7 @@ import ( "errors" "fmt" "io/fs" + "math/rand" "net" "os" "path/filepath" @@ -580,10 +581,17 @@ func (s *Service) monitorParentPID() { func computeFileSocketPath() (string, error) { tempPath := os.TempDir() for i := 0; i < 1000; i++ { - path := filepath.Join(tempPath, fmt.Sprintf("bridge_%v.sock", uuid.NewString())) + path := filepath.Join(tempPath, fmt.Sprintf("bridge%04d", rand.Intn(10000))) // nolint:gosec if _, err := os.Stat(path); errors.Is(err, fs.ErrNotExist) { return path, nil } + + if err := os.Remove(path); err != nil { + logrus.WithField("path", path).WithError(err).Warning("Could not remove existing socket file") + continue + } + + return path, nil } return "", errors.New("unable to find a suitable file socket in user config folder") From 590fdacba3027ddd4a783e93f51ddd1b2411ec6e Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Tue, 31 Jan 2023 13:34:01 +0100 Subject: [PATCH 009/130] fix(GODT-2319): seed the math/rand RNG on app startup. --- internal/app/app.go | 5 +++++ internal/vault/settings.go | 20 +++++++++++++++++++- internal/vault/settings_test.go | 5 +++++ 3 files changed, 29 insertions(+), 1 deletion(-) diff --git a/internal/app/app.go b/internal/app/app.go index db93442f..6663a920 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -19,11 +19,13 @@ package app import ( "fmt" + "math/rand" "net/http" "net/http/cookiejar" "os" "path/filepath" "runtime" + "time" "github.com/Masterminds/semver/v3" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" @@ -155,6 +157,9 @@ func New() *cli.App { //nolint:funlen } func run(c *cli.Context) error { //nolint:funlen + // Seed the default RNG from the math/rand package. + rand.Seed(time.Now().UnixNano()) + // Get the current bridge version. version, err := semver.NewVersion(constants.Version) if err != nil { diff --git a/internal/vault/settings.go b/internal/vault/settings.go index b452c44f..9967e307 100644 --- a/internal/vault/settings.go +++ b/internal/vault/settings.go @@ -18,8 +18,16 @@ package vault import ( + "math" + "math/rand" + "github.com/Masterminds/semver/v3" "github.com/ProtonMail/proton-bridge/v3/internal/updater" + "github.com/sirupsen/logrus" +) + +const ( + ForbiddenRollout = 0.6046602879796196 ) // GetIMAPPort sets the port that the IMAP server should listen on. @@ -96,7 +104,17 @@ func (vault *Vault) SetUpdateChannel(channel updater.Channel) error { // GetUpdateRollout sets the update rollout. func (vault *Vault) GetUpdateRollout() float64 { - return vault.get().Settings.UpdateRollout + // The rollout value 0.6046602879796196 is forbidden. The RNG was not seeded when it was picked (GODT-2319). + rollout := vault.get().Settings.UpdateRollout + if math.Abs(rollout-ForbiddenRollout) >= 0.00000001 { + return rollout + } + + rollout = rand.Float64() //nolint:gosec + if err := vault.SetUpdateRollout(rollout); err != nil { + logrus.WithError(err).Warning("Failed writing updateRollout value in vault") + } + return rollout } // SetUpdateRollout sets the update rollout. diff --git a/internal/vault/settings_test.go b/internal/vault/settings_test.go index fa099e09..33528fae 100644 --- a/internal/vault/settings_test.go +++ b/internal/vault/settings_test.go @@ -18,6 +18,7 @@ package vault_test import ( + "math" "testing" "github.com/Masterminds/semver/v3" @@ -103,6 +104,10 @@ func TestVault_Settings_UpdateRollout(t *testing.T) { // Check the new update rollout. require.Equal(t, float64(0.5), s.GetUpdateRollout()) + + // Since GODT-2319 0.6046602879796196 is not allowed as a rollout value (RNG was not seeded) + require.NoError(t, s.SetUpdateRollout(vault.ForbiddenRollout)) + require.GreaterOrEqual(t, math.Abs(s.GetUpdateRollout()-vault.ForbiddenRollout), 0.00000001) } func TestVault_Settings_ColorScheme(t *testing.T) { From f14ad8b3fa51182bb814b8053d7062372f7de29f Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Tue, 31 Jan 2023 16:31:11 +0100 Subject: [PATCH 010/130] chore: README update. --- README.md | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 466f514e..60f890ed 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ # Proton Mail Bridge and Import Export app -Copyright (c) 2022 Proton AG +Copyright (c) 2023 Proton AG This repository holds the Proton Mail Bridge and the Proton Mail Import-Export applications. For a detailed build information see [BUILDS](./BUILDS.md). @@ -48,9 +48,6 @@ major problems. ## Environment Variables -### Bridge application -- `BRIDGESTRICTMODE`: tells bridge to turn on `bbolt`'s "strict mode" which checks the database after every `Commit`. Set to `1` to enable. - ### Dev build or run - `APP_VERSION`: set the bridge app version used during testing or building - `PROTONMAIL_ENV`: when set to `dev` it is not using Sentry to report crashes @@ -86,7 +83,7 @@ There are now three types of system folders which Bridge recognises: | gRPC client json | config | grpcClientConfig_.json | | Logs | data | logs | | gluon DB | data | gluon/backend/db | -| gluon messages | sata | gluon/backend/store | +| gluon messages | data | gluon/backend/store | | Update files | data | updates | | sentry cache | data | sentry_cache | | Mac/Linux File Socket | temp | bridge{4_DIGITS} | From 79c252358549221189f49b7fdcaadeed69f83996 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 31 Jan 2023 17:35:51 +0100 Subject: [PATCH 011/130] chore: Add recipient to SMTP error message --- internal/user/smtp.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/user/smtp.go b/internal/user/smtp.go index 09080e54..5c0b03be 100644 --- a/internal/user/smtp.go +++ b/internal/user/smtp.go @@ -468,12 +468,12 @@ func getRecipients( prefs, err := parallel.MapContext(ctx, runtime.NumCPU(), addresses, func(ctx context.Context, recipient string) (proton.SendPreferences, error) { pubKeys, recType, err := client.GetPublicKeys(ctx, recipient) if err != nil { - return proton.SendPreferences{}, fmt.Errorf("failed to get public keys: %w", err) + return proton.SendPreferences{}, fmt.Errorf("failed to get public key for %v: %w", recipient, err) } contactSettings, err := getContactSettings(ctx, client, userKR, recipient) if err != nil { - return proton.SendPreferences{}, fmt.Errorf("failed to get contact settings: %w", err) + return proton.SendPreferences{}, fmt.Errorf("failed to get contact settings for %v: %w", recipient, err) } return buildSendPrefs(contactSettings, settings, pubKeys, draft.MIMEType, recType == proton.RecipientTypeInternal) From 45ec6b6e7469b3943ffdf097acd0ac6de206218d Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Wed, 1 Feb 2023 14:04:45 +0100 Subject: [PATCH 012/130] feat(GODT-2289): UIDValidity as Timestamp Update UIDValidity to be timestamp with the number of seconds since the 1st of February 2023. This avoids the problem where we lose the last UIDValidity value due to the vault being missing/corrupted/deleted. --- go.mod | 2 +- go.sum | 4 ++-- internal/app/bridge.go | 2 ++ internal/bridge/bridge.go | 9 +++++++++ internal/bridge/bridge_test.go | 5 +++++ internal/bridge/imap.go | 3 +++ internal/bridge/refresh_test.go | 5 +++-- internal/bridge/settings.go | 1 + internal/user/imap.go | 10 ---------- internal/vault/types_user.go | 4 ---- internal/vault/user.go | 23 ----------------------- tests/ctx_bridge_test.go | 2 ++ 12 files changed, 28 insertions(+), 42 deletions(-) diff --git a/go.mod b/go.mod index e01a6075..69d486c0 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230130104154-2c64e59b8f54 + github.com/ProtonMail/gluon v0.14.2-0.20230201115538-18e0b89693fc github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.3.1-0.20230130144605-4b05f1e5c427 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 3e164c8b..49a271b5 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230130104154-2c64e59b8f54 h1:uUg8CDiYTMlbvGijzoN0fb72vwDJD7hMjgNTbmAHxRc= -github.com/ProtonMail/gluon v0.14.2-0.20230130104154-2c64e59b8f54/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230201115538-18e0b89693fc h1:q7sX422Eu9H97v2sLRPmPFi8yBJtNwQRzVN9DSmBHvc= +github.com/ProtonMail/gluon v0.14.2-0.20230201115538-18e0b89693fc/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/internal/app/bridge.go b/internal/app/bridge.go index 668aca59..38ce3c82 100644 --- a/internal/app/bridge.go +++ b/internal/app/bridge.go @@ -23,6 +23,7 @@ import ( "runtime" "github.com/Masterminds/semver/v3" + "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/go-autostart" "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" @@ -110,6 +111,7 @@ func withBridge( //nolint:funlen // Crash and report stuff crashHandler, reporter, + imap.DefaultEpochUIDValidityGenerator(), // The logging stuff. c.String(flagLogIMAP) == "client" || c.String(flagLogIMAP) == "all", diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index 1a6de766..43cd7087 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -30,6 +30,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/ProtonMail/gluon" imapEvents "github.com/ProtonMail/gluon/events" + "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/gluon/watcher" "github.com/ProtonMail/go-proton-api" @@ -122,6 +123,8 @@ type Bridge struct { // goUpdate triggers a check/install of updates. goUpdate func() + + uidValidityGenerator imap.UIDValidityGenerator } // New creates a new bridge. @@ -140,6 +143,7 @@ func New( //nolint:funlen proxyCtl ProxyController, // the DoH controller crashHandler async.PanicHandler, reporter reporter.Reporter, + uidValidityGenerator imap.UIDValidityGenerator, logIMAPClient, logIMAPServer bool, // whether to log IMAP client/server activity logSMTP bool, // whether to log SMTP activity @@ -169,6 +173,7 @@ func New( //nolint:funlen api, identifier, proxyCtl, + uidValidityGenerator, logIMAPClient, logIMAPServer, logSMTP, ) if err != nil { @@ -214,6 +219,7 @@ func newBridge( api *proton.Manager, identifier Identifier, proxyCtl ProxyController, + uidValidityGenerator imap.UIDValidityGenerator, logIMAPClient, logIMAPServer, logSMTP bool, ) (*Bridge, error) { @@ -252,6 +258,7 @@ func newBridge( logIMAPServer, imapEventCh, tasks, + uidValidityGenerator, ) if err != nil { return nil, fmt.Errorf("failed to create IMAP server: %w", err) @@ -298,6 +305,8 @@ func newBridge( lastVersion: lastVersion, tasks: tasks, + + uidValidityGenerator: uidValidityGenerator, } bridge.smtpServer = newSMTPServer(bridge, tlsConfig, logSMTP) diff --git a/internal/bridge/bridge_test.go b/internal/bridge/bridge_test.go index 298a7d66..c9514709 100644 --- a/internal/bridge/bridge_test.go +++ b/internal/bridge/bridge_test.go @@ -29,6 +29,7 @@ import ( "time" "github.com/Masterminds/semver/v3" + "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" "github.com/ProtonMail/go-proton-api/server/backend" @@ -594,6 +595,9 @@ func withMocks(t *testing.T, tests func(*bridge.Mocks)) { tests(mocks) } +// Needs to be global to survive bridge shutdown/startup in unit tests as they happen to fast. +var testUIDValidityGenerator = imap.DefaultEpochUIDValidityGenerator() + // withBridge creates a new bridge which points to the given API URL and uses the given keychain, and closes it when done. func withBridgeNoMocks( ctx context.Context, @@ -639,6 +643,7 @@ func withBridgeNoMocks( mocks.ProxyCtl, mocks.CrashHandler, mocks.Reporter, + testUIDValidityGenerator, // The logging stuff. os.Getenv("BRIDGE_LOG_IMAP_CLIENT") == "1", diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index e8deded8..a9f411e0 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -28,6 +28,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/ProtonMail/gluon" imapEvents "github.com/ProtonMail/gluon/events" + "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/gluon/store" "github.com/ProtonMail/proton-bridge/v3/internal/async" @@ -254,6 +255,7 @@ func newIMAPServer( logClient, logServer bool, eventCh chan<- imapEvents.Event, tasks *async.Group, + uidValidityGenerator imap.UIDValidityGenerator, ) (*gluon.Server, error) { gluonCacheDir = ApplyGluonCachePathSuffix(gluonCacheDir) gluonConfigDir = ApplyGluonConfigPathSuffix(gluonConfigDir) @@ -297,6 +299,7 @@ func newIMAPServer( gluon.WithLogger(imapClientLog, imapServerLog), getGluonVersionInfo(version), gluon.WithReporter(reporter), + gluon.WithUIDValidityGenerator(uidValidityGenerator), ) if err != nil { return nil, err diff --git a/internal/bridge/refresh_test.go b/internal/bridge/refresh_test.go index eb1f4159..ad4192f6 100644 --- a/internal/bridge/refresh_test.go +++ b/internal/bridge/refresh_test.go @@ -57,6 +57,7 @@ func TestBridge_Refresh(t *testing.T) { require.Equal(t, userID, (<-syncCh).UserID) }) + var uidValidities = make(map[string]uint32, len(names)) // If we then connect an IMAP client, it should see all the labels with UID validity of 1. withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(b *bridge.Bridge, mocks *bridge.Mocks) { mocks.Reporter.EXPECT().ReportMessageWithContext(gomock.Any(), gomock.Any()).AnyTimes() @@ -73,7 +74,7 @@ func TestBridge_Refresh(t *testing.T) { for _, name := range names { status, err := client.Select("Folders/"+name, false) require.NoError(t, err) - require.Equal(t, uint32(1000), status.UidValidity) + uidValidities[name] = status.UidValidity } }) @@ -106,7 +107,7 @@ func TestBridge_Refresh(t *testing.T) { for _, name := range names { status, err := client.Select("Folders/"+name, false) require.NoError(t, err) - require.Equal(t, uint32(1001), status.UidValidity) + require.Greater(t, status.UidValidity, uidValidities[name]) } }) }) diff --git a/internal/bridge/settings.go b/internal/bridge/settings.go index 6d276561..1e0b1a0f 100644 --- a/internal/bridge/settings.go +++ b/internal/bridge/settings.go @@ -163,6 +163,7 @@ func (bridge *Bridge) SetGluonDir(ctx context.Context, newGluonDir string) error bridge.logIMAPServer, bridge.imapEventCh, bridge.tasks, + bridge.uidValidityGenerator, ) if err != nil { panic(fmt.Errorf("failed to create new IMAP server: %w", err)) diff --git a/internal/user/imap.go b/internal/user/imap.go index 9de879e2..9251440b 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -477,16 +477,6 @@ func (conn *imapConnector) GetUpdates() <-chan imap.Update { }, conn.updateChLock) } -// GetUIDValidity returns the default UID validity for this user. -func (conn *imapConnector) GetUIDValidity() imap.UID { - return conn.vault.GetUIDValidity(conn.addrID) -} - -// SetUIDValidity sets the default UID validity for this user. -func (conn *imapConnector) SetUIDValidity(validity imap.UID) error { - return conn.vault.SetUIDValidity(conn.addrID, validity) -} - // IsMailboxVisible returns whether this mailbox should be visible over IMAP. func (conn *imapConnector) IsMailboxVisible(_ context.Context, mailboxID imap.MailboxID) bool { return atomic.LoadUint32(&conn.showAllMail) != 0 || mailboxID != proton.AllMailLabel diff --git a/internal/vault/types_user.go b/internal/vault/types_user.go index 0fe118da..af1958e3 100644 --- a/internal/vault/types_user.go +++ b/internal/vault/types_user.go @@ -17,8 +17,6 @@ package vault -import "github.com/ProtonMail/gluon/imap" - // UserData holds information about a single bridge user. // The user may or may not be logged in. type UserData struct { @@ -28,7 +26,6 @@ type UserData struct { GluonKey []byte GluonIDs map[string]string - UIDValidity map[string]imap.UID BridgePass []byte // raw token represented as byte slice (needs to be encoded) AddressMode AddressMode @@ -79,7 +76,6 @@ func newDefaultUser(userID, username, primaryEmail, authUID, authRef string, key GluonKey: newRandomToken(32), GluonIDs: make(map[string]string), - UIDValidity: make(map[string]imap.UID), BridgePass: newRandomToken(16), AddressMode: CombinedMode, diff --git a/internal/vault/user.go b/internal/vault/user.go index 1f3bf8b6..f97358dc 100644 --- a/internal/vault/user.go +++ b/internal/vault/user.go @@ -20,7 +20,6 @@ package vault import ( "fmt" - "github.com/ProtonMail/gluon/imap" "github.com/bradenaw/juniper/xslices" "golang.org/x/exp/slices" ) @@ -81,24 +80,6 @@ func (user *User) RemoveGluonID(addrID, gluonID string) error { return err } -func (user *User) GetUIDValidity(addrID string) imap.UID { - if validity, ok := user.vault.getUser(user.userID).UIDValidity[addrID]; ok { - return validity - } - - if err := user.SetUIDValidity(addrID, 1000); err != nil { - panic(err) - } - - return user.GetUIDValidity(addrID) -} - -func (user *User) SetUIDValidity(addrID string, validity imap.UID) error { - return user.vault.modUser(user.userID, func(data *UserData) { - data.UIDValidity[addrID] = validity - }) -} - // AddressMode returns the user's address mode. func (user *User) AddressMode() AddressMode { return user.vault.getUser(user.userID).AddressMode @@ -208,10 +189,6 @@ func (user *User) ClearSyncStatus() error { data.SyncStatus = SyncStatus{} data.EventID = "" - - for addrID := range data.UIDValidity { - data.UIDValidity[addrID]++ - } }) } diff --git a/tests/ctx_bridge_test.go b/tests/ctx_bridge_test.go index fb43cd60..3d7a75bd 100644 --- a/tests/ctx_bridge_test.go +++ b/tests/ctx_bridge_test.go @@ -29,6 +29,7 @@ import ( "runtime" "time" + "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/constants" @@ -160,6 +161,7 @@ func (t *testCtx) initBridge() (<-chan events.Event, error) { t.mocks.ProxyCtl, t.mocks.CrashHandler, t.reporter, + imap.DefaultEpochUIDValidityGenerator(), // Logging stuff logIMAP, From fbac5134cac1791e72b51fad0b08740d28086880 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Wed, 1 Feb 2023 14:45:03 +0100 Subject: [PATCH 013/130] fix(GODT-2224): Properly handle context cancellation during sync There was an issue where new attachment download requests would hang forever due to not checking whether the context was cancelled. At this point there were no more workers to consume to channel messages. --- internal/user/sync.go | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/internal/user/sync.go b/internal/user/sync.go index af432080..ae866745 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -344,7 +344,7 @@ func syncMessages( flushUpdateCh := make(chan flushUpdate) - errorCh := make(chan error, maxParallelDownloads+2) + errorCh := make(chan error, maxParallelDownloads*4) // Go routine in charge of downloading message metadata logging.GoAnnotated(ctx, func(ctx context.Context) { @@ -360,13 +360,15 @@ func syncMessages( metadata, err := client.GetMessageMetadataPage(ctx, 0, len(metadataChunk), proton.MessageFilter{ID: metadataChunk}) if err != nil { downloadReq.err = err - downloadCh <- downloadReq + select { + case downloadCh <- downloadReq: + case <-ctx.Done(): + return + } return } if ctx.Err() != nil { - downloadReq.err = err - downloadCh <- downloadReq return } @@ -789,7 +791,11 @@ func (a *attachmentDownloader) getAttachments(ctx context.Context, attachments [ resultChs := make([]chan attachmentResult, len(attachments)) for i, id := range attachments { resultChs[i] = make(chan attachmentResult, 1) - a.workerCh <- attachmentJob{id: id.ID, result: resultChs[i], size: id.Size} + select { + case a.workerCh <- attachmentJob{id: id.ID, result: resultChs[i], size: id.Size}: + case <-ctx.Done(): + return nil, ctx.Err() + } } result := make([][]byte, len(attachments)) From a955dcbaa911282f75cb5ea7c8a141287911b8a2 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Wed, 1 Feb 2023 15:53:27 +0100 Subject: [PATCH 014/130] fix(GODT-2323): Fix Expunge not issued for move When moving between system labels the expunge commands were not being issued. --- go.mod | 2 +- go.sum | 4 ++-- internal/user/imap.go | 2 +- tests/features/imap/message/move.feature | 23 +++++++++++++++++++++++ 4 files changed, 27 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 69d486c0..8bd5d117 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/gluon v0.14.2-0.20230201115538-18e0b89693fc github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.3.1-0.20230130144605-4b05f1e5c427 + github.com/ProtonMail/go-proton-api v0.3.1-0.20230202061850-e2fc4deffe20 github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.4.10 github.com/PuerkitoBio/goquery v1.8.0 diff --git a/go.sum b/go.sum index 49a271b5..4580bb2e 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230130144605-4b05f1e5c427 h1:M/sTrpruuxBtkeVFPoMd9WM2Kg36XlCTvYuv4q0urkg= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230130144605-4b05f1e5c427/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230202061850-e2fc4deffe20 h1:EMDPJ/VrXRvlY9xZ9X2HZgdDh6285ikKnrW6psm0cf4= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230202061850-e2fc4deffe20/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= diff --git a/internal/user/imap.go b/internal/user/imap.go index 9251440b..1356be05 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -427,7 +427,7 @@ func (conn *imapConnector) MoveMessages(ctx context.Context, messageIDs []imap.M result = result || true } - if v, ok := conn.apiLabels[string(labelToID)]; ok && v.Type == proton.LabelTypeFolder { + if v, ok := conn.apiLabels[string(labelToID)]; ok && (v.Type == proton.LabelTypeFolder || v.Type == proton.LabelTypeSystem) { result = result || true } diff --git a/tests/features/imap/message/move.feature b/tests/features/imap/message/move.feature index f98cca25..272498d8 100644 --- a/tests/features/imap/message/move.feature +++ b/tests/features/imap/message/move.feature @@ -64,6 +64,29 @@ Feature: IMAP move messages | john.doe@mail.com | [user:user]@[domain] | baz | false | And IMAP client "1" sees 0 messages in "Labels/label2" + Scenario: Move message from system label to system label + When IMAP client "1" moves the message with subject "foo" from "INBOX" to "Trash" + And it succeeds + And IMAP client "1" sees the following messages in "INBOX": + | from | to | subject | unread | + | jane.doe@mail.com | name@[domain] | bar | true | + And IMAP client "1" sees the following messages in "Trash": + | from | to | subject | unread | + | john.doe@mail.com | [user:user]@[domain] | foo | false | + + Scenario: Move message from folder to system label + When IMAP client "1" moves the message with subject "baz" from "Labels/label2" to "Folders/mbox" + And it succeeds + And IMAP client "1" sees the following messages in "Folders/mbox": + | from | to | subject | unread | + | john.doe@mail.com | [user:user]@[domain] | baz | false | + When IMAP client "1" moves the message with subject "baz" from "Folders/mbox" to "Trash" + And it succeeds + And IMAP client "1" sees 0 messages in "Folders/mbox" + And IMAP client "1" sees the following messages in "Trash": + | from | to | subject | unread | + | john.doe@mail.com | [user:user]@[domain] | baz | false | + Scenario: Move message from All Mail is not possible When IMAP client "1" moves the message with subject "baz" from "All Mail" to "Folders/folder" Then it fails From 0c8d4e8dd80d71d6e8d2143f9be9489dc6c825b5 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Thu, 2 Feb 2023 11:19:32 +0100 Subject: [PATCH 015/130] fix(GODT-2326): Only run sync after addIMAPUser() There is concurrency bug due to competing sync calls that can occur when we clear the sync status in the Vault. Running sync at the end of addIMAPUser() avoids the problem. This patch also remove the execution of a sync task for `user.ClearSyncStatus()` --- internal/bridge/imap.go | 1 + internal/user/user.go | 12 +++++------- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index a9f411e0..8c2dcbdb 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -172,6 +172,7 @@ func (bridge *Bridge) addIMAPUser(ctx context.Context, user *user.User) error { } } + user.TriggerSync() return nil } diff --git a/internal/user/user.go b/internal/user/user.go index abdbadb3..d7423827 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -234,12 +234,13 @@ func New( }) }) - // Trigger an initial sync (if necessary). - user.goSync() - return user, nil } +func (user *User) TriggerSync() { + user.goSync() +} + // ID returns the user's ID. func (user *User) ID() string { return safe.RLockRet(func() string { @@ -482,11 +483,8 @@ func (user *User) GetSyncStatus() vault.SyncStatus { return user.vault.GetSyncStatus() } -// ClearSyncStatus clears the sync status of the user. This triggers a resync. +// ClearSyncStatus clears the sync status of the user. func (user *User) ClearSyncStatus() error { - user.abortable.Abort() - defer user.goSync() - return user.vault.ClearSyncStatus() } From 8901d83c9419a05c4b08f036ebf0e2c1cfa8b651 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Thu, 2 Feb 2023 12:59:33 +0100 Subject: [PATCH 016/130] test(GODT-2326): Remove user tests These tests no longer work due to sync only being started after an account has been added. Functionality of these tests is covered in the bridge unit tests. --- internal/user/user_test.go | 101 ------------------------------------- 1 file changed, 101 deletions(-) diff --git a/internal/user/user_test.go b/internal/user/user_test.go index 8542bac2..a9ac6e04 100644 --- a/internal/user/user_test.go +++ b/internal/user/user_test.go @@ -22,16 +22,12 @@ import ( "testing" "time" - "github.com/ProtonMail/gluon/connector" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" "github.com/ProtonMail/go-proton-api/server/backend" - "github.com/ProtonMail/proton-bridge/v3/internal/bridge/mocks" "github.com/ProtonMail/proton-bridge/v3/internal/certs" - "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/ProtonMail/proton-bridge/v3/tests" - "github.com/golang/mock/gomock" "github.com/stretchr/testify/require" "go.uber.org/goleak" ) @@ -70,101 +66,15 @@ func TestUser_Info(t *testing.T) { }) } -func TestUser_Sync(t *testing.T) { - withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *proton.Manager) { - withAccount(t, s, "username", "password", []string{}, func(string, []string) { - withUser(t, ctx, s, m, "username", "password", func(user *User) { - // User starts a sync at startup. - require.IsType(t, events.SyncStarted{}, <-user.GetEventCh()) - - // User sends sync progress. - require.IsType(t, events.SyncProgress{}, <-user.GetEventCh()) - - // User finishes a sync at startup. - require.IsType(t, events.SyncFinished{}, <-user.GetEventCh()) - }) - }) - }) -} - func TestUser_AddressMode(t *testing.T) { withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *proton.Manager) { withAccount(t, s, "username", "password", []string{}, func(string, []string) { withUser(t, ctx, s, m, "username", "password", func(user *User) { - // User finishes syncing at startup. - require.IsType(t, events.SyncStarted{}, <-user.GetEventCh()) - require.IsType(t, events.SyncProgress{}, <-user.GetEventCh()) - require.IsType(t, events.SyncFinished{}, <-user.GetEventCh()) - // By default, user should be in combined mode. require.Equal(t, vault.CombinedMode, user.GetAddressMode()) // User should be able to switch to split mode. require.NoError(t, user.SetAddressMode(ctx, vault.SplitMode)) - - // Create a new set of IMAP connectors (after switching to split mode). - imapConn, err := user.NewIMAPConnectors() - require.NoError(t, err) - - // Process updates from the new set of IMAP connectors. - for _, imapConn := range imapConn { - go func(imapConn connector.Connector) { - for update := range imapConn.GetUpdates() { - update.Done(nil) - } - }(imapConn) - } - - // User finishes syncing after switching to split mode. - require.IsType(t, events.SyncStarted{}, <-user.GetEventCh()) - require.IsType(t, events.SyncProgress{}, <-user.GetEventCh()) - require.IsType(t, events.SyncFinished{}, <-user.GetEventCh()) - }) - }) - }) -} - -func TestUser_Deauth(t *testing.T) { - withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *proton.Manager) { - withAccount(t, s, "username", "password", []string{}, func(string, []string) { - withUser(t, ctx, s, m, "username", "password", func(user *User) { - require.IsType(t, events.SyncStarted{}, <-user.GetEventCh()) - require.IsType(t, events.SyncProgress{}, <-user.GetEventCh()) - require.IsType(t, events.SyncFinished{}, <-user.GetEventCh()) - - // Revoke the user's auth token. - require.NoError(t, s.RevokeUser(user.ID())) - - // The user should eventually be logged out. - require.Eventually(t, func() bool { _, ok := (<-user.GetEventCh()).(events.UserDeauth); return ok }, 500*time.Second, 100*time.Millisecond) - }) - }) - }) -} - -func TestUser_Refresh(t *testing.T) { - ctl := gomock.NewController(t) - mockReporter := mocks.NewMockReporter(ctl) - - withAPI(t, context.Background(), func(ctx context.Context, s *server.Server, m *proton.Manager) { - withAccount(t, s, "username", "password", []string{}, func(string, []string) { - withUser(t, ctx, s, m, "username", "password", func(user *User) { - require.IsType(t, events.SyncStarted{}, <-user.GetEventCh()) - require.IsType(t, events.SyncProgress{}, <-user.GetEventCh()) - require.IsType(t, events.SyncFinished{}, <-user.GetEventCh()) - - user.reporter = mockReporter - - mockReporter.EXPECT().ReportMessageWithContext( - gomock.Eq("Warning: refresh occurred"), - mocks.NewRefreshContextMatcher(proton.RefreshAll), - ).Return(nil) - - // Send refresh event - require.NoError(t, s.RefreshUser(user.ID(), proton.RefreshAll)) - - // The user should eventually be re-synced. - require.Eventually(t, func() bool { _, ok := (<-user.GetEventCh()).(events.UserRefreshed); return ok }, 5*time.Second, 100*time.Millisecond) }) }) }) @@ -220,16 +130,5 @@ func withUser(tb testing.TB, ctx context.Context, _ *server.Server, m *proton.Ma require.NoError(tb, err) defer user.Close() - imapConn, err := user.NewIMAPConnectors() - require.NoError(tb, err) - - for _, imapConn := range imapConn { - go func(imapConn connector.Connector) { - for update := range imapConn.GetUpdates() { - update.Done(nil) - } - }(imapConn) - } - fn(user) } From 219400de8daf4777d9e8ca3e26c967333f83dcb4 Mon Sep 17 00:00:00 2001 From: Romain Le Jeune Date: Thu, 2 Feb 2023 15:25:27 +0000 Subject: [PATCH 017/130] test(GODT-2298): add integration test for In-Reply-To header use cases. --- tests/ctx_helper_test.go | 2 + tests/features/smtp/send/bcc.feature | 1 + .../smtp/send/embedded_message.feature | 1 + .../smtp/send/one_account_to_another.feature | 4 + tests/features/smtp/send/same_message.feature | 2 + tests/features/smtp/send/send_reply.feature | 153 ++++++++++++++++++ tests/types_test.go | 23 ++- 7 files changed, 185 insertions(+), 1 deletion(-) create mode 100644 tests/features/smtp/send/send_reply.feature diff --git a/tests/ctx_helper_test.go b/tests/ctx_helper_test.go index 510c7309..4bf0103c 100644 --- a/tests/ctx_helper_test.go +++ b/tests/ctx_helper_test.go @@ -20,6 +20,7 @@ package tests import ( "context" "fmt" + "os" "runtime" "github.com/ProtonMail/go-proton-api" @@ -33,6 +34,7 @@ func (t *testCtx) withProton(fn func(*proton.Manager) error) error { proton.WithHostURL(t.api.GetHostURL()), proton.WithTransport(proton.InsecureTransport()), proton.WithAppVersion(t.api.GetAppVersion()), + proton.WithDebug(os.Getenv("FEATURE_API_DEBUG") != ""), ) defer m.Close() diff --git a/tests/features/smtp/send/bcc.feature b/tests/features/smtp/send/bcc.feature index ec8d41e6..a41f60da 100644 --- a/tests/features/smtp/send/bcc.feature +++ b/tests/features/smtp/send/bcc.feature @@ -45,6 +45,7 @@ Feature: SMTP with bcc """ + @long-black Scenario: Send message only to bcc When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:bcc]@[domain]": """ diff --git a/tests/features/smtp/send/embedded_message.feature b/tests/features/smtp/send/embedded_message.feature index 38154a39..3ab685c9 100644 --- a/tests/features/smtp/send/embedded_message.feature +++ b/tests/features/smtp/send/embedded_message.feature @@ -7,6 +7,7 @@ Feature: SMTP sending embedded message And the user logs in with username "[user:to]" and password "password" And user "[user:user]" connects and authenticates SMTP client "1" + @long-black Scenario: Send it When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]": """ diff --git a/tests/features/smtp/send/one_account_to_another.feature b/tests/features/smtp/send/one_account_to_another.feature index 08d1a53a..62e20587 100644 --- a/tests/features/smtp/send/one_account_to_another.feature +++ b/tests/features/smtp/send/one_account_to_another.feature @@ -6,6 +6,8 @@ Feature: SMTP sending two messages And the user logs in with username "[user:user]" and password "password" And the user logs in with username "[user:recp]" and password "password" + + @long-black Scenario: Send from one account to the other When user "[user:user]" connects and authenticates SMTP client "1" And SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:recp]@[domain]": @@ -60,6 +62,8 @@ Feature: SMTP sending two messages | from | to | subject | body | | [user:user]@[domain] | [user:recp]@[domain] | One account to the other | hello | + + @long-black Scenario: Send from one account to the other with attachments When user "[user:user]" connects and authenticates SMTP client "1" And SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:recp]@[domain]": diff --git a/tests/features/smtp/send/same_message.feature b/tests/features/smtp/send/same_message.feature index dddb810b..394b28d3 100644 --- a/tests/features/smtp/send/same_message.feature +++ b/tests/features/smtp/send/same_message.feature @@ -16,6 +16,7 @@ Feature: SMTP sending the same message twice """ And it succeeds + @long-black Scenario: The exact same message is not sent twice When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]": """ @@ -36,6 +37,7 @@ Feature: SMTP sending the same message twice | [user:user]@[domain] | [user:to]@[domain] | Hello | World | + @long-black Scenario: Slight change means different message and is sent twice When SMTP client "1" sends the following message from "[user:user]@[domain]" to "[user:to]@[domain]": """ diff --git a/tests/features/smtp/send/send_reply.feature b/tests/features/smtp/send/send_reply.feature new file mode 100644 index 00000000..47f9acf4 --- /dev/null +++ b/tests/features/smtp/send/send_reply.feature @@ -0,0 +1,153 @@ +Feature: SMTP send reply + + Background: + Given there exists an account with username "[user:user1]" and password "password" + And there exists an account with username "[user:user2]" and password "password" + And bridge starts + And the user logs in with username "[user:user1]" and password "password" + And user "[user:user1]" connects and authenticates SMTP client "1" + And user "[user:user1]" connects and authenticates IMAP client "1" + And user "[user:user1]" finishes syncing + + @long-black + Scenario: Reply with In-Reply-To but no References + # User1 send the initial message. + When SMTP client "1" sends the following message from "[user:user1]@[domain]" to "[user:user2]@[domain]": + """ + From: Bridge Test <[user:user1]@[domain]> + To: Internal Bridge <[user:user2]@[domain]> + Subject: Please Reply + Message-ID: + + hello + + """ + Then it succeeds + Then IMAP client "1" eventually sees the following messages in "Sent": + | from | to | subject | message-id | + | [user:user1]@[domain] | [user:user2]@[domain] | Please Reply | | + # login user2. + And the user logs in with username "[user:user2]" and password "password" + And user "[user:user2]" connects and authenticates IMAP client "2" + And user "[user:user2]" connects and authenticates SMTP client "2" + And user "[user:user2]" finishes syncing + # User2 receive the message. + Then IMAP client "2" eventually sees the following messages in "INBOX": + | from | subject | message-id | + | [user:user1]@[domain] | Please Reply | | + # User2 reply to it. + When SMTP client "2" sends the following message from "[user:user2]@[domain]" to "[user:user1]@[domain]": + """ + From: Internal Bridge <[user:user2]@[domain]> + To: Bridge Test <[user:user1]@[domain]> + Content-Type: text/plain + Subject: FW - Please Reply + In-Reply-To: + + Heya + + """ + Then it succeeds + Then IMAP client "2" eventually sees the following messages in "Sent": + | from | to | subject | in-reply-to | references | + | [user:user2]@[domain] | [user:user1]@[domain] | FW - Please Reply | | | + # User1 receive the reply.| + And IMAP client "1" eventually sees the following messages in "INBOX": + | from | subject | body | in-reply-to | references | + | [user:user2]@[domain] | FW - Please Reply | Heya | | | + + @long-black + Scenario: Reply with References but no In-Reply-To + # User1 send the initial message. + When SMTP client "1" sends the following message from "[user:user1]@[domain]" to "[user:user2]@[domain]": + """ + From: Bridge Test <[user:user1]@[domain]> + To: Internal Bridge <[user:user2]@[domain]> + Subject: Please Reply + Message-ID: + + hello + + """ + Then it succeeds + Then IMAP client "1" eventually sees the following messages in "Sent": + | from | to | subject | message-id | + | [user:user1]@[domain] | [user:user2]@[domain] | Please Reply | | + # login user2. + And the user logs in with username "[user:user2]" and password "password" + And user "[user:user2]" connects and authenticates IMAP client "2" + And user "[user:user2]" connects and authenticates SMTP client "2" + And user "[user:user2]" finishes syncing + # User2 receive the message. + Then IMAP client "2" eventually sees the following messages in "INBOX": + | from | subject | message-id | + | [user:user1]@[domain] | Please Reply | | + # User2 reply to it. + When SMTP client "2" sends the following message from "[user:user2]@[domain]" to "[user:user1]@[domain]": + """ + From: Internal Bridge <[user:user2]@[domain]> + To: Bridge Test <[user:user1]@[domain]> + Content-Type: text/plain + Subject: FW - Please Reply + References: + + Heya + + """ + Then it succeeds + Then IMAP client "2" eventually sees the following messages in "Sent": + | from | to | subject | in-reply-to | references | + | [user:user2]@[domain] | [user:user1]@[domain] | FW - Please Reply | | | + # User1 receive the reply.| + And IMAP client "1" eventually sees the following messages in "INBOX": + | from | subject | body | in-reply-to | references | + | [user:user2]@[domain] | FW - Please Reply | Heya | | | + + + @long-black + Scenario: Reply with both References and In-Reply-To + # User1 send the initial message. + When SMTP client "1" sends the following message from "[user:user1]@[domain]" to "[user:user2]@[domain]": + """ + From: Bridge Test <[user:user1]@[domain]> + To: Internal Bridge <[user:user2]@[domain]> + Subject: Please Reply + Message-ID: + + hello + + """ + Then it succeeds + Then IMAP client "1" eventually sees the following messages in "Sent": + | from | to | subject | message-id | + | [user:user1]@[domain] | [user:user2]@[domain] | Please Reply | | + # login user2. + And the user logs in with username "[user:user2]" and password "password" + And user "[user:user2]" connects and authenticates IMAP client "2" + And user "[user:user2]" connects and authenticates SMTP client "2" + And user "[user:user2]" finishes syncing + # User2 receive the message. + Then IMAP client "2" eventually sees the following messages in "INBOX": + | from | subject | message-id | + | [user:user1]@[domain] | Please Reply | | + # User2 reply to it. + When SMTP client "2" sends the following message from "[user:user2]@[domain]" to "[user:user1]@[domain]": + """ + From: Internal Bridge <[user:user2]@[domain]> + To: Bridge Test <[user:user1]@[domain]> + Content-Type: text/plain + Subject: FW - Please Reply + In-Reply-To: + References: + + Heya + + """ + Then it succeeds + Then IMAP client "2" eventually sees the following messages in "Sent": + | from | to | subject | in-reply-to | references | + | [user:user2]@[domain] | [user:user1]@[domain] | FW - Please Reply | | | + # User1 receive the reply.| + And IMAP client "1" eventually sees the following messages in "INBOX": + | from | subject | body | in-reply-to | references | + | [user:user2]@[domain] | FW - Please Reply | Heya | | | \ No newline at end of file diff --git a/tests/types_test.go b/tests/types_test.go index dfb8eb7d..c59b13dc 100644 --- a/tests/types_test.go +++ b/tests/types_test.go @@ -21,6 +21,7 @@ import ( "bytes" "fmt" "io" + "os" "reflect" "strconv" "strings" @@ -49,6 +50,9 @@ type Message struct { Unread bool `bdd:"unread"` Deleted bool `bdd:"deleted"` + + InReplyTo string `bdd:"in-reply-to"` + References string `bdd:"references"` } func (msg Message) Build() []byte { @@ -74,6 +78,14 @@ func (msg Message) Build() []byte { b = append(b, "Subject: "+msg.Subject+"\r\n"...) } + if msg.InReplyTo != "" { + b = append(b, "In-Reply-To: "+msg.InReplyTo+"\r\n"...) + } + + if msg.References != "" { + b = append(b, "References: "+msg.References+"\r\n"...) + } + if msg.Date != "" { date, err := time.Parse(time.RFC822, msg.Date) if err != nil { @@ -125,6 +137,9 @@ func newMessageFromIMAP(msg *imap.Message) Message { Unread: !slices.Contains(msg.Flags, imap.SeenFlag), Deleted: slices.Contains(msg.Flags, imap.DeletedFlag), Date: msg.Envelope.Date.Format(time.RFC822Z), + InReplyTo: msg.Envelope.InReplyTo, + // Go-imap only supports in-reply-to so we have to mimic other client by using it as references. + References: msg.Envelope.InReplyTo, } if len(msg.Envelope.From) > 0 { @@ -195,7 +210,13 @@ func matchMailboxes(have, want []Mailbox) error { func eventually(condition func() error) error { ch := make(chan error, 1) - timer := time.NewTimer(30 * time.Second) + var timerDuration = 30 * time.Second + // Extend to 5min for live API. + if hostURL := os.Getenv("FEATURE_TEST_HOST_URL"); hostURL != "" { + timerDuration = 600 * time.Second + } + + timer := time.NewTimer(timerDuration) defer timer.Stop() ticker := time.NewTicker(100 * time.Millisecond) From 5ec1da34b4bc8d1570b3c2661fa6f69b2895c323 Mon Sep 17 00:00:00 2001 From: Romain Le Jeune Date: Thu, 2 Feb 2023 15:36:37 +0000 Subject: [PATCH 018/130] feat(GODT-2278): improve sentry logs. --- .../bridge-gui/bridge-gui/AppController.cpp | 4 +-- .../bridge-gui/bridge-gui/SentryUtils.cpp | 27 ++++++++++++++++--- .../bridge-gui/bridge-gui/SentryUtils.h | 6 ++--- .../frontend/bridge-gui/bridge-gui/build.ps1 | 2 ++ .../frontend/bridge-gui/bridge-gui/build.sh | 3 ++- .../frontend/bridge-gui/bridge-gui/main.cpp | 12 +++++---- internal/sentry/reporter.go | 22 +++++++++++---- 7 files changed, 56 insertions(+), 20 deletions(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp index 6b69b4d1..c745b784 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp @@ -76,10 +76,10 @@ ProcessMonitor *AppController::bridgeMonitor() const { //**************************************************************************************************************************************************** void AppController::onFatalError(QString const &function, QString const &message) { QString const fullMessage = QString("%1(): %2").arg(function, message); - reportSentryException(SENTRY_LEVEL_ERROR, "AppController got notified of a fatal error", "Exception", fullMessage.toLocal8Bit()); + auto uuid = reportSentryException(SENTRY_LEVEL_ERROR, "AppController got notified of a fatal error", "Exception", fullMessage.toLocal8Bit()); QMessageBox::critical(nullptr, tr("Error"), message); restart(true); - log().fatal(fullMessage); + log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex()).arg(fullMessage)); qApp->exit(EXIT_FAILURE); } diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index 7c26a756..6dafef9f 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -16,19 +16,38 @@ // along with Proton Mail Bridge. If not, see . #include "SentryUtils.h" +#include "Version.h" +#include +#include +#include +#include +#include static constexpr const char *LoggerName = "bridge-gui"; +QByteArray getProtectedHostname() { + QByteArray hostname = QCryptographicHash::hash(QSysInfo::machineHostName().toUtf8(), QCryptographicHash::Sha256); + return hostname.toHex(); +} -void reportSentryEvent(sentry_level_t level, const char *message) { +void setSentryReportScope() { + sentry_set_tag("OS", bridgepp::goos().toUtf8()); + sentry_set_tag("Client", PROJECT_FULL_NAME); + sentry_set_tag("Version", PROJECT_VER); + sentry_set_tag("UserAgent", QString("/ (%1)").arg(bridgepp::goos()).toUtf8()); + sentry_set_tag("HostArch", QSysInfo::currentCpuArchitecture().toUtf8()); + sentry_set_tag("server_name", getProtectedHostname()); +} + +sentry_uuid_t reportSentryEvent(sentry_level_t level, const char *message) { auto event = sentry_value_new_message_event(level, LoggerName, message); - sentry_capture_event(event); + return sentry_capture_event(event); } -void reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception) { +sentry_uuid_t reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception) { auto event = sentry_value_new_message_event(level, LoggerName, message); sentry_event_add_exception(event, sentry_value_new_exception(exceptionType, exception)); - sentry_capture_event(event); + return sentry_capture_event(event); } diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h index dfc0ffa9..14ed3824 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h @@ -21,8 +21,8 @@ #include - -void reportSentryEvent(sentry_level_t level, const char *message); -void reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception); +void setSentryReportScope(); +sentry_uuid_t reportSentryEvent(sentry_level_t level, const char *message); +sentry_uuid_t reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception); #endif //BRIDGE_GUI_SENTRYUTILS_H diff --git a/internal/frontend/bridge-gui/bridge-gui/build.ps1 b/internal/frontend/bridge-gui/bridge-gui/build.ps1 index 16793360..20bd2f49 100644 --- a/internal/frontend/bridge-gui/bridge-gui/build.ps1 +++ b/internal/frontend/bridge-gui/bridge-gui/build.ps1 @@ -75,6 +75,7 @@ function check_exit() { Write-host "Running build for version $bridgeVersion - $buildConfig in $buildDir" +$REVISION_HASH = git rev-parse --short=10 HEAD git submodule update --init --recursive $vcpkgRoot . $vcpkgBootstrap -disableMetrics . $vcpkgExe install sentry-native:x64-windows grpc:x64-windows --clean-after-build @@ -82,6 +83,7 @@ git submodule update --init --recursive $vcpkgRoot . $cmakeExe -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE="$buildConfig" ` -DBRIDGE_APP_FULL_NAME="$bridgeFullName" ` -DBRIDGE_VENDOR="$bridgeVendor" ` + -DBRIDGE_REVISION=$REVISION_HASH ` -DBRIDGE_APP_VERSION="$bridgeVersion" ` -S . -B $buildDir diff --git a/internal/frontend/bridge-gui/bridge-gui/build.sh b/internal/frontend/bridge-gui/bridge-gui/build.sh index bcd84158..c47663d5 100755 --- a/internal/frontend/bridge-gui/bridge-gui/build.sh +++ b/internal/frontend/bridge-gui/bridge-gui/build.sh @@ -55,7 +55,7 @@ BRIDGE_VENDOR=${BRIDGE_VENDOR:-"Proton AG"} BUILD_CONFIG=${BRIDGE_GUI_BUILD_CONFIG:-Debug} BUILD_DIR=$(echo "./cmake-build-${BUILD_CONFIG}" | tr '[:upper:]' '[:lower:]') VCPKG_ROOT="${BRIDGE_REPO_ROOT}/extern/vcpkg" - +BRIDGE_REVISION=$(git rev-parse --short=10 HEAD) git submodule update --init --recursive ${VCPKG_ROOT} check_exit "Failed to initialize vcpkg as a submodule." @@ -93,6 +93,7 @@ cmake \ -DCMAKE_BUILD_TYPE="${BUILD_CONFIG}" \ -DBRIDGE_APP_FULL_NAME="${BRIDGE_APP_FULL_NAME}" \ -DBRIDGE_VENDOR="${BRIDGE_VENDOR}" \ + -DBRIDGE_REVISION="${BRIDGE_REVISION}" \ -DBRIDGE_APP_VERSION="${BRIDGE_APP_VERSION}" "${BRIDGE_CMAKE_MACOS_OPTS}" \ -G Ninja \ -S . \ diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 47a75a28..7e2f89c7 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include @@ -238,7 +239,8 @@ void focusOtherInstance() { } catch (Exception const &e) { app().log().error(e.qwhat()); - reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during focusOtherInstance()", "Exception", e.what()); + auto uuid = reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during focusOtherInstance()", "Exception", e.what()); + app().log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex()).arg(e.qwhat())); } } @@ -296,13 +298,13 @@ int main(int argc, char *argv[]) { const QString sentryCachePath = sentryCacheDir(); sentry_options_set_database_path(sentryOptions, sentryCachePath.toStdString().c_str()); } - sentry_options_set_release(sentryOptions, SentryProductID); + sentry_options_set_release(sentryOptions, QByteArray(PROJECT_REVISION).toHex()); // Enable this for debugging sentry. // sentry_options_set_debug(sentryOptions, 1); if (sentry_init(sentryOptions) != 0) { std::cerr << "Failed to initialize sentry" << std::endl; } - + setSentryReportScope(); auto sentryClose = qScopeGuard([] { sentry_close(); }); // The application instance is needed to display system message boxes. As we may have to do it in the exception handler, @@ -426,9 +428,9 @@ int main(int argc, char *argv[]) { return result; } catch (Exception const &e) { - reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during main", "Exception", e.what()); + auto uuid = reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during main", "Exception", e.what()); QMessageBox::critical(nullptr, "Error", e.qwhat()); - QTextStream(stderr) << e.qwhat() << "\n"; + QTextStream(stderr) << "reportID: " << QByteArray(uuid.bytes, 16).toHex() << "Captured exception :" << e.qwhat() << "\n"; return EXIT_FAILURE; } } diff --git a/internal/sentry/reporter.go b/internal/sentry/reporter.go index c8c54ef8..f9697f00 100644 --- a/internal/sentry/reporter.go +++ b/internal/sentry/reporter.go @@ -18,6 +18,7 @@ package sentry import ( + "crypto/sha256" "errors" "fmt" "log" @@ -62,12 +63,21 @@ type Reporter struct { appVersion string identifier Identifier hostArch string + serverName string } type Identifier interface { GetUserAgent() string } +func getProtectedHostname() string { + hostname, err := os.Hostname() + if err != nil { + return "Unknown" + } + return fmt.Sprintf("%x", sha256.Sum256([]byte(hostname))) +} + // NewReporter creates new sentry reporter with appName and appVersion to report. func NewReporter(appName, appVersion string, identifier Identifier) *Reporter { return &Reporter{ @@ -75,6 +85,7 @@ func NewReporter(appName, appVersion string, identifier Identifier) *Reporter { appVersion: appVersion, identifier: identifier, hostArch: getHostArch(), + serverName: getProtectedHostname(), } } @@ -126,11 +137,12 @@ func (r *Reporter) scopedReport(context map[string]interface{}, doReport func()) } tags := map[string]string{ - "OS": runtime.GOOS, - "Client": r.appName, - "Version": r.appVersion, - "UserAgent": r.identifier.GetUserAgent(), - "HostArch": r.hostArch, + "OS": runtime.GOOS, + "Client": r.appName, + "Version": r.appVersion, + "UserAgent": r.identifier.GetUserAgent(), + "HostArch": r.hostArch, + "server_name": r.serverName, } sentry.WithScope(func(scope *sentry.Scope) { From e2c1f38ed3a2b3a4156da3b097f83c8f9bcaa32c Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Thu, 2 Feb 2023 16:25:27 +0100 Subject: [PATCH 019/130] fix(GODT-2328): Ignore labels that aren't part of user label set --- internal/user/sync.go | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/internal/user/sync.go b/internal/user/sync.go index ae866745..1bba8b10 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -728,7 +728,12 @@ func wantLabel(label proton.Label) bool { func wantLabels(apiLabels map[string]proton.Label, labelIDs []string) []string { return xslices.Filter(labelIDs, func(labelID string) bool { - return wantLabel(apiLabels[labelID]) + apiLabel, ok := apiLabels[labelID] + if !ok { + return false + } + + return wantLabel(apiLabel) }) } From a36dbbf422b99595294e3cd36422dbb1d153fc3f Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Thu, 2 Feb 2023 15:57:25 +0100 Subject: [PATCH 020/130] fix(GODT-2333): Do not allow modifications to All Mail label Rather than waiting for API to reply, prevent these operations from taking place in the first place. --- internal/user/imap.go | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/internal/user/imap.go b/internal/user/imap.go index 1356be05..4b50a305 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -275,6 +275,10 @@ func (conn *imapConnector) CreateMessage( ) (imap.Message, []byte, error) { defer conn.goPollAPIEvents(false) + if mailboxID == proton.AllMailLabel { + return imap.Message{}, nil, fmt.Errorf("not allowed") + } + // Compute the hash of the message (to match it against SMTP messages). hash, err := getMessageHash(literal) if err != nil { @@ -362,6 +366,10 @@ func (conn *imapConnector) GetMessageLiteral(ctx context.Context, id imap.Messag func (conn *imapConnector) AddMessagesToMailbox(ctx context.Context, messageIDs []imap.MessageID, mailboxID imap.MailboxID) error { defer conn.goPollAPIEvents(false) + if mailboxID == proton.AllMailLabel { + return fmt.Errorf("not allowed") + } + return conn.client.LabelMessages(ctx, mapTo[imap.MessageID, string](messageIDs), string(mailboxID)) } @@ -369,6 +377,10 @@ func (conn *imapConnector) AddMessagesToMailbox(ctx context.Context, messageIDs func (conn *imapConnector) RemoveMessagesFromMailbox(ctx context.Context, messageIDs []imap.MessageID, mailboxID imap.MailboxID) error { defer conn.goPollAPIEvents(false) + if mailboxID == proton.AllMailLabel { + return fmt.Errorf("not allowed") + } + if err := conn.client.UnlabelMessages(ctx, mapTo[imap.MessageID, string](messageIDs), string(mailboxID)); err != nil { return err } @@ -413,7 +425,9 @@ func (conn *imapConnector) MoveMessages(ctx context.Context, messageIDs []imap.M defer conn.goPollAPIEvents(false) if (labelFromID == proton.InboxLabel && labelToID == proton.SentLabel) || - (labelFromID == proton.SentLabel && labelToID == proton.InboxLabel) { + (labelFromID == proton.SentLabel && labelToID == proton.InboxLabel) || + labelFromID == proton.AllMailLabel || + labelToID == proton.AllMailLabel { return false, fmt.Errorf("not allowed") } From c3d5a0b8f8d1b11e67b55cbf1d05ae21bdfd24f4 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Thu, 2 Feb 2023 18:19:40 +0100 Subject: [PATCH 021/130] feat(GODT-2295): notifications for IMAP login when signed out. --- go.mod | 2 +- go.sum | 4 +- internal/bridge/bridge_test.go | 16 + internal/bridge/imap.go | 8 + internal/events/user.go | 10 + .../bridge-gui-tester/Tabs/UsersTab.cpp | 17 + .../bridge-gui-tester/Tabs/UsersTab.h | 1 + .../bridge-gui-tester/Tabs/UsersTab.ui | 149 +-- .../bridge-gui/bridge-gui/QMLBackend.cpp | 24 +- .../bridge-gui/bridge-gui/QMLBackend.h | 2 + .../bridge-gui/bridge-gui/UserList.cpp | 13 + .../frontend/bridge-gui/bridge-gui/UserList.h | 1 + .../qml/Notifications/Notifications.qml | 29 + .../bridgepp/bridgepp/GRPC/EventFactory.cpp | 13 + .../bridgepp/bridgepp/GRPC/EventFactory.h | 1 + .../bridgepp/bridgepp/GRPC/GRPCClient.cpp | 7 + .../bridgepp/bridgepp/GRPC/GRPCClient.h | 1 + .../bridgepp/bridgepp/GRPC/bridge.pb.cc | 557 ++++++++--- .../bridgepp/bridgepp/GRPC/bridge.pb.h | 311 +++++- .../bridgepp/bridgepp/User/User.cpp | 23 +- .../bridge-gui/bridgepp/bridgepp/User/User.h | 3 + internal/frontend/cli/frontend.go | 5 +- internal/frontend/grpc/bridge.pb.go | 932 ++++++++++-------- internal/frontend/grpc/bridge.proto | 7 +- internal/frontend/grpc/event_factory.go | 4 + internal/frontend/grpc/service.go | 3 + 26 files changed, 1519 insertions(+), 624 deletions(-) diff --git a/go.mod b/go.mod index 8bd5d117..6c24d229 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230201115538-18e0b89693fc + github.com/ProtonMail/gluon v0.14.2-0.20230202124956-4fa6b6a0b9b5 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.3.1-0.20230202061850-e2fc4deffe20 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 4580bb2e..2e1e7a17 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230201115538-18e0b89693fc h1:q7sX422Eu9H97v2sLRPmPFi8yBJtNwQRzVN9DSmBHvc= -github.com/ProtonMail/gluon v0.14.2-0.20230201115538-18e0b89693fc/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230202124956-4fa6b6a0b9b5 h1:AvU75C80KwKiPcAolL0p26zNdjJvr49qlVjgbqY+VsM= +github.com/ProtonMail/gluon v0.14.2-0.20230202124956-4fa6b6a0b9b5/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/internal/bridge/bridge_test.go b/internal/bridge/bridge_test.go index c9514709..20d5a602 100644 --- a/internal/bridge/bridge_test.go +++ b/internal/bridge/bridge_test.go @@ -21,6 +21,7 @@ import ( "context" "crypto/tls" "fmt" + "net" "net/http" "os" "path/filepath" @@ -497,6 +498,21 @@ func TestBridge_InitGluonDirectory(t *testing.T) { }) } +func TestBridge_LoginFailed(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, vaultKey []byte) { + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, vaultKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + failCh, done := chToType[events.Event, events.IMAPLoginFailed](bridge.GetEvents(events.IMAPLoginFailed{})) + defer done() + + imapClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort()))) + require.NoError(t, err) + + require.Error(t, imapClient.Login("badUser", "badPass")) + require.Equal(t, "badUser", (<-failCh).Username) + }) + }) +} + func TestBridge_ChangeCacheDirectory(t *testing.T) { withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, vaultKey []byte) { userID, addrID, err := s.CreateUser("imap", password) diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index 8c2dcbdb..cd3d25ad 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -33,6 +33,7 @@ import ( "github.com/ProtonMail/gluon/store" "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/ProtonMail/proton-bridge/v3/internal/constants" + "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/logging" "github.com/ProtonMail/proton-bridge/v3/internal/user" "github.com/ProtonMail/proton-bridge/v3/internal/vault" @@ -228,6 +229,13 @@ func (bridge *Bridge) handleIMAPEvent(event imapEvents.Event) { if event.IMAPID.Name != "" && event.IMAPID.Version != "" { bridge.identifier.SetClient(event.IMAPID.Name, event.IMAPID.Version) } + + case imapEvents.LoginFailed: + logrus.WithFields(logrus.Fields{ + "sessionID": event.SessionID, + "username": event.Username, + }).Info("Received IMAP login failure notification") + bridge.publish(events.IMAPLoginFailed{Username: event.Username}) } } diff --git a/internal/events/user.go b/internal/events/user.go index cbcf5a72..a2a03188 100644 --- a/internal/events/user.go +++ b/internal/events/user.go @@ -169,3 +169,13 @@ type UsedSpaceChanged struct { func (event UsedSpaceChanged) String() string { return fmt.Sprintf("UsedSpaceChanged: UserID: %s, UsedSpace: %v", event.UserID, event.UsedSpace) } + +type IMAPLoginFailed struct { + eventBase + + Username string +} + +func (event IMAPLoginFailed) String() string { + return fmt.Sprintf("IMAPLoginFailed: Username: %s", event.Username) +} diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp index e970e90e..b0139f73 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp @@ -52,6 +52,7 @@ UsersTab::UsersTab(QWidget *parent) connect(ui_.tableUserList, &QTableView::doubleClicked, this, &UsersTab::onEditUserButton); connect(ui_.buttonRemoveUser, &QPushButton::clicked, this, &UsersTab::onRemoveUserButton); connect(ui_.buttonUserBadEvent, &QPushButton::clicked, this, &UsersTab::onSendUserBadEvent); + connect(ui_.buttonImapLoginFailed, &QPushButton::clicked, this, &UsersTab::onSendIMAPLoginFailedEvent); connect(ui_.buttonUsedBytesChanged, &QPushButton::clicked, this, &UsersTab::onSendUsedBytesChangedEvent); connect(ui_.checkUsernamePasswordError, &QCheckBox::toggled, this, &UsersTab::updateGUIState); @@ -189,6 +190,19 @@ void UsersTab::onSendUsedBytesChangedEvent() { } +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +void UsersTab::onSendIMAPLoginFailedEvent() { + GRPCService &grpc = app().grpc(); + if (grpc.isStreaming()) { + grpc.sendEvent(newIMAPLoginFailedEvent(ui_.editIMAPLoginFailedUsername->text())); + } + + this->updateGUIState(); +} + + //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** @@ -203,6 +217,9 @@ void UsersTab::updateGUIState() { ui_.groupBoxUsedSpace->setEnabled(hasSelectedUser && (UserState::Connected == state)); ui_.editUsernamePasswordError->setEnabled(ui_.checkUsernamePasswordError->isChecked()); ui_.spinUsedBytes->setValue(user ? user->usedBytes() : 0.0); + + if (user) + ui_.editIMAPLoginFailedUsername->setText(user->primaryEmailOrUsername()); } diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h index 0f43a418..868e094c 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h @@ -62,6 +62,7 @@ private slots: void onSelectionChanged(QItemSelection, QItemSelection); ///< Slot for the change of the selection. void onSendUserBadEvent(); ///< Slot for the 'Send Bad Event Error' button. void onSendUsedBytesChangedEvent(); ///< Slot for the 'Send Used Bytes Changed Event' button. + void onSendIMAPLoginFailedEvent(); ///< Slot for the 'Send IMAP Login failure Event' button. void updateGUIState(); ///< Update the GUI state. private: // member functions. diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui index 34d79ad7..36c8cec4 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui @@ -66,52 +66,6 @@ - - - - - 0 - 0 - - - - Used Bytes Changed - - - - - - - - Used Bytes - - - - - - - QAbstractSpinBox::NoButtons - - - 0 - - - 1000000000000000.000000000000000 - - - - - - - - - Send Used Bytes Changed - - - - - - @@ -126,13 +80,6 @@ - - - - Message: - - - @@ -142,18 +89,102 @@ - Bad event error. + + + + error message + + + + + + + Send + + + + + + + + 0 + 0 + + + + Used Bytes Changed + + - - - Send Bad Event Error - - + + + + + QAbstractSpinBox::NoButtons + + + 0 + + + 1000000000000000.000000000000000 + + + + + + + Send + + + + + + + + + + + + + 0 + 0 + + + + IMAP Login Failure + + + + + + + + + 200 + 0 + + + + + + + username or primary email + + + + + + + Send + + + + diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp index 9c8bfb4d..015eb9da 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp @@ -467,6 +467,7 @@ bool QMLBackend::isDoHEnabled() const { ) } + //**************************************************************************************************************************************************** /// \return The value for the 'isAutomaticUpdateOn' property. //**************************************************************************************************************************************************** @@ -876,8 +877,9 @@ void QMLBackend::onUserBadEvent(QString const &userID, QString const &errorMessa HANDLE_EXCEPTION( Q_UNUSED(errorMessage); SPUser const user = users_->getUserWithID(userID); - if (!user) + if (!user) { app().log().error(QString("Received bad event for unknown user %1").arg(user->id())); + } user->setState(UserState::SignedOut); emit userBadEvent(tr("%1 was logged out because of an internal error.").arg(user->primaryEmailOrUsername())); emit selectUser(userID); @@ -886,6 +888,24 @@ void QMLBackend::onUserBadEvent(QString const &userID, QString const &errorMessa } +//**************************************************************************************************************************************************** +/// \param[in] username The username (or primary email address) +//**************************************************************************************************************************************************** +void QMLBackend::onIMAPLoginFailed(QString const &username) { + HANDLE_EXCEPTION( + SPUser const user = users_->getUserWithUsernameOrEmail(username); + if ((!user) || (user->state() != UserState::SignedOut)) { // We want to pop-up only if a signed-out user has been detected + return; + } + if (user->isInIMAPLoginFailureCooldown()) + return; + user->startImapLoginFailureCooldown(60 * 60 * 1000); // 1 hour cooldown during which we will not display this notification to this user again. + emit selectUser(user->id()); + emit imapLoginWhileSignedOut(username); + ) +} + + //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** @@ -994,5 +1014,7 @@ void QMLBackend::connectGrpcEvents() { // user events connect(client, &GRPCClient::userDisconnected, this, &QMLBackend::userDisconnected); connect(client, &GRPCClient::userBadEvent, this, &QMLBackend::onUserBadEvent); + connect(client, &GRPCClient::imapLoginFailed, this, &QMLBackend::onIMAPLoginFailed); + users_->connectGRPCEvents(); } diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h index 05197abe..f4d28d96 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h @@ -180,6 +180,7 @@ public slots: // slot for signals received from gRPC that need transformation in void onLoginFinished(QString const &userID, bool wasSignedOut); ///< Slot for LoginFinished gRPC event. void onLoginAlreadyLoggedIn(QString const &userID); ///< Slot for the LoginAlreadyLoggedIn gRPC event. void onUserBadEvent(QString const& userID, QString const& errorMessage); ///< Slot for the userBadEvent gRPC event. + void onIMAPLoginFailed(QString const& username); ///< Slot the the imapLoginFailed event. signals: // Signals received from the Go backend, to be forwarded to QML void toggleAutostartFinished(); ///< Signal for the 'toggleAutostartFinished' gRPC stream event. @@ -233,6 +234,7 @@ signals: // Signals received from the Go backend, to be forwarded to QML void hideMainWindow(); ///< Signal for the 'hideMainWindow' gRPC stream event. void genericError(QString const &title, QString const &description); ///< Signal for the 'genericError' gRPC stream event. void selectUser(QString const); ///< Signal that request the given user account to be displayed. + void imapLoginWhileSignedOut(QString const& username); ///< Signal for the notification of IMAP login attempt on a signed out account. // This signal is emitted when an exception is intercepted is calls triggered by QML. QML engine would intercept the exception otherwise. void fatalError(QString const &function, QString const &message) const; ///< Signal emitted when an fatal error occurs. diff --git a/internal/frontend/bridge-gui/bridge-gui/UserList.cpp b/internal/frontend/bridge-gui/bridge-gui/UserList.cpp index 8d09a408..36d60e8e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/UserList.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/UserList.cpp @@ -149,6 +149,19 @@ bridgepp::SPUser UserList::getUserWithID(QString const &userID) const { } +//**************************************************************************************************************************************************** +/// \param[in] username The username or email. +/// \return The user with the given ID. +/// \return A null pointer if the user could not be found. +//**************************************************************************************************************************************************** +bridgepp::SPUser UserList::getUserWithUsernameOrEmail(QString const &username) const { + QList::const_iterator it = std::find_if(users_.begin(), users_.end(), [username](SPUser const &user) -> bool { + return user && ((username.compare(user->username(), Qt::CaseInsensitive) == 0) || user->addresses().contains(username, Qt::CaseInsensitive)); + }); + return (it == users_.end()) ? nullptr : *it; +} + + //**************************************************************************************************************************************************** /// \param[in] row The row. //**************************************************************************************************************************************************** diff --git a/internal/frontend/bridge-gui/bridge-gui/UserList.h b/internal/frontend/bridge-gui/bridge-gui/UserList.h index 84c06480..7c308895 100644 --- a/internal/frontend/bridge-gui/bridge-gui/UserList.h +++ b/internal/frontend/bridge-gui/bridge-gui/UserList.h @@ -44,6 +44,7 @@ public: // member functions. void appendUser(bridgepp::SPUser const &user); ///< Add a new user. void updateUserAtRow(int row, bridgepp::User const &user); ///< Update the user at given row. bridgepp::SPUser getUserWithID(QString const &userID) const; ///< Retrieve the user with the given ID. + bridgepp::SPUser getUserWithUsernameOrEmail(QString const& username) const; ///< Retrieve the user with the given primary email address or username // the userCount property. Q_PROPERTY(int count READ count NOTIFY countChanged) diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml b/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml index 23638a32..75c387e3 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml @@ -81,6 +81,7 @@ QtObject { root.apiCertIssue, root.noActiveKeyForRecipient, root.userBadEvent, + root.imapLoginWhileSignedOut, root.genericError ] @@ -1129,6 +1130,34 @@ QtObject { ] } + property Notification imapLoginWhileSignedOut: Notification { + title: qsTr("IMAP Login failed") + brief: title + description: "#PlaceHolderText" + icon: "./icons/ic-exclamation-circle-filled.svg" + type: Notification.NotificationType.Danger + group: Notifications.Group.Connection + + Connections { + target: Backend + function onImapLoginWhileSignedOut(username) { + root.imapLoginWhileSignedOut.description = qsTr("An email client tried to connect to the account %1, but this account is signed " + + "out. Please sign-in to continue.").arg(username) + root.imapLoginWhileSignedOut.active = true + } + } + + action: [ + Action { + text: qsTr("OK") + + onTriggered: { + root.imapLoginWhileSignedOut.active = false + } + } + ] + } + property Notification genericError: Notification { title: "#PlaceholderText#" description: "#PlaceholderText#" diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp index c833f91c..4259b4cd 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp @@ -588,6 +588,19 @@ SPStreamEvent newUsedBytesChangedEvent(QString const &userID, qint64 usedBytes) } +//**************************************************************************************************************************************************** +/// \param[in] username The username that was provided for the failed IMAP login attempt. +/// \return The event. +//**************************************************************************************************************************************************** +SPStreamEvent newIMAPLoginFailedEvent(QString const &username) { + auto event = new grpc::ImapLoginFailedEvent; + event->set_username(username.toStdString()); + auto userEvent = new grpc::UserEvent; + userEvent->set_allocated_imaploginfailedevent(event); + return wrapUserEvent(userEvent); +} + + //**************************************************************************************************************************************************** /// \param[in] errorCode The error errorCode. /// \return The event. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h index 151e17c9..76569b2e 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h @@ -79,6 +79,7 @@ SPStreamEvent newUserDisconnectedEvent(QString const &username); ///< Create a n SPStreamEvent newUserChangedEvent(QString const &userID); ///< Create a new UserChangedEvent event. SPStreamEvent newUserBadEvent(QString const &userID, QString const& errorMessage); ///< Create a new UserBadEvent event. SPStreamEvent newUsedBytesChangedEvent(QString const &userID, qint64 usedBytes); ///< Create a new UsedBytesChangedEvent event. +SPStreamEvent newIMAPLoginFailedEvent(QString const &username); ///< Create a new ImapLoginFailedEvent event. // Generic error event SPStreamEvent newGenericErrorEvent(grpc::ErrorCode errorCode); ///< Create a new GenericErrrorEvent event. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp index 8445fc69..85fb3845 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp @@ -1382,6 +1382,13 @@ void GRPCClient::processUserEvent(UserEvent const &event) { emit usedBytesChanged(userID, usedBytes); break; } + case UserEvent::kImapLoginFailedEvent: { + ImapLoginFailedEvent const& e = event.imaploginfailedevent(); + QString const username = QString::fromStdString(e.username()); + this->logTrace(QString("User event received: IMAPLoginFailed (username = %1).:").arg(username)); + emit imapLoginFailed(username); + break; + } default: this->logError("Unknown User event received."); } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h index 0ecd6a94..9d883cef 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h @@ -180,6 +180,7 @@ signals: void userChanged(QString const &userID); void userBadEvent(QString const &userID, QString const& errorMessage); void usedBytesChanged(QString const &userID, qint64 usedBytes); + void imapLoginFailed(QString const& username); public: // keychain related calls grpc::Status availableKeychains(QStringList &outKeychains); diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc index 877ee0ed..40954ecb 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc @@ -773,6 +773,19 @@ struct UsedBytesChangedEventDefaultTypeInternal { }; }; PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UsedBytesChangedEventDefaultTypeInternal _UsedBytesChangedEvent_default_instance_; +PROTOBUF_CONSTEXPR ImapLoginFailedEvent::ImapLoginFailedEvent( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.username_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct ImapLoginFailedEventDefaultTypeInternal { + PROTOBUF_CONSTEXPR ImapLoginFailedEventDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~ImapLoginFailedEventDefaultTypeInternal() {} + union { + ImapLoginFailedEvent _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ImapLoginFailedEventDefaultTypeInternal _ImapLoginFailedEvent_default_instance_; PROTOBUF_CONSTEXPR GenericErrorEvent::GenericErrorEvent( ::_pbi::ConstantInitialized): _impl_{ /*decltype(_impl_.code_)*/0 @@ -787,7 +800,7 @@ struct GenericErrorEventDefaultTypeInternal { }; PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GenericErrorEventDefaultTypeInternal _GenericErrorEvent_default_instance_; } // namespace grpc -static ::_pb::Metadata file_level_metadata_bridge_2eproto[59]; +static ::_pb::Metadata file_level_metadata_bridge_2eproto[60]; static const ::_pb::EnumDescriptor* file_level_enum_descriptors_bridge_2eproto[7]; static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_bridge_2eproto = nullptr; @@ -1214,6 +1227,7 @@ const uint32_t TableStruct_bridge_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(p ::_pbi::kInvalidFieldOffsetTag, ::_pbi::kInvalidFieldOffsetTag, ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, PROTOBUF_FIELD_OFFSET(::grpc::UserEvent, _impl_.event_), ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::grpc::ToggleSplitModeFinishedEvent, _internal_metadata_), @@ -1253,6 +1267,13 @@ const uint32_t TableStruct_bridge_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(p PROTOBUF_FIELD_OFFSET(::grpc::UsedBytesChangedEvent, _impl_.userid_), PROTOBUF_FIELD_OFFSET(::grpc::UsedBytesChangedEvent, _impl_.usedbytes_), ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::grpc::ImapLoginFailedEvent, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::grpc::ImapLoginFailedEvent, _impl_.username_), + ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::grpc::GenericErrorEvent, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -1314,12 +1335,13 @@ static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protode { 398, -1, -1, sizeof(::grpc::AddressChangedLogoutEvent)}, { 405, -1, -1, sizeof(::grpc::ApiCertIssueEvent)}, { 411, -1, -1, sizeof(::grpc::UserEvent)}, - { 423, -1, -1, sizeof(::grpc::ToggleSplitModeFinishedEvent)}, - { 430, -1, -1, sizeof(::grpc::UserDisconnectedEvent)}, - { 437, -1, -1, sizeof(::grpc::UserChangedEvent)}, - { 444, -1, -1, sizeof(::grpc::UserBadEvent)}, - { 452, -1, -1, sizeof(::grpc::UsedBytesChangedEvent)}, - { 460, -1, -1, sizeof(::grpc::GenericErrorEvent)}, + { 424, -1, -1, sizeof(::grpc::ToggleSplitModeFinishedEvent)}, + { 431, -1, -1, sizeof(::grpc::UserDisconnectedEvent)}, + { 438, -1, -1, sizeof(::grpc::UserChangedEvent)}, + { 445, -1, -1, sizeof(::grpc::UserBadEvent)}, + { 453, -1, -1, sizeof(::grpc::UsedBytesChangedEvent)}, + { 461, -1, -1, sizeof(::grpc::ImapLoginFailedEvent)}, + { 468, -1, -1, sizeof(::grpc::GenericErrorEvent)}, }; static const ::_pb::Message* const file_default_instances[] = { @@ -1381,6 +1403,7 @@ static const ::_pb::Message* const file_default_instances[] = { &::grpc::_UserChangedEvent_default_instance_._instance, &::grpc::_UserBadEvent_default_instance_._instance, &::grpc::_UsedBytesChangedEvent_default_instance_._instance, + &::grpc::_ImapLoginFailedEvent_default_instance_._instance, &::grpc::_GenericErrorEvent_default_instance_._instance, }; @@ -1502,138 +1525,141 @@ const char descriptor_table_protodef_bridge_2eproto[] PROTOBUF_SECTION_VARIABLE( "KeyForRecipientEvent\022\r\n\005email\030\001 \001(\t\"&\n\023A" "ddressChangedEvent\022\017\n\007address\030\001 \001(\t\",\n\031A" "ddressChangedLogoutEvent\022\017\n\007address\030\001 \001(" - "\t\"\023\n\021ApiCertIssueEvent\"\255\002\n\tUserEvent\022E\n\027" + "\t\"\023\n\021ApiCertIssueEvent\"\351\002\n\tUserEvent\022E\n\027" "toggleSplitModeFinished\030\001 \001(\0132\".grpc.Tog" "gleSplitModeFinishedEventH\000\0227\n\020userDisco" "nnected\030\002 \001(\0132\033.grpc.UserDisconnectedEve" "ntH\000\022-\n\013userChanged\030\003 \001(\0132\026.grpc.UserCha" "ngedEventH\000\022*\n\014userBadEvent\030\004 \001(\0132\022.grpc" ".UserBadEventH\000\022<\n\025usedBytesChangedEvent" - "\030\005 \001(\0132\033.grpc.UsedBytesChangedEventH\000B\007\n" - "\005event\".\n\034ToggleSplitModeFinishedEvent\022\016" - "\n\006userID\030\001 \001(\t\")\n\025UserDisconnectedEvent\022" - "\020\n\010username\030\001 \001(\t\"\"\n\020UserChangedEvent\022\016\n" - "\006userID\030\001 \001(\t\"4\n\014UserBadEvent\022\016\n\006userID\030" - "\001 \001(\t\022\024\n\014errorMessage\030\002 \001(\t\":\n\025UsedBytes" - "ChangedEvent\022\016\n\006userID\030\001 \001(\t\022\021\n\tusedByte" - "s\030\002 \001(\003\"2\n\021GenericErrorEvent\022\035\n\004code\030\001 \001" - "(\0162\017.grpc.ErrorCode*q\n\010LogLevel\022\r\n\tLOG_P" - "ANIC\020\000\022\r\n\tLOG_FATAL\020\001\022\r\n\tLOG_ERROR\020\002\022\014\n\010" - "LOG_WARN\020\003\022\014\n\010LOG_INFO\020\004\022\r\n\tLOG_DEBUG\020\005\022" - "\r\n\tLOG_TRACE\020\006*6\n\tUserState\022\016\n\nSIGNED_OU" - "T\020\000\022\n\n\006LOCKED\020\001\022\r\n\tCONNECTED\020\002*\242\001\n\016Login" - "ErrorType\022\033\n\027USERNAME_PASSWORD_ERROR\020\000\022\r" - "\n\tFREE_USER\020\001\022\024\n\020CONNECTION_ERROR\020\002\022\r\n\tT" - "FA_ERROR\020\003\022\r\n\tTFA_ABORT\020\004\022\027\n\023TWO_PASSWOR" - "DS_ERROR\020\005\022\027\n\023TWO_PASSWORDS_ABORT\020\006*[\n\017U" - "pdateErrorType\022\027\n\023UPDATE_MANUAL_ERROR\020\000\022" - "\026\n\022UPDATE_FORCE_ERROR\020\001\022\027\n\023UPDATE_SILENT" - "_ERROR\020\002*k\n\022DiskCacheErrorType\022 \n\034DISK_C" - "ACHE_UNAVAILABLE_ERROR\020\000\022\036\n\032CANT_MOVE_DI" - "SK_CACHE_ERROR\020\001\022\023\n\017DISK_FULL_ERROR\020\002*\335\001" - "\n\033MailServerSettingsErrorType\022\033\n\027IMAP_PO" - "RT_STARTUP_ERROR\020\000\022\033\n\027SMTP_PORT_STARTUP_" - "ERROR\020\001\022\032\n\026IMAP_PORT_CHANGE_ERROR\020\002\022\032\n\026S" - "MTP_PORT_CHANGE_ERROR\020\003\022%\n!IMAP_CONNECTI" - "ON_MODE_CHANGE_ERROR\020\004\022%\n!SMTP_CONNECTIO" - "N_MODE_CHANGE_ERROR\020\005*S\n\tErrorCode\022\021\n\rUN" - "KNOWN_ERROR\020\000\022\031\n\025TLS_CERT_EXPORT_ERROR\020\001" - "\022\030\n\024TLS_KEY_EXPORT_ERROR\020\0022\231\035\n\006Bridge\022I\n" - "\013CheckTokens\022\034.google.protobuf.StringVal" - "ue\032\034.google.protobuf.StringValue\022\?\n\013AddL" - "ogEntry\022\030.grpc.AddLogEntryRequest\032\026.goog" - "le.protobuf.Empty\022:\n\010GuiReady\022\026.google.p" - "rotobuf.Empty\032\026.grpc.GuiReadyResponse\0226\n" - "\004Quit\022\026.google.protobuf.Empty\032\026.google.p" - "rotobuf.Empty\0229\n\007Restart\022\026.google.protob" - "uf.Empty\032\026.google.protobuf.Empty\022C\n\rShow" - "OnStartup\022\026.google.protobuf.Empty\032\032.goog" - "le.protobuf.BoolValue\022F\n\020SetIsAutostartO" - "n\022\032.google.protobuf.BoolValue\032\026.google.p" - "rotobuf.Empty\022C\n\rIsAutostartOn\022\026.google." - "protobuf.Empty\032\032.google.protobuf.BoolVal" - "ue\022F\n\020SetIsBetaEnabled\022\032.google.protobuf" - ".BoolValue\032\026.google.protobuf.Empty\022C\n\rIs" - "BetaEnabled\022\026.google.protobuf.Empty\032\032.go" - "ogle.protobuf.BoolValue\022I\n\023SetIsAllMailV" - "isible\022\032.google.protobuf.BoolValue\032\026.goo" - "gle.protobuf.Empty\022F\n\020IsAllMailVisible\022\026" - ".google.protobuf.Empty\032\032.google.protobuf" - ".BoolValue\022<\n\004GoOs\022\026.google.protobuf.Emp" - "ty\032\034.google.protobuf.StringValue\022>\n\014Trig" - "gerReset\022\026.google.protobuf.Empty\032\026.googl" - "e.protobuf.Empty\022\?\n\007Version\022\026.google.pro" - "tobuf.Empty\032\034.google.protobuf.StringValu" - "e\022@\n\010LogsPath\022\026.google.protobuf.Empty\032\034." - "google.protobuf.StringValue\022C\n\013LicensePa" - "th\022\026.google.protobuf.Empty\032\034.google.prot" - "obuf.StringValue\022L\n\024ReleaseNotesPageLink" + "\030\005 \001(\0132\033.grpc.UsedBytesChangedEventH\000\022:\n" + "\024imapLoginFailedEvent\030\006 \001(\0132\032.grpc.ImapL" + "oginFailedEventH\000B\007\n\005event\".\n\034ToggleSpli" + "tModeFinishedEvent\022\016\n\006userID\030\001 \001(\t\")\n\025Us" + "erDisconnectedEvent\022\020\n\010username\030\001 \001(\t\"\"\n" + "\020UserChangedEvent\022\016\n\006userID\030\001 \001(\t\"4\n\014Use" + "rBadEvent\022\016\n\006userID\030\001 \001(\t\022\024\n\014errorMessag" + "e\030\002 \001(\t\":\n\025UsedBytesChangedEvent\022\016\n\006user" + "ID\030\001 \001(\t\022\021\n\tusedBytes\030\002 \001(\003\"(\n\024ImapLogin" + "FailedEvent\022\020\n\010username\030\001 \001(\t\"2\n\021Generic" + "ErrorEvent\022\035\n\004code\030\001 \001(\0162\017.grpc.ErrorCod" + "e*q\n\010LogLevel\022\r\n\tLOG_PANIC\020\000\022\r\n\tLOG_FATA" + "L\020\001\022\r\n\tLOG_ERROR\020\002\022\014\n\010LOG_WARN\020\003\022\014\n\010LOG_" + "INFO\020\004\022\r\n\tLOG_DEBUG\020\005\022\r\n\tLOG_TRACE\020\006*6\n\t" + "UserState\022\016\n\nSIGNED_OUT\020\000\022\n\n\006LOCKED\020\001\022\r\n" + "\tCONNECTED\020\002*\242\001\n\016LoginErrorType\022\033\n\027USERN" + "AME_PASSWORD_ERROR\020\000\022\r\n\tFREE_USER\020\001\022\024\n\020C" + "ONNECTION_ERROR\020\002\022\r\n\tTFA_ERROR\020\003\022\r\n\tTFA_" + "ABORT\020\004\022\027\n\023TWO_PASSWORDS_ERROR\020\005\022\027\n\023TWO_" + "PASSWORDS_ABORT\020\006*[\n\017UpdateErrorType\022\027\n\023" + "UPDATE_MANUAL_ERROR\020\000\022\026\n\022UPDATE_FORCE_ER" + "ROR\020\001\022\027\n\023UPDATE_SILENT_ERROR\020\002*k\n\022DiskCa" + "cheErrorType\022 \n\034DISK_CACHE_UNAVAILABLE_E" + "RROR\020\000\022\036\n\032CANT_MOVE_DISK_CACHE_ERROR\020\001\022\023" + "\n\017DISK_FULL_ERROR\020\002*\335\001\n\033MailServerSettin" + "gsErrorType\022\033\n\027IMAP_PORT_STARTUP_ERROR\020\000" + "\022\033\n\027SMTP_PORT_STARTUP_ERROR\020\001\022\032\n\026IMAP_PO" + "RT_CHANGE_ERROR\020\002\022\032\n\026SMTP_PORT_CHANGE_ER" + "ROR\020\003\022%\n!IMAP_CONNECTION_MODE_CHANGE_ERR" + "OR\020\004\022%\n!SMTP_CONNECTION_MODE_CHANGE_ERRO" + "R\020\005*S\n\tErrorCode\022\021\n\rUNKNOWN_ERROR\020\000\022\031\n\025T" + "LS_CERT_EXPORT_ERROR\020\001\022\030\n\024TLS_KEY_EXPORT" + "_ERROR\020\0022\231\035\n\006Bridge\022I\n\013CheckTokens\022\034.goo" + "gle.protobuf.StringValue\032\034.google.protob" + "uf.StringValue\022\?\n\013AddLogEntry\022\030.grpc.Add" + "LogEntryRequest\032\026.google.protobuf.Empty\022" + ":\n\010GuiReady\022\026.google.protobuf.Empty\032\026.gr" + "pc.GuiReadyResponse\0226\n\004Quit\022\026.google.pro" + "tobuf.Empty\032\026.google.protobuf.Empty\0229\n\007R" + "estart\022\026.google.protobuf.Empty\032\026.google." + "protobuf.Empty\022C\n\rShowOnStartup\022\026.google" + ".protobuf.Empty\032\032.google.protobuf.BoolVa" + "lue\022F\n\020SetIsAutostartOn\022\032.google.protobu" + "f.BoolValue\032\026.google.protobuf.Empty\022C\n\rI" + "sAutostartOn\022\026.google.protobuf.Empty\032\032.g" + "oogle.protobuf.BoolValue\022F\n\020SetIsBetaEna" + "bled\022\032.google.protobuf.BoolValue\032\026.googl" + "e.protobuf.Empty\022C\n\rIsBetaEnabled\022\026.goog" + "le.protobuf.Empty\032\032.google.protobuf.Bool" + "Value\022I\n\023SetIsAllMailVisible\022\032.google.pr" + "otobuf.BoolValue\032\026.google.protobuf.Empty" + "\022F\n\020IsAllMailVisible\022\026.google.protobuf.E" + "mpty\032\032.google.protobuf.BoolValue\022<\n\004GoOs" "\022\026.google.protobuf.Empty\032\034.google.protob" - "uf.StringValue\022N\n\026DependencyLicensesLink" + "uf.StringValue\022>\n\014TriggerReset\022\026.google." + "protobuf.Empty\032\026.google.protobuf.Empty\022\?" + "\n\007Version\022\026.google.protobuf.Empty\032\034.goog" + "le.protobuf.StringValue\022@\n\010LogsPath\022\026.go" + "ogle.protobuf.Empty\032\034.google.protobuf.St" + "ringValue\022C\n\013LicensePath\022\026.google.protob" + "uf.Empty\032\034.google.protobuf.StringValue\022L" + "\n\024ReleaseNotesPageLink\022\026.google.protobuf" + ".Empty\032\034.google.protobuf.StringValue\022N\n\026" + "DependencyLicensesLink\022\026.google.protobuf" + ".Empty\032\034.google.protobuf.StringValue\022G\n\017" + "LandingPageLink\022\026.google.protobuf.Empty\032" + "\034.google.protobuf.StringValue\022J\n\022SetColo" + "rSchemeName\022\034.google.protobuf.StringValu" + "e\032\026.google.protobuf.Empty\022G\n\017ColorScheme" + "Name\022\026.google.protobuf.Empty\032\034.google.pr" + "otobuf.StringValue\022J\n\022CurrentEmailClient" "\022\026.google.protobuf.Empty\032\034.google.protob" - "uf.StringValue\022G\n\017LandingPageLink\022\026.goog" + "uf.StringValue\022;\n\tReportBug\022\026.grpc.Repor" + "tBugRequest\032\026.google.protobuf.Empty\022M\n\025E" + "xportTLSCertificates\022\034.google.protobuf.S" + "tringValue\032\026.google.protobuf.Empty\022E\n\rFo" + "rceLauncher\022\034.google.protobuf.StringValu" + "e\032\026.google.protobuf.Empty\022I\n\021SetMainExec" + "utable\022\034.google.protobuf.StringValue\032\026.g" + "oogle.protobuf.Empty\0223\n\005Login\022\022.grpc.Log" + "inRequest\032\026.google.protobuf.Empty\0226\n\010Log" + "in2FA\022\022.grpc.LoginRequest\032\026.google.proto" + "buf.Empty\022=\n\017Login2Passwords\022\022.grpc.Logi" + "nRequest\032\026.google.protobuf.Empty\022=\n\nLogi" + "nAbort\022\027.grpc.LoginAbortRequest\032\026.google" + ".protobuf.Empty\022=\n\013CheckUpdate\022\026.google." + "protobuf.Empty\032\026.google.protobuf.Empty\022\?" + "\n\rInstallUpdate\022\026.google.protobuf.Empty\032" + "\026.google.protobuf.Empty\022L\n\026SetIsAutomati" + "cUpdateOn\022\032.google.protobuf.BoolValue\032\026." + "google.protobuf.Empty\022I\n\023IsAutomaticUpda" + "teOn\022\026.google.protobuf.Empty\032\032.google.pr" + "otobuf.BoolValue\022E\n\rDiskCachePath\022\026.goog" "le.protobuf.Empty\032\034.google.protobuf.Stri" - "ngValue\022J\n\022SetColorSchemeName\022\034.google.p" - "rotobuf.StringValue\032\026.google.protobuf.Em" - "pty\022G\n\017ColorSchemeName\022\026.google.protobuf" - ".Empty\032\034.google.protobuf.StringValue\022J\n\022" - "CurrentEmailClient\022\026.google.protobuf.Emp" - "ty\032\034.google.protobuf.StringValue\022;\n\tRepo" - "rtBug\022\026.grpc.ReportBugRequest\032\026.google.p" - "rotobuf.Empty\022M\n\025ExportTLSCertificates\022\034" - ".google.protobuf.StringValue\032\026.google.pr" - "otobuf.Empty\022E\n\rForceLauncher\022\034.google.p" - "rotobuf.StringValue\032\026.google.protobuf.Em" - "pty\022I\n\021SetMainExecutable\022\034.google.protob" - "uf.StringValue\032\026.google.protobuf.Empty\0223" - "\n\005Login\022\022.grpc.LoginRequest\032\026.google.pro" - "tobuf.Empty\0226\n\010Login2FA\022\022.grpc.LoginRequ" - "est\032\026.google.protobuf.Empty\022=\n\017Login2Pas" - "swords\022\022.grpc.LoginRequest\032\026.google.prot" - "obuf.Empty\022=\n\nLoginAbort\022\027.grpc.LoginAbo" - "rtRequest\032\026.google.protobuf.Empty\022=\n\013Che" - "ckUpdate\022\026.google.protobuf.Empty\032\026.googl" - "e.protobuf.Empty\022\?\n\rInstallUpdate\022\026.goog" - "le.protobuf.Empty\032\026.google.protobuf.Empt" - "y\022L\n\026SetIsAutomaticUpdateOn\022\032.google.pro" - "tobuf.BoolValue\032\026.google.protobuf.Empty\022" - "I\n\023IsAutomaticUpdateOn\022\026.google.protobuf" - ".Empty\032\032.google.protobuf.BoolValue\022E\n\rDi" - "skCachePath\022\026.google.protobuf.Empty\032\034.go" - "ogle.protobuf.StringValue\022H\n\020SetDiskCach" - "ePath\022\034.google.protobuf.StringValue\032\026.go" - "ogle.protobuf.Empty\022E\n\017SetIsDoHEnabled\022\032" - ".google.protobuf.BoolValue\032\026.google.prot" - "obuf.Empty\022B\n\014IsDoHEnabled\022\026.google.prot" - "obuf.Empty\032\032.google.protobuf.BoolValue\022D" - "\n\022MailServerSettings\022\026.google.protobuf.E" - "mpty\032\026.grpc.ImapSmtpSettings\022G\n\025SetMailS" - "erverSettings\022\026.grpc.ImapSmtpSettings\032\026." - "google.protobuf.Empty\022@\n\010Hostname\022\026.goog" - "le.protobuf.Empty\032\034.google.protobuf.Stri" - "ngValue\022E\n\nIsPortFree\022\033.google.protobuf." - "Int32Value\032\032.google.protobuf.BoolValue\022N" - "\n\022AvailableKeychains\022\026.google.protobuf.E" - "mpty\032 .grpc.AvailableKeychainsResponse\022J" - "\n\022SetCurrentKeychain\022\034.google.protobuf.S" - "tringValue\032\026.google.protobuf.Empty\022G\n\017Cu" - "rrentKeychain\022\026.google.protobuf.Empty\032\034." - "google.protobuf.StringValue\022=\n\013GetUserLi" - "st\022\026.google.protobuf.Empty\032\026.grpc.UserLi" - "stResponse\0223\n\007GetUser\022\034.google.protobuf." - "StringValue\032\n.grpc.User\022F\n\020SetUserSplitM" - "ode\022\032.grpc.UserSplitModeRequest\032\026.google" - ".protobuf.Empty\022B\n\nLogoutUser\022\034.google.p" - "rotobuf.StringValue\032\026.google.protobuf.Em" - "pty\022B\n\nRemoveUser\022\034.google.protobuf.Stri" - "ngValue\032\026.google.protobuf.Empty\022Q\n\026Confi" - "gureUserAppleMail\022\037.grpc.ConfigureAppleM" - "ailRequest\032\026.google.protobuf.Empty\022\?\n\016Ru" - "nEventStream\022\030.grpc.EventStreamRequest\032\021" - ".grpc.StreamEvent0\001\022A\n\017StopEventStream\022\026" - ".google.protobuf.Empty\032\026.google.protobuf" - ".EmptyB6Z4github.com/ProtonMail/proton-b" - "ridge/v3/internal/grpcb\006proto3" + "ngValue\022H\n\020SetDiskCachePath\022\034.google.pro" + "tobuf.StringValue\032\026.google.protobuf.Empt" + "y\022E\n\017SetIsDoHEnabled\022\032.google.protobuf.B" + "oolValue\032\026.google.protobuf.Empty\022B\n\014IsDo" + "HEnabled\022\026.google.protobuf.Empty\032\032.googl" + "e.protobuf.BoolValue\022D\n\022MailServerSettin" + "gs\022\026.google.protobuf.Empty\032\026.grpc.ImapSm" + "tpSettings\022G\n\025SetMailServerSettings\022\026.gr" + "pc.ImapSmtpSettings\032\026.google.protobuf.Em" + "pty\022@\n\010Hostname\022\026.google.protobuf.Empty\032" + "\034.google.protobuf.StringValue\022E\n\nIsPortF" + "ree\022\033.google.protobuf.Int32Value\032\032.googl" + "e.protobuf.BoolValue\022N\n\022AvailableKeychai" + "ns\022\026.google.protobuf.Empty\032 .grpc.Availa" + "bleKeychainsResponse\022J\n\022SetCurrentKeycha" + "in\022\034.google.protobuf.StringValue\032\026.googl" + "e.protobuf.Empty\022G\n\017CurrentKeychain\022\026.go" + "ogle.protobuf.Empty\032\034.google.protobuf.St" + "ringValue\022=\n\013GetUserList\022\026.google.protob" + "uf.Empty\032\026.grpc.UserListResponse\0223\n\007GetU" + "ser\022\034.google.protobuf.StringValue\032\n.grpc" + ".User\022F\n\020SetUserSplitMode\022\032.grpc.UserSpl" + "itModeRequest\032\026.google.protobuf.Empty\022B\n" + "\nLogoutUser\022\034.google.protobuf.StringValu" + "e\032\026.google.protobuf.Empty\022B\n\nRemoveUser\022" + "\034.google.protobuf.StringValue\032\026.google.p" + "rotobuf.Empty\022Q\n\026ConfigureUserAppleMail\022" + "\037.grpc.ConfigureAppleMailRequest\032\026.googl" + "e.protobuf.Empty\022\?\n\016RunEventStream\022\030.grp" + "c.EventStreamRequest\032\021.grpc.StreamEvent0" + "\001\022A\n\017StopEventStream\022\026.google.protobuf.E" + "mpty\032\026.google.protobuf.EmptyB6Z4github.c" + "om/ProtonMail/proton-bridge/v3/internal/" + "grpcb\006proto3" ; static const ::_pbi::DescriptorTable* const descriptor_table_bridge_2eproto_deps[2] = { &::descriptor_table_google_2fprotobuf_2fempty_2eproto, @@ -1641,9 +1667,9 @@ static const ::_pbi::DescriptorTable* const descriptor_table_bridge_2eproto_deps }; static ::_pbi::once_flag descriptor_table_bridge_2eproto_once; const ::_pbi::DescriptorTable descriptor_table_bridge_2eproto = { - false, false, 9950, descriptor_table_protodef_bridge_2eproto, + false, false, 10052, descriptor_table_protodef_bridge_2eproto, "bridge.proto", - &descriptor_table_bridge_2eproto_once, descriptor_table_bridge_2eproto_deps, 2, 59, + &descriptor_table_bridge_2eproto_once, descriptor_table_bridge_2eproto_deps, 2, 60, schemas, file_default_instances, TableStruct_bridge_2eproto::offsets, file_level_metadata_bridge_2eproto, file_level_enum_descriptors_bridge_2eproto, file_level_service_descriptors_bridge_2eproto, @@ -12407,6 +12433,7 @@ class UserEvent::_Internal { static const ::grpc::UserChangedEvent& userchanged(const UserEvent* msg); static const ::grpc::UserBadEvent& userbadevent(const UserEvent* msg); static const ::grpc::UsedBytesChangedEvent& usedbyteschangedevent(const UserEvent* msg); + static const ::grpc::ImapLoginFailedEvent& imaploginfailedevent(const UserEvent* msg); }; const ::grpc::ToggleSplitModeFinishedEvent& @@ -12429,6 +12456,10 @@ const ::grpc::UsedBytesChangedEvent& UserEvent::_Internal::usedbyteschangedevent(const UserEvent* msg) { return *msg->_impl_.event_.usedbyteschangedevent_; } +const ::grpc::ImapLoginFailedEvent& +UserEvent::_Internal::imaploginfailedevent(const UserEvent* msg) { + return *msg->_impl_.event_.imaploginfailedevent_; +} void UserEvent::set_allocated_togglesplitmodefinished(::grpc::ToggleSplitModeFinishedEvent* togglesplitmodefinished) { ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); clear_event(); @@ -12504,6 +12535,21 @@ void UserEvent::set_allocated_usedbyteschangedevent(::grpc::UsedBytesChangedEven } // @@protoc_insertion_point(field_set_allocated:grpc.UserEvent.usedBytesChangedEvent) } +void UserEvent::set_allocated_imaploginfailedevent(::grpc::ImapLoginFailedEvent* imaploginfailedevent) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + clear_event(); + if (imaploginfailedevent) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(imaploginfailedevent); + if (message_arena != submessage_arena) { + imaploginfailedevent = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, imaploginfailedevent, submessage_arena); + } + set_has_imaploginfailedevent(); + _impl_.event_.imaploginfailedevent_ = imaploginfailedevent; + } + // @@protoc_insertion_point(field_set_allocated:grpc.UserEvent.imapLoginFailedEvent) +} UserEvent::UserEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned) : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { @@ -12546,6 +12592,11 @@ UserEvent::UserEvent(const UserEvent& from) from._internal_usedbyteschangedevent()); break; } + case kImapLoginFailedEvent: { + _this->_internal_mutable_imaploginfailedevent()->::grpc::ImapLoginFailedEvent::MergeFrom( + from._internal_imaploginfailedevent()); + break; + } case EVENT_NOT_SET: { break; } @@ -12618,6 +12669,12 @@ void UserEvent::clear_event() { } break; } + case kImapLoginFailedEvent: { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.event_.imaploginfailedevent_; + } + break; + } case EVENT_NOT_SET: { break; } @@ -12682,6 +12739,14 @@ const char* UserEvent::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx } else goto handle_unusual; continue; + // .grpc.ImapLoginFailedEvent imapLoginFailedEvent = 6; + case 6: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 50)) { + ptr = ctx->ParseMessage(_internal_mutable_imaploginfailedevent(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; default: goto handle_unusual; } // switch @@ -12746,6 +12811,13 @@ uint8_t* UserEvent::_InternalSerialize( _Internal::usedbyteschangedevent(this).GetCachedSize(), target, stream); } + // .grpc.ImapLoginFailedEvent imapLoginFailedEvent = 6; + if (_internal_has_imaploginfailedevent()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(6, _Internal::imaploginfailedevent(this), + _Internal::imaploginfailedevent(this).GetCachedSize(), target, stream); + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); @@ -12798,6 +12870,13 @@ size_t UserEvent::ByteSizeLong() const { *_impl_.event_.usedbyteschangedevent_); break; } + // .grpc.ImapLoginFailedEvent imapLoginFailedEvent = 6; + case kImapLoginFailedEvent: { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.event_.imaploginfailedevent_); + break; + } case EVENT_NOT_SET: { break; } @@ -12846,6 +12925,11 @@ void UserEvent::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROT from._internal_usedbyteschangedevent()); break; } + case kImapLoginFailedEvent: { + _this->_internal_mutable_imaploginfailedevent()->::grpc::ImapLoginFailedEvent::MergeFrom( + from._internal_imaploginfailedevent()); + break; + } case EVENT_NOT_SET: { break; } @@ -13971,6 +14055,209 @@ void UsedBytesChangedEvent::InternalSwap(UsedBytesChangedEvent* other) { // =================================================================== +class ImapLoginFailedEvent::_Internal { + public: +}; + +ImapLoginFailedEvent::ImapLoginFailedEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:grpc.ImapLoginFailedEvent) +} +ImapLoginFailedEvent::ImapLoginFailedEvent(const ImapLoginFailedEvent& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + ImapLoginFailedEvent* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.username_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.username_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.username_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_username().empty()) { + _this->_impl_.username_.Set(from._internal_username(), + _this->GetArenaForAllocation()); + } + // @@protoc_insertion_point(copy_constructor:grpc.ImapLoginFailedEvent) +} + +inline void ImapLoginFailedEvent::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.username_){} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.username_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.username_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +ImapLoginFailedEvent::~ImapLoginFailedEvent() { + // @@protoc_insertion_point(destructor:grpc.ImapLoginFailedEvent) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void ImapLoginFailedEvent::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.username_.Destroy(); +} + +void ImapLoginFailedEvent::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void ImapLoginFailedEvent::Clear() { +// @@protoc_insertion_point(message_clear_start:grpc.ImapLoginFailedEvent) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.username_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* ImapLoginFailedEvent::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string username = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 10)) { + auto str = _internal_mutable_username(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "grpc.ImapLoginFailedEvent.username")); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* ImapLoginFailedEvent::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:grpc.ImapLoginFailedEvent) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string username = 1; + if (!this->_internal_username().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_username().data(), static_cast(this->_internal_username().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "grpc.ImapLoginFailedEvent.username"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_username(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:grpc.ImapLoginFailedEvent) + return target; +} + +size_t ImapLoginFailedEvent::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:grpc.ImapLoginFailedEvent) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string username = 1; + if (!this->_internal_username().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_username()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData ImapLoginFailedEvent::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + ImapLoginFailedEvent::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*ImapLoginFailedEvent::GetClassData() const { return &_class_data_; } + + +void ImapLoginFailedEvent::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:grpc.ImapLoginFailedEvent) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_username().empty()) { + _this->_internal_set_username(from._internal_username()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void ImapLoginFailedEvent::CopyFrom(const ImapLoginFailedEvent& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:grpc.ImapLoginFailedEvent) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool ImapLoginFailedEvent::IsInitialized() const { + return true; +} + +void ImapLoginFailedEvent::InternalSwap(ImapLoginFailedEvent* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.username_, lhs_arena, + &other->_impl_.username_, rhs_arena + ); +} + +::PROTOBUF_NAMESPACE_ID::Metadata ImapLoginFailedEvent::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_bridge_2eproto_getter, &descriptor_table_bridge_2eproto_once, + file_level_metadata_bridge_2eproto[58]); +} + +// =================================================================== + class GenericErrorEvent::_Internal { public: }; @@ -14147,7 +14434,7 @@ void GenericErrorEvent::InternalSwap(GenericErrorEvent* other) { ::PROTOBUF_NAMESPACE_ID::Metadata GenericErrorEvent::GetMetadata() const { return ::_pbi::AssignDescriptors( &descriptor_table_bridge_2eproto_getter, &descriptor_table_bridge_2eproto_once, - file_level_metadata_bridge_2eproto[58]); + file_level_metadata_bridge_2eproto[59]); } // @@protoc_insertion_point(namespace_scope) @@ -14385,6 +14672,10 @@ template<> PROTOBUF_NOINLINE ::grpc::UsedBytesChangedEvent* Arena::CreateMaybeMessage< ::grpc::UsedBytesChangedEvent >(Arena* arena) { return Arena::CreateMessageInternal< ::grpc::UsedBytesChangedEvent >(arena); } +template<> PROTOBUF_NOINLINE ::grpc::ImapLoginFailedEvent* +Arena::CreateMaybeMessage< ::grpc::ImapLoginFailedEvent >(Arena* arena) { + return Arena::CreateMessageInternal< ::grpc::ImapLoginFailedEvent >(arena); +} template<> PROTOBUF_NOINLINE ::grpc::GenericErrorEvent* Arena::CreateMaybeMessage< ::grpc::GenericErrorEvent >(Arena* arena) { return Arena::CreateMessageInternal< ::grpc::GenericErrorEvent >(arena); diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h index e39d8cd8..e223ea57 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h @@ -100,6 +100,9 @@ extern GuiReadyResponseDefaultTypeInternal _GuiReadyResponse_default_instance_; class HasNoKeychainEvent; struct HasNoKeychainEventDefaultTypeInternal; extern HasNoKeychainEventDefaultTypeInternal _HasNoKeychainEvent_default_instance_; +class ImapLoginFailedEvent; +struct ImapLoginFailedEventDefaultTypeInternal; +extern ImapLoginFailedEventDefaultTypeInternal _ImapLoginFailedEvent_default_instance_; class ImapSmtpSettings; struct ImapSmtpSettingsDefaultTypeInternal; extern ImapSmtpSettingsDefaultTypeInternal _ImapSmtpSettings_default_instance_; @@ -245,6 +248,7 @@ template<> ::grpc::EventStreamRequest* Arena::CreateMaybeMessage<::grpc::EventSt template<> ::grpc::GenericErrorEvent* Arena::CreateMaybeMessage<::grpc::GenericErrorEvent>(Arena*); template<> ::grpc::GuiReadyResponse* Arena::CreateMaybeMessage<::grpc::GuiReadyResponse>(Arena*); template<> ::grpc::HasNoKeychainEvent* Arena::CreateMaybeMessage<::grpc::HasNoKeychainEvent>(Arena*); +template<> ::grpc::ImapLoginFailedEvent* Arena::CreateMaybeMessage<::grpc::ImapLoginFailedEvent>(Arena*); template<> ::grpc::ImapSmtpSettings* Arena::CreateMaybeMessage<::grpc::ImapSmtpSettings>(Arena*); template<> ::grpc::InternetStatusEvent* Arena::CreateMaybeMessage<::grpc::InternetStatusEvent>(Arena*); template<> ::grpc::KeychainEvent* Arena::CreateMaybeMessage<::grpc::KeychainEvent>(Arena*); @@ -9082,6 +9086,7 @@ class UserEvent final : kUserChanged = 3, kUserBadEvent = 4, kUsedBytesChangedEvent = 5, + kImapLoginFailedEvent = 6, EVENT_NOT_SET = 0, }; @@ -9168,6 +9173,7 @@ class UserEvent final : kUserChangedFieldNumber = 3, kUserBadEventFieldNumber = 4, kUsedBytesChangedEventFieldNumber = 5, + kImapLoginFailedEventFieldNumber = 6, }; // .grpc.ToggleSplitModeFinishedEvent toggleSplitModeFinished = 1; bool has_togglesplitmodefinished() const; @@ -9259,6 +9265,24 @@ class UserEvent final : ::grpc::UsedBytesChangedEvent* usedbyteschangedevent); ::grpc::UsedBytesChangedEvent* unsafe_arena_release_usedbyteschangedevent(); + // .grpc.ImapLoginFailedEvent imapLoginFailedEvent = 6; + bool has_imaploginfailedevent() const; + private: + bool _internal_has_imaploginfailedevent() const; + public: + void clear_imaploginfailedevent(); + const ::grpc::ImapLoginFailedEvent& imaploginfailedevent() const; + PROTOBUF_NODISCARD ::grpc::ImapLoginFailedEvent* release_imaploginfailedevent(); + ::grpc::ImapLoginFailedEvent* mutable_imaploginfailedevent(); + void set_allocated_imaploginfailedevent(::grpc::ImapLoginFailedEvent* imaploginfailedevent); + private: + const ::grpc::ImapLoginFailedEvent& _internal_imaploginfailedevent() const; + ::grpc::ImapLoginFailedEvent* _internal_mutable_imaploginfailedevent(); + public: + void unsafe_arena_set_allocated_imaploginfailedevent( + ::grpc::ImapLoginFailedEvent* imaploginfailedevent); + ::grpc::ImapLoginFailedEvent* unsafe_arena_release_imaploginfailedevent(); + void clear_event(); EventCase event_case() const; // @@protoc_insertion_point(class_scope:grpc.UserEvent) @@ -9269,6 +9293,7 @@ class UserEvent final : void set_has_userchanged(); void set_has_userbadevent(); void set_has_usedbyteschangedevent(); + void set_has_imaploginfailedevent(); inline bool has_event() const; inline void clear_has_event(); @@ -9285,6 +9310,7 @@ class UserEvent final : ::grpc::UserChangedEvent* userchanged_; ::grpc::UserBadEvent* userbadevent_; ::grpc::UsedBytesChangedEvent* usedbyteschangedevent_; + ::grpc::ImapLoginFailedEvent* imaploginfailedevent_; } event_; mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; uint32_t _oneof_case_[1]; @@ -10087,6 +10113,159 @@ class UsedBytesChangedEvent final : }; // ------------------------------------------------------------------- +class ImapLoginFailedEvent final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:grpc.ImapLoginFailedEvent) */ { + public: + inline ImapLoginFailedEvent() : ImapLoginFailedEvent(nullptr) {} + ~ImapLoginFailedEvent() override; + explicit PROTOBUF_CONSTEXPR ImapLoginFailedEvent(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + ImapLoginFailedEvent(const ImapLoginFailedEvent& from); + ImapLoginFailedEvent(ImapLoginFailedEvent&& from) noexcept + : ImapLoginFailedEvent() { + *this = ::std::move(from); + } + + inline ImapLoginFailedEvent& operator=(const ImapLoginFailedEvent& from) { + CopyFrom(from); + return *this; + } + inline ImapLoginFailedEvent& operator=(ImapLoginFailedEvent&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const ImapLoginFailedEvent& default_instance() { + return *internal_default_instance(); + } + static inline const ImapLoginFailedEvent* internal_default_instance() { + return reinterpret_cast( + &_ImapLoginFailedEvent_default_instance_); + } + static constexpr int kIndexInFileMessages = + 58; + + friend void swap(ImapLoginFailedEvent& a, ImapLoginFailedEvent& b) { + a.Swap(&b); + } + inline void Swap(ImapLoginFailedEvent* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(ImapLoginFailedEvent* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + ImapLoginFailedEvent* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const ImapLoginFailedEvent& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const ImapLoginFailedEvent& from) { + ImapLoginFailedEvent::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(ImapLoginFailedEvent* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "grpc.ImapLoginFailedEvent"; + } + protected: + explicit ImapLoginFailedEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUsernameFieldNumber = 1, + }; + // string username = 1; + void clear_username(); + const std::string& username() const; + template + void set_username(ArgT0&& arg0, ArgT... args); + std::string* mutable_username(); + PROTOBUF_NODISCARD std::string* release_username(); + void set_allocated_username(std::string* username); + private: + const std::string& _internal_username() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_username(const std::string& value); + std::string* _internal_mutable_username(); + public: + + // @@protoc_insertion_point(class_scope:grpc.ImapLoginFailedEvent) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr username_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_bridge_2eproto; +}; +// ------------------------------------------------------------------- + class GenericErrorEvent final : public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:grpc.GenericErrorEvent) */ { public: @@ -10135,7 +10314,7 @@ class GenericErrorEvent final : &_GenericErrorEvent_default_instance_); } static constexpr int kIndexInFileMessages = - 58; + 59; friend void swap(GenericErrorEvent& a, GenericErrorEvent& b) { a.Swap(&b); @@ -15992,6 +16171,80 @@ inline ::grpc::UsedBytesChangedEvent* UserEvent::mutable_usedbyteschangedevent() return _msg; } +// .grpc.ImapLoginFailedEvent imapLoginFailedEvent = 6; +inline bool UserEvent::_internal_has_imaploginfailedevent() const { + return event_case() == kImapLoginFailedEvent; +} +inline bool UserEvent::has_imaploginfailedevent() const { + return _internal_has_imaploginfailedevent(); +} +inline void UserEvent::set_has_imaploginfailedevent() { + _impl_._oneof_case_[0] = kImapLoginFailedEvent; +} +inline void UserEvent::clear_imaploginfailedevent() { + if (_internal_has_imaploginfailedevent()) { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.event_.imaploginfailedevent_; + } + clear_has_event(); + } +} +inline ::grpc::ImapLoginFailedEvent* UserEvent::release_imaploginfailedevent() { + // @@protoc_insertion_point(field_release:grpc.UserEvent.imapLoginFailedEvent) + if (_internal_has_imaploginfailedevent()) { + clear_has_event(); + ::grpc::ImapLoginFailedEvent* temp = _impl_.event_.imaploginfailedevent_; + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + _impl_.event_.imaploginfailedevent_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::grpc::ImapLoginFailedEvent& UserEvent::_internal_imaploginfailedevent() const { + return _internal_has_imaploginfailedevent() + ? *_impl_.event_.imaploginfailedevent_ + : reinterpret_cast< ::grpc::ImapLoginFailedEvent&>(::grpc::_ImapLoginFailedEvent_default_instance_); +} +inline const ::grpc::ImapLoginFailedEvent& UserEvent::imaploginfailedevent() const { + // @@protoc_insertion_point(field_get:grpc.UserEvent.imapLoginFailedEvent) + return _internal_imaploginfailedevent(); +} +inline ::grpc::ImapLoginFailedEvent* UserEvent::unsafe_arena_release_imaploginfailedevent() { + // @@protoc_insertion_point(field_unsafe_arena_release:grpc.UserEvent.imapLoginFailedEvent) + if (_internal_has_imaploginfailedevent()) { + clear_has_event(); + ::grpc::ImapLoginFailedEvent* temp = _impl_.event_.imaploginfailedevent_; + _impl_.event_.imaploginfailedevent_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void UserEvent::unsafe_arena_set_allocated_imaploginfailedevent(::grpc::ImapLoginFailedEvent* imaploginfailedevent) { + clear_event(); + if (imaploginfailedevent) { + set_has_imaploginfailedevent(); + _impl_.event_.imaploginfailedevent_ = imaploginfailedevent; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:grpc.UserEvent.imapLoginFailedEvent) +} +inline ::grpc::ImapLoginFailedEvent* UserEvent::_internal_mutable_imaploginfailedevent() { + if (!_internal_has_imaploginfailedevent()) { + clear_event(); + set_has_imaploginfailedevent(); + _impl_.event_.imaploginfailedevent_ = CreateMaybeMessage< ::grpc::ImapLoginFailedEvent >(GetArenaForAllocation()); + } + return _impl_.event_.imaploginfailedevent_; +} +inline ::grpc::ImapLoginFailedEvent* UserEvent::mutable_imaploginfailedevent() { + ::grpc::ImapLoginFailedEvent* _msg = _internal_mutable_imaploginfailedevent(); + // @@protoc_insertion_point(field_mutable:grpc.UserEvent.imapLoginFailedEvent) + return _msg; +} + inline bool UserEvent::has_event() const { return event_case() != EVENT_NOT_SET; } @@ -16343,6 +16596,60 @@ inline void UsedBytesChangedEvent::set_usedbytes(int64_t value) { // ------------------------------------------------------------------- +// ImapLoginFailedEvent + +// string username = 1; +inline void ImapLoginFailedEvent::clear_username() { + _impl_.username_.ClearToEmpty(); +} +inline const std::string& ImapLoginFailedEvent::username() const { + // @@protoc_insertion_point(field_get:grpc.ImapLoginFailedEvent.username) + return _internal_username(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void ImapLoginFailedEvent::set_username(ArgT0&& arg0, ArgT... args) { + + _impl_.username_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:grpc.ImapLoginFailedEvent.username) +} +inline std::string* ImapLoginFailedEvent::mutable_username() { + std::string* _s = _internal_mutable_username(); + // @@protoc_insertion_point(field_mutable:grpc.ImapLoginFailedEvent.username) + return _s; +} +inline const std::string& ImapLoginFailedEvent::_internal_username() const { + return _impl_.username_.Get(); +} +inline void ImapLoginFailedEvent::_internal_set_username(const std::string& value) { + + _impl_.username_.Set(value, GetArenaForAllocation()); +} +inline std::string* ImapLoginFailedEvent::_internal_mutable_username() { + + return _impl_.username_.Mutable(GetArenaForAllocation()); +} +inline std::string* ImapLoginFailedEvent::release_username() { + // @@protoc_insertion_point(field_release:grpc.ImapLoginFailedEvent.username) + return _impl_.username_.Release(); +} +inline void ImapLoginFailedEvent::set_allocated_username(std::string* username) { + if (username != nullptr) { + + } else { + + } + _impl_.username_.SetAllocated(username, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.username_.IsDefault()) { + _impl_.username_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:grpc.ImapLoginFailedEvent.username) +} + +// ------------------------------------------------------------------- + // GenericErrorEvent // .grpc.ErrorCode code = 1; @@ -16484,6 +16791,8 @@ inline void GenericErrorEvent::set_code(::grpc::ErrorCode value) { // ------------------------------------------------------------------- +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.cpp index 382a5d50..dc6a1ec1 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.cpp @@ -34,7 +34,8 @@ SPUser User::newUser(QObject *parent) { /// \param[in] parent The parent object. //**************************************************************************************************************************************************** User::User(QObject *parent) - : QObject(parent) { + : QObject(parent) + , imapFailureCooldownEndTime_(QDateTime::currentDateTime()) { } @@ -311,4 +312,24 @@ QString User::stateToString(UserState state) { } +//**************************************************************************************************************************************************** +/// We display a notification and pop the application window if an IMAP client tries to connect to a signed out account, but we do not want to +/// do it repeatedly, as it's an intrusive action. This function let's you define a period of time during which the notification should not be +/// displayed. +/// +/// \param durationMSecs The duration of the period in milliseconds. +//**************************************************************************************************************************************************** +void User::startImapLoginFailureCooldown(qint64 durationMSecs) { + imapFailureCooldownEndTime_ = QDateTime::currentDateTime().addMSecs(durationMSecs); +} + + +//**************************************************************************************************************************************************** +/// \return true if we currently are in a cooldown period for the notification +//**************************************************************************************************************************************************** +bool User::isInIMAPLoginFailureCooldown() const { + return QDateTime::currentDateTime() < imapFailureCooldownEndTime_; +} + + } // namespace bridgepp diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h index 14a82249..28f4c05b 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h @@ -74,6 +74,8 @@ public: // member functions. User &operator=(User &&) = delete; ///< Disabled move assignment operator. void update(User const &user); ///< Update the user. Q_INVOKABLE QString primaryEmailOrUsername() const; ///< Return the user primary email, or, if unknown its username. + void startImapLoginFailureCooldown(qint64 durationMSecs); ///< Start the user cooldown period for the IMAP login attempt while signed-out notification. + bool isInIMAPLoginFailureCooldown() const; ///< Check if the user in a IMAP login failure notification. public slots: // slots for QML generated calls @@ -137,6 +139,7 @@ private: // member functions. User(QObject *parent); ///< Default constructor. private: // data members. + QDateTime imapFailureCooldownEndTime_; ///< The end date/time for the IMAP login failure notification cooldown period. QString id_; ///< The userID. QString username_; ///< The username QString password_; ///< The IMAP password of the user. diff --git a/internal/frontend/cli/frontend.go b/internal/frontend/cli/frontend.go index 39d34244..aac7d258 100644 --- a/internal/frontend/cli/frontend.go +++ b/internal/frontend/cli/frontend.go @@ -261,7 +261,7 @@ func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan e return fe } -func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:funlen +func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:funlen,gocyclo // GODT-1949: Better error events. for _, err := range f.bridge.GetErrors() { switch { @@ -303,6 +303,9 @@ func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:funle f.Printf("User %s received a bad event and was logged out.\n", user.Username) + case events.IMAPLoginFailed: + f.Printf("An IMAP login attempt failed for user %v\n", event.Username) + case events.UserAddressUpdated: user, err := f.bridge.GetUserInfo(event.UserID) if err != nil { diff --git a/internal/frontend/grpc/bridge.pb.go b/internal/frontend/grpc/bridge.pb.go index d25c8af5..4a291990 100644 --- a/internal/frontend/grpc/bridge.pb.go +++ b/internal/frontend/grpc/bridge.pb.go @@ -3563,6 +3563,7 @@ type UserEvent struct { // *UserEvent_UserChanged // *UserEvent_UserBadEvent // *UserEvent_UsedBytesChangedEvent + // *UserEvent_ImapLoginFailedEvent Event isUserEvent_Event `protobuf_oneof:"event"` } @@ -3640,6 +3641,13 @@ func (x *UserEvent) GetUsedBytesChangedEvent() *UsedBytesChangedEvent { return nil } +func (x *UserEvent) GetImapLoginFailedEvent() *ImapLoginFailedEvent { + if x, ok := x.GetEvent().(*UserEvent_ImapLoginFailedEvent); ok { + return x.ImapLoginFailedEvent + } + return nil +} + type isUserEvent_Event interface { isUserEvent_Event() } @@ -3664,6 +3672,10 @@ type UserEvent_UsedBytesChangedEvent struct { UsedBytesChangedEvent *UsedBytesChangedEvent `protobuf:"bytes,5,opt,name=usedBytesChangedEvent,proto3,oneof"` } +type UserEvent_ImapLoginFailedEvent struct { + ImapLoginFailedEvent *ImapLoginFailedEvent `protobuf:"bytes,6,opt,name=imapLoginFailedEvent,proto3,oneof"` +} + func (*UserEvent_ToggleSplitModeFinished) isUserEvent_Event() {} func (*UserEvent_UserDisconnected) isUserEvent_Event() {} @@ -3674,6 +3686,8 @@ func (*UserEvent_UserBadEvent) isUserEvent_Event() {} func (*UserEvent_UsedBytesChangedEvent) isUserEvent_Event() {} +func (*UserEvent_ImapLoginFailedEvent) isUserEvent_Event() {} + type ToggleSplitModeFinishedEvent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3925,6 +3939,53 @@ func (x *UsedBytesChangedEvent) GetUsedBytes() int64 { return 0 } +type ImapLoginFailedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Username string `protobuf:"bytes,1,opt,name=username,proto3" json:"username,omitempty"` +} + +func (x *ImapLoginFailedEvent) Reset() { + *x = ImapLoginFailedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_bridge_proto_msgTypes[58] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *ImapLoginFailedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*ImapLoginFailedEvent) ProtoMessage() {} + +func (x *ImapLoginFailedEvent) ProtoReflect() protoreflect.Message { + mi := &file_bridge_proto_msgTypes[58] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use ImapLoginFailedEvent.ProtoReflect.Descriptor instead. +func (*ImapLoginFailedEvent) Descriptor() ([]byte, []int) { + return file_bridge_proto_rawDescGZIP(), []int{58} +} + +func (x *ImapLoginFailedEvent) GetUsername() string { + if x != nil { + return x.Username + } + return "" +} + type GenericErrorEvent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3936,7 +3997,7 @@ type GenericErrorEvent struct { func (x *GenericErrorEvent) Reset() { *x = GenericErrorEvent{} if protoimpl.UnsafeEnabled { - mi := &file_bridge_proto_msgTypes[58] + mi := &file_bridge_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3949,7 +4010,7 @@ func (x *GenericErrorEvent) String() string { func (*GenericErrorEvent) ProtoMessage() {} func (x *GenericErrorEvent) ProtoReflect() protoreflect.Message { - mi := &file_bridge_proto_msgTypes[58] + mi := &file_bridge_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3962,7 +4023,7 @@ func (x *GenericErrorEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use GenericErrorEvent.ProtoReflect.Descriptor instead. func (*GenericErrorEvent) Descriptor() ([]byte, []int) { - return file_bridge_proto_rawDescGZIP(), []int{58} + return file_bridge_proto_rawDescGZIP(), []int{59} } func (x *GenericErrorEvent) GetCode() ErrorCode { @@ -4339,7 +4400,7 @@ var file_bridge_proto_rawDesc = []byte{ 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x13, 0x0a, 0x11, 0x41, 0x70, 0x69, 0x43, 0x65, 0x72, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x22, 0x8a, 0x03, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x5e, + 0x22, 0xdc, 0x03, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x70, 0x6c, @@ -4363,321 +4424,329 @@ var file_bridge_proto_rawDesc = []byte{ 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x15, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x36, 0x0a, - 0x1c, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, - 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, + 0x76, 0x65, 0x6e, 0x74, 0x12, 0x50, 0x0a, 0x14, 0x69, 0x6d, 0x61, 0x70, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, + 0x52, 0x14, 0x69, 0x6d, 0x61, 0x70, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, + 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, + 0x36, 0x0a, 0x1c, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, + 0x64, 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, + 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x33, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, 0x44, + 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2a, 0x0a, 0x10, + 0x55, 0x73, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x4a, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, + 0x42, 0x61, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, + 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, + 0x12, 0x22, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x22, 0x4d, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, + 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, - 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x33, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, - 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, - 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2a, 0x0a, 0x10, 0x55, 0x73, - 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, - 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, - 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x4a, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x42, 0x61, - 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x22, - 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x22, 0x4d, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x43, - 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, - 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, - 0x72, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, - 0x73, 0x22, 0x38, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x2a, 0x71, 0x0a, 0x08, 0x4c, - 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x50, - 0x41, 0x4e, 0x49, 0x43, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x46, 0x41, - 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x45, 0x52, 0x52, - 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x47, 0x5f, 0x57, 0x41, 0x52, 0x4e, - 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x47, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, - 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x05, 0x12, - 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x06, 0x2a, 0x36, - 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x53, - 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, - 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, - 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xa2, 0x01, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, - 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x53, 0x45, - 0x52, 0x4e, 0x41, 0x4d, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x5f, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x52, 0x45, 0x45, 0x5f, 0x55, - 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, - 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x54, - 0x46, 0x41, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x46, - 0x41, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x57, 0x4f, - 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x57, 0x4f, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, - 0x52, 0x44, 0x53, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x06, 0x2a, 0x5b, 0x0a, 0x0f, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, - 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x5f, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x55, 0x50, 0x44, 0x41, 0x54, - 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, - 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x49, 0x4c, 0x45, 0x4e, 0x54, - 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0x6b, 0x0a, 0x12, 0x44, 0x69, 0x73, 0x6b, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, - 0x0a, 0x1c, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x5f, 0x55, 0x4e, 0x41, - 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, - 0x12, 0x1e, 0x0a, 0x1a, 0x43, 0x41, 0x4e, 0x54, 0x5f, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x44, 0x49, - 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, - 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x46, 0x55, 0x4c, 0x4c, 0x5f, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0xdd, 0x01, 0x0a, 0x1b, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x72, 0x72, 0x6f, - 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, - 0x52, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, - 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, - 0x53, 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, - 0x1a, 0x0a, 0x16, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x43, 0x48, 0x41, - 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, - 0x4d, 0x54, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, - 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x25, 0x0a, 0x21, 0x49, 0x4d, 0x41, 0x50, 0x5f, - 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, - 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x12, 0x25, - 0x0a, 0x21, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, - 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x10, 0x05, 0x2a, 0x53, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x45, 0x52, - 0x54, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, - 0x12, 0x18, 0x0a, 0x14, 0x54, 0x4c, 0x53, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x45, 0x58, 0x50, 0x4f, - 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x32, 0x99, 0x1d, 0x0a, 0x06, 0x42, - 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x6f, - 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x3f, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, - 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x3a, 0x0a, 0x08, 0x47, 0x75, 0x69, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x75, 0x69, - 0x52, 0x65, 0x61, 0x64, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, - 0x04, 0x51, 0x75, 0x69, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, + 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, + 0x74, 0x65, 0x73, 0x22, 0x32, 0x0a, 0x14, 0x49, 0x6d, 0x61, 0x70, 0x4c, 0x6f, 0x67, 0x69, 0x6e, + 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, + 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, + 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x38, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, + 0x69, 0x63, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x04, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, + 0x65, 0x2a, 0x71, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x0d, 0x0a, + 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x50, 0x41, 0x4e, 0x49, 0x43, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, + 0x4c, 0x4f, 0x47, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, + 0x4f, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, + 0x47, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x47, 0x5f, + 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x44, 0x45, + 0x42, 0x55, 0x47, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x54, 0x52, 0x41, + 0x43, 0x45, 0x10, 0x06, 0x2a, 0x36, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, + 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x4f, 0x55, 0x54, 0x10, + 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, + 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xa2, 0x01, 0x0a, + 0x0e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x1b, 0x0a, 0x17, 0x55, 0x53, 0x45, 0x52, 0x4e, 0x41, 0x4d, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, + 0x57, 0x4f, 0x52, 0x44, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, + 0x46, 0x52, 0x45, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x43, + 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, + 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x46, 0x41, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, + 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x46, 0x41, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x04, 0x12, + 0x17, 0x0a, 0x13, 0x54, 0x57, 0x4f, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x53, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x57, 0x4f, 0x5f, + 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x53, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, + 0x06, 0x2a, 0x5b, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4d, + 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x16, 0x0a, + 0x12, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, + 0x53, 0x49, 0x4c, 0x45, 0x4e, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0x6b, + 0x0a, 0x12, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, + 0x48, 0x45, 0x5f, 0x55, 0x4e, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x43, 0x41, 0x4e, 0x54, 0x5f, 0x4d, + 0x4f, 0x56, 0x45, 0x5f, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x46, + 0x55, 0x4c, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0xdd, 0x01, 0x0a, 0x1b, + 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x49, + 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4d, 0x54, 0x50, + 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, 0x5f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, + 0x52, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, + 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x43, + 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x25, 0x0a, + 0x21, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, + 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, + 0x4f, 0x52, 0x10, 0x04, 0x12, 0x25, 0x0a, 0x21, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x43, 0x4f, 0x4e, + 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x48, 0x41, + 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x2a, 0x53, 0x0a, 0x09, 0x45, + 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x4e, 0x4b, 0x4e, + 0x4f, 0x57, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x54, + 0x4c, 0x53, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x4c, 0x53, 0x5f, 0x4b, 0x45, + 0x59, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, + 0x32, 0x99, 0x1d, 0x0a, 0x06, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x43, + 0x68, 0x65, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4c, 0x6f, 0x67, + 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, + 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x08, 0x47, 0x75, 0x69, 0x52, 0x65, + 0x61, 0x64, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x47, 0x75, 0x69, 0x52, 0x65, 0x61, 0x64, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x51, 0x75, 0x69, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x07, 0x52, + 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x53, 0x68, 0x6f, 0x77, 0x4f, 0x6e, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, + 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x6e, 0x12, + 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x73, 0x74, 0x61, + 0x72, 0x74, 0x4f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, + 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x49, + 0x73, 0x42, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, + 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x43, 0x0a, 0x0d, 0x53, 0x68, 0x6f, 0x77, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, - 0x70, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x12, 0x43, 0x0a, 0x0d, 0x49, 0x73, 0x42, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, + 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, - 0x74, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, - 0x0d, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x6e, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x49, 0x73, 0x42, 0x65, 0x74, 0x61, 0x45, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x49, 0x73, - 0x42, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x49, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x4d, 0x61, 0x69, 0x6c, 0x56, - 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x46, 0x0a, 0x10, 0x49, 0x73, - 0x41, 0x6c, 0x6c, 0x4d, 0x61, 0x69, 0x6c, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x47, 0x6f, 0x4f, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x3e, 0x0a, 0x0c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x65, 0x74, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x49, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x6c, + 0x6c, 0x4d, 0x61, 0x69, 0x6c, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, + 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x3f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x40, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x50, 0x61, - 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4c, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x65, - 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, + 0x12, 0x46, 0x0a, 0x10, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x4d, 0x61, 0x69, 0x6c, 0x56, 0x69, 0x73, + 0x69, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, + 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x47, 0x6f, 0x4f, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x16, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, - 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x4c, 0x69, 0x6e, 0x6b, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x47, 0x0a, 0x0f, 0x4c, 0x61, 0x6e, 0x64, 0x69, 0x6e, - 0x67, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, - 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, - 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, + 0x72, 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, - 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x3b, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, 0x12, 0x16, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4d, 0x0a, - 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, - 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0d, - 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x72, 0x12, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, - 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x33, - 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, - 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x46, 0x41, 0x12, - 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0f, 0x4c, - 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x12, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0a, 0x4c, 0x6f, - 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, - 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x43, 0x68, 0x65, - 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, - 0x61, 0x6c, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4c, 0x0a, 0x16, 0x53, 0x65, 0x74, - 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x13, 0x49, 0x73, 0x41, 0x75, 0x74, - 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, + 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x48, 0x0a, 0x10, 0x53, 0x65, 0x74, - 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, - 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0c, 0x49, 0x73, - 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, - 0x0a, 0x12, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, - 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6c, 0x53, - 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a, - 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x63, + 0x65, 0x6e, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4c, + 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x50, 0x61, + 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x16, + 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, + 0x65, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x47, 0x0a, 0x0f, + 0x4c, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, + 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x45, 0x0a, 0x0a, 0x49, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x72, 0x65, 0x65, 0x12, 0x1b, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, - 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x12, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, - 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x75, 0x72, - 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x67, + 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, + 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x43, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3b, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, + 0x42, 0x75, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, + 0x74, 0x42, 0x75, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x4d, 0x0a, 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x4c, 0x53, + 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x47, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, - 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x47, 0x65, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x1a, 0x0a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, - 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, - 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, - 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x6f, 0x75, - 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x52, - 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x51, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x55, 0x73, 0x65, 0x72, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, - 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x74, 0x6f, 0x70, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, + 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0d, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x75, 0x6e, 0x63, + 0x68, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x11, 0x53, 0x65, 0x74, + 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, - 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x4d, 0x61, 0x69, 0x6c, 0x2f, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x2f, 0x76, 0x33, - 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x12, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x32, 0x46, 0x41, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, + 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x3d, 0x0a, 0x0f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x50, 0x61, 0x73, 0x73, 0x77, + 0x6f, 0x72, 0x64, 0x73, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x3d, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x17, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x3d, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, + 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x4c, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, + 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, + 0x13, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, + 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x6b, + 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x48, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0f, 0x53, 0x65, 0x74, + 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, + 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x42, 0x0a, 0x0c, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, 0x0a, 0x12, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, + 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, + 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x15, 0x53, 0x65, + 0x74, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, + 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x49, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x46, + 0x72, 0x65, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x12, + 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, + 0x6e, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, + 0x53, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, + 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x75, 0x72, 0x72, + 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, + 0x12, 0x33, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x0a, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, + 0x0a, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, + 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x51, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x12, + 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, + 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, + 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x74, 0x6f, + 0x70, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x36, 0x5a, 0x34, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x50, 0x72, 0x6f, 0x74, 0x6f, + 0x6e, 0x4d, 0x61, 0x69, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2d, 0x62, 0x72, 0x69, + 0x64, 0x67, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, + 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4693,7 +4762,7 @@ func file_bridge_proto_rawDescGZIP() []byte { } var file_bridge_proto_enumTypes = make([]protoimpl.EnumInfo, 7) -var file_bridge_proto_msgTypes = make([]protoimpl.MessageInfo, 59) +var file_bridge_proto_msgTypes = make([]protoimpl.MessageInfo, 60) var file_bridge_proto_goTypes = []interface{}{ (LogLevel)(0), // 0: grpc.LogLevel (UserState)(0), // 1: grpc.UserState @@ -4760,11 +4829,12 @@ var file_bridge_proto_goTypes = []interface{}{ (*UserChangedEvent)(nil), // 62: grpc.UserChangedEvent (*UserBadEvent)(nil), // 63: grpc.UserBadEvent (*UsedBytesChangedEvent)(nil), // 64: grpc.UsedBytesChangedEvent - (*GenericErrorEvent)(nil), // 65: grpc.GenericErrorEvent - (*wrapperspb.StringValue)(nil), // 66: google.protobuf.StringValue - (*emptypb.Empty)(nil), // 67: google.protobuf.Empty - (*wrapperspb.BoolValue)(nil), // 68: google.protobuf.BoolValue - (*wrapperspb.Int32Value)(nil), // 69: google.protobuf.Int32Value + (*ImapLoginFailedEvent)(nil), // 65: grpc.ImapLoginFailedEvent + (*GenericErrorEvent)(nil), // 66: grpc.GenericErrorEvent + (*wrapperspb.StringValue)(nil), // 67: google.protobuf.StringValue + (*emptypb.Empty)(nil), // 68: google.protobuf.Empty + (*wrapperspb.BoolValue)(nil), // 69: google.protobuf.BoolValue + (*wrapperspb.Int32Value)(nil), // 70: google.protobuf.Int32Value } var file_bridge_proto_depIdxs = []int32{ 0, // 0: grpc.AddLogEntryRequest.level:type_name -> grpc.LogLevel @@ -4778,7 +4848,7 @@ var file_bridge_proto_depIdxs = []int32{ 50, // 8: grpc.StreamEvent.keychain:type_name -> grpc.KeychainEvent 54, // 9: grpc.StreamEvent.mail:type_name -> grpc.MailEvent 59, // 10: grpc.StreamEvent.user:type_name -> grpc.UserEvent - 65, // 11: grpc.StreamEvent.genericError:type_name -> grpc.GenericErrorEvent + 66, // 11: grpc.StreamEvent.genericError:type_name -> grpc.GenericErrorEvent 21, // 12: grpc.AppEvent.internetStatus:type_name -> grpc.InternetStatusEvent 22, // 13: grpc.AppEvent.toggleAutostartFinished:type_name -> grpc.ToggleAutostartFinishedEvent 23, // 14: grpc.AppEvent.resetFinished:type_name -> grpc.ResetFinishedEvent @@ -4822,120 +4892,121 @@ var file_bridge_proto_depIdxs = []int32{ 62, // 52: grpc.UserEvent.userChanged:type_name -> grpc.UserChangedEvent 63, // 53: grpc.UserEvent.userBadEvent:type_name -> grpc.UserBadEvent 64, // 54: grpc.UserEvent.usedBytesChangedEvent:type_name -> grpc.UsedBytesChangedEvent - 6, // 55: grpc.GenericErrorEvent.code:type_name -> grpc.ErrorCode - 66, // 56: grpc.Bridge.CheckTokens:input_type -> google.protobuf.StringValue - 7, // 57: grpc.Bridge.AddLogEntry:input_type -> grpc.AddLogEntryRequest - 67, // 58: grpc.Bridge.GuiReady:input_type -> google.protobuf.Empty - 67, // 59: grpc.Bridge.Quit:input_type -> google.protobuf.Empty - 67, // 60: grpc.Bridge.Restart:input_type -> google.protobuf.Empty - 67, // 61: grpc.Bridge.ShowOnStartup:input_type -> google.protobuf.Empty - 68, // 62: grpc.Bridge.SetIsAutostartOn:input_type -> google.protobuf.BoolValue - 67, // 63: grpc.Bridge.IsAutostartOn:input_type -> google.protobuf.Empty - 68, // 64: grpc.Bridge.SetIsBetaEnabled:input_type -> google.protobuf.BoolValue - 67, // 65: grpc.Bridge.IsBetaEnabled:input_type -> google.protobuf.Empty - 68, // 66: grpc.Bridge.SetIsAllMailVisible:input_type -> google.protobuf.BoolValue - 67, // 67: grpc.Bridge.IsAllMailVisible:input_type -> google.protobuf.Empty - 67, // 68: grpc.Bridge.GoOs:input_type -> google.protobuf.Empty - 67, // 69: grpc.Bridge.TriggerReset:input_type -> google.protobuf.Empty - 67, // 70: grpc.Bridge.Version:input_type -> google.protobuf.Empty - 67, // 71: grpc.Bridge.LogsPath:input_type -> google.protobuf.Empty - 67, // 72: grpc.Bridge.LicensePath:input_type -> google.protobuf.Empty - 67, // 73: grpc.Bridge.ReleaseNotesPageLink:input_type -> google.protobuf.Empty - 67, // 74: grpc.Bridge.DependencyLicensesLink:input_type -> google.protobuf.Empty - 67, // 75: grpc.Bridge.LandingPageLink:input_type -> google.protobuf.Empty - 66, // 76: grpc.Bridge.SetColorSchemeName:input_type -> google.protobuf.StringValue - 67, // 77: grpc.Bridge.ColorSchemeName:input_type -> google.protobuf.Empty - 67, // 78: grpc.Bridge.CurrentEmailClient:input_type -> google.protobuf.Empty - 9, // 79: grpc.Bridge.ReportBug:input_type -> grpc.ReportBugRequest - 66, // 80: grpc.Bridge.ExportTLSCertificates:input_type -> google.protobuf.StringValue - 66, // 81: grpc.Bridge.ForceLauncher:input_type -> google.protobuf.StringValue - 66, // 82: grpc.Bridge.SetMainExecutable:input_type -> google.protobuf.StringValue - 10, // 83: grpc.Bridge.Login:input_type -> grpc.LoginRequest - 10, // 84: grpc.Bridge.Login2FA:input_type -> grpc.LoginRequest - 10, // 85: grpc.Bridge.Login2Passwords:input_type -> grpc.LoginRequest - 11, // 86: grpc.Bridge.LoginAbort:input_type -> grpc.LoginAbortRequest - 67, // 87: grpc.Bridge.CheckUpdate:input_type -> google.protobuf.Empty - 67, // 88: grpc.Bridge.InstallUpdate:input_type -> google.protobuf.Empty - 68, // 89: grpc.Bridge.SetIsAutomaticUpdateOn:input_type -> google.protobuf.BoolValue - 67, // 90: grpc.Bridge.IsAutomaticUpdateOn:input_type -> google.protobuf.Empty - 67, // 91: grpc.Bridge.DiskCachePath:input_type -> google.protobuf.Empty - 66, // 92: grpc.Bridge.SetDiskCachePath:input_type -> google.protobuf.StringValue - 68, // 93: grpc.Bridge.SetIsDoHEnabled:input_type -> google.protobuf.BoolValue - 67, // 94: grpc.Bridge.IsDoHEnabled:input_type -> google.protobuf.Empty - 67, // 95: grpc.Bridge.MailServerSettings:input_type -> google.protobuf.Empty - 12, // 96: grpc.Bridge.SetMailServerSettings:input_type -> grpc.ImapSmtpSettings - 67, // 97: grpc.Bridge.Hostname:input_type -> google.protobuf.Empty - 69, // 98: grpc.Bridge.IsPortFree:input_type -> google.protobuf.Int32Value - 67, // 99: grpc.Bridge.AvailableKeychains:input_type -> google.protobuf.Empty - 66, // 100: grpc.Bridge.SetCurrentKeychain:input_type -> google.protobuf.StringValue - 67, // 101: grpc.Bridge.CurrentKeychain:input_type -> google.protobuf.Empty - 67, // 102: grpc.Bridge.GetUserList:input_type -> google.protobuf.Empty - 66, // 103: grpc.Bridge.GetUser:input_type -> google.protobuf.StringValue - 15, // 104: grpc.Bridge.SetUserSplitMode:input_type -> grpc.UserSplitModeRequest - 66, // 105: grpc.Bridge.LogoutUser:input_type -> google.protobuf.StringValue - 66, // 106: grpc.Bridge.RemoveUser:input_type -> google.protobuf.StringValue - 17, // 107: grpc.Bridge.ConfigureUserAppleMail:input_type -> grpc.ConfigureAppleMailRequest - 18, // 108: grpc.Bridge.RunEventStream:input_type -> grpc.EventStreamRequest - 67, // 109: grpc.Bridge.StopEventStream:input_type -> google.protobuf.Empty - 66, // 110: grpc.Bridge.CheckTokens:output_type -> google.protobuf.StringValue - 67, // 111: grpc.Bridge.AddLogEntry:output_type -> google.protobuf.Empty - 8, // 112: grpc.Bridge.GuiReady:output_type -> grpc.GuiReadyResponse - 67, // 113: grpc.Bridge.Quit:output_type -> google.protobuf.Empty - 67, // 114: grpc.Bridge.Restart:output_type -> google.protobuf.Empty - 68, // 115: grpc.Bridge.ShowOnStartup:output_type -> google.protobuf.BoolValue - 67, // 116: grpc.Bridge.SetIsAutostartOn:output_type -> google.protobuf.Empty - 68, // 117: grpc.Bridge.IsAutostartOn:output_type -> google.protobuf.BoolValue - 67, // 118: grpc.Bridge.SetIsBetaEnabled:output_type -> google.protobuf.Empty - 68, // 119: grpc.Bridge.IsBetaEnabled:output_type -> google.protobuf.BoolValue - 67, // 120: grpc.Bridge.SetIsAllMailVisible:output_type -> google.protobuf.Empty - 68, // 121: grpc.Bridge.IsAllMailVisible:output_type -> google.protobuf.BoolValue - 66, // 122: grpc.Bridge.GoOs:output_type -> google.protobuf.StringValue - 67, // 123: grpc.Bridge.TriggerReset:output_type -> google.protobuf.Empty - 66, // 124: grpc.Bridge.Version:output_type -> google.protobuf.StringValue - 66, // 125: grpc.Bridge.LogsPath:output_type -> google.protobuf.StringValue - 66, // 126: grpc.Bridge.LicensePath:output_type -> google.protobuf.StringValue - 66, // 127: grpc.Bridge.ReleaseNotesPageLink:output_type -> google.protobuf.StringValue - 66, // 128: grpc.Bridge.DependencyLicensesLink:output_type -> google.protobuf.StringValue - 66, // 129: grpc.Bridge.LandingPageLink:output_type -> google.protobuf.StringValue - 67, // 130: grpc.Bridge.SetColorSchemeName:output_type -> google.protobuf.Empty - 66, // 131: grpc.Bridge.ColorSchemeName:output_type -> google.protobuf.StringValue - 66, // 132: grpc.Bridge.CurrentEmailClient:output_type -> google.protobuf.StringValue - 67, // 133: grpc.Bridge.ReportBug:output_type -> google.protobuf.Empty - 67, // 134: grpc.Bridge.ExportTLSCertificates:output_type -> google.protobuf.Empty - 67, // 135: grpc.Bridge.ForceLauncher:output_type -> google.protobuf.Empty - 67, // 136: grpc.Bridge.SetMainExecutable:output_type -> google.protobuf.Empty - 67, // 137: grpc.Bridge.Login:output_type -> google.protobuf.Empty - 67, // 138: grpc.Bridge.Login2FA:output_type -> google.protobuf.Empty - 67, // 139: grpc.Bridge.Login2Passwords:output_type -> google.protobuf.Empty - 67, // 140: grpc.Bridge.LoginAbort:output_type -> google.protobuf.Empty - 67, // 141: grpc.Bridge.CheckUpdate:output_type -> google.protobuf.Empty - 67, // 142: grpc.Bridge.InstallUpdate:output_type -> google.protobuf.Empty - 67, // 143: grpc.Bridge.SetIsAutomaticUpdateOn:output_type -> google.protobuf.Empty - 68, // 144: grpc.Bridge.IsAutomaticUpdateOn:output_type -> google.protobuf.BoolValue - 66, // 145: grpc.Bridge.DiskCachePath:output_type -> google.protobuf.StringValue - 67, // 146: grpc.Bridge.SetDiskCachePath:output_type -> google.protobuf.Empty - 67, // 147: grpc.Bridge.SetIsDoHEnabled:output_type -> google.protobuf.Empty - 68, // 148: grpc.Bridge.IsDoHEnabled:output_type -> google.protobuf.BoolValue - 12, // 149: grpc.Bridge.MailServerSettings:output_type -> grpc.ImapSmtpSettings - 67, // 150: grpc.Bridge.SetMailServerSettings:output_type -> google.protobuf.Empty - 66, // 151: grpc.Bridge.Hostname:output_type -> google.protobuf.StringValue - 68, // 152: grpc.Bridge.IsPortFree:output_type -> google.protobuf.BoolValue - 13, // 153: grpc.Bridge.AvailableKeychains:output_type -> grpc.AvailableKeychainsResponse - 67, // 154: grpc.Bridge.SetCurrentKeychain:output_type -> google.protobuf.Empty - 66, // 155: grpc.Bridge.CurrentKeychain:output_type -> google.protobuf.StringValue - 16, // 156: grpc.Bridge.GetUserList:output_type -> grpc.UserListResponse - 14, // 157: grpc.Bridge.GetUser:output_type -> grpc.User - 67, // 158: grpc.Bridge.SetUserSplitMode:output_type -> google.protobuf.Empty - 67, // 159: grpc.Bridge.LogoutUser:output_type -> google.protobuf.Empty - 67, // 160: grpc.Bridge.RemoveUser:output_type -> google.protobuf.Empty - 67, // 161: grpc.Bridge.ConfigureUserAppleMail:output_type -> google.protobuf.Empty - 19, // 162: grpc.Bridge.RunEventStream:output_type -> grpc.StreamEvent - 67, // 163: grpc.Bridge.StopEventStream:output_type -> google.protobuf.Empty - 110, // [110:164] is the sub-list for method output_type - 56, // [56:110] is the sub-list for method input_type - 56, // [56:56] is the sub-list for extension type_name - 56, // [56:56] is the sub-list for extension extendee - 0, // [0:56] is the sub-list for field type_name + 65, // 55: grpc.UserEvent.imapLoginFailedEvent:type_name -> grpc.ImapLoginFailedEvent + 6, // 56: grpc.GenericErrorEvent.code:type_name -> grpc.ErrorCode + 67, // 57: grpc.Bridge.CheckTokens:input_type -> google.protobuf.StringValue + 7, // 58: grpc.Bridge.AddLogEntry:input_type -> grpc.AddLogEntryRequest + 68, // 59: grpc.Bridge.GuiReady:input_type -> google.protobuf.Empty + 68, // 60: grpc.Bridge.Quit:input_type -> google.protobuf.Empty + 68, // 61: grpc.Bridge.Restart:input_type -> google.protobuf.Empty + 68, // 62: grpc.Bridge.ShowOnStartup:input_type -> google.protobuf.Empty + 69, // 63: grpc.Bridge.SetIsAutostartOn:input_type -> google.protobuf.BoolValue + 68, // 64: grpc.Bridge.IsAutostartOn:input_type -> google.protobuf.Empty + 69, // 65: grpc.Bridge.SetIsBetaEnabled:input_type -> google.protobuf.BoolValue + 68, // 66: grpc.Bridge.IsBetaEnabled:input_type -> google.protobuf.Empty + 69, // 67: grpc.Bridge.SetIsAllMailVisible:input_type -> google.protobuf.BoolValue + 68, // 68: grpc.Bridge.IsAllMailVisible:input_type -> google.protobuf.Empty + 68, // 69: grpc.Bridge.GoOs:input_type -> google.protobuf.Empty + 68, // 70: grpc.Bridge.TriggerReset:input_type -> google.protobuf.Empty + 68, // 71: grpc.Bridge.Version:input_type -> google.protobuf.Empty + 68, // 72: grpc.Bridge.LogsPath:input_type -> google.protobuf.Empty + 68, // 73: grpc.Bridge.LicensePath:input_type -> google.protobuf.Empty + 68, // 74: grpc.Bridge.ReleaseNotesPageLink:input_type -> google.protobuf.Empty + 68, // 75: grpc.Bridge.DependencyLicensesLink:input_type -> google.protobuf.Empty + 68, // 76: grpc.Bridge.LandingPageLink:input_type -> google.protobuf.Empty + 67, // 77: grpc.Bridge.SetColorSchemeName:input_type -> google.protobuf.StringValue + 68, // 78: grpc.Bridge.ColorSchemeName:input_type -> google.protobuf.Empty + 68, // 79: grpc.Bridge.CurrentEmailClient:input_type -> google.protobuf.Empty + 9, // 80: grpc.Bridge.ReportBug:input_type -> grpc.ReportBugRequest + 67, // 81: grpc.Bridge.ExportTLSCertificates:input_type -> google.protobuf.StringValue + 67, // 82: grpc.Bridge.ForceLauncher:input_type -> google.protobuf.StringValue + 67, // 83: grpc.Bridge.SetMainExecutable:input_type -> google.protobuf.StringValue + 10, // 84: grpc.Bridge.Login:input_type -> grpc.LoginRequest + 10, // 85: grpc.Bridge.Login2FA:input_type -> grpc.LoginRequest + 10, // 86: grpc.Bridge.Login2Passwords:input_type -> grpc.LoginRequest + 11, // 87: grpc.Bridge.LoginAbort:input_type -> grpc.LoginAbortRequest + 68, // 88: grpc.Bridge.CheckUpdate:input_type -> google.protobuf.Empty + 68, // 89: grpc.Bridge.InstallUpdate:input_type -> google.protobuf.Empty + 69, // 90: grpc.Bridge.SetIsAutomaticUpdateOn:input_type -> google.protobuf.BoolValue + 68, // 91: grpc.Bridge.IsAutomaticUpdateOn:input_type -> google.protobuf.Empty + 68, // 92: grpc.Bridge.DiskCachePath:input_type -> google.protobuf.Empty + 67, // 93: grpc.Bridge.SetDiskCachePath:input_type -> google.protobuf.StringValue + 69, // 94: grpc.Bridge.SetIsDoHEnabled:input_type -> google.protobuf.BoolValue + 68, // 95: grpc.Bridge.IsDoHEnabled:input_type -> google.protobuf.Empty + 68, // 96: grpc.Bridge.MailServerSettings:input_type -> google.protobuf.Empty + 12, // 97: grpc.Bridge.SetMailServerSettings:input_type -> grpc.ImapSmtpSettings + 68, // 98: grpc.Bridge.Hostname:input_type -> google.protobuf.Empty + 70, // 99: grpc.Bridge.IsPortFree:input_type -> google.protobuf.Int32Value + 68, // 100: grpc.Bridge.AvailableKeychains:input_type -> google.protobuf.Empty + 67, // 101: grpc.Bridge.SetCurrentKeychain:input_type -> google.protobuf.StringValue + 68, // 102: grpc.Bridge.CurrentKeychain:input_type -> google.protobuf.Empty + 68, // 103: grpc.Bridge.GetUserList:input_type -> google.protobuf.Empty + 67, // 104: grpc.Bridge.GetUser:input_type -> google.protobuf.StringValue + 15, // 105: grpc.Bridge.SetUserSplitMode:input_type -> grpc.UserSplitModeRequest + 67, // 106: grpc.Bridge.LogoutUser:input_type -> google.protobuf.StringValue + 67, // 107: grpc.Bridge.RemoveUser:input_type -> google.protobuf.StringValue + 17, // 108: grpc.Bridge.ConfigureUserAppleMail:input_type -> grpc.ConfigureAppleMailRequest + 18, // 109: grpc.Bridge.RunEventStream:input_type -> grpc.EventStreamRequest + 68, // 110: grpc.Bridge.StopEventStream:input_type -> google.protobuf.Empty + 67, // 111: grpc.Bridge.CheckTokens:output_type -> google.protobuf.StringValue + 68, // 112: grpc.Bridge.AddLogEntry:output_type -> google.protobuf.Empty + 8, // 113: grpc.Bridge.GuiReady:output_type -> grpc.GuiReadyResponse + 68, // 114: grpc.Bridge.Quit:output_type -> google.protobuf.Empty + 68, // 115: grpc.Bridge.Restart:output_type -> google.protobuf.Empty + 69, // 116: grpc.Bridge.ShowOnStartup:output_type -> google.protobuf.BoolValue + 68, // 117: grpc.Bridge.SetIsAutostartOn:output_type -> google.protobuf.Empty + 69, // 118: grpc.Bridge.IsAutostartOn:output_type -> google.protobuf.BoolValue + 68, // 119: grpc.Bridge.SetIsBetaEnabled:output_type -> google.protobuf.Empty + 69, // 120: grpc.Bridge.IsBetaEnabled:output_type -> google.protobuf.BoolValue + 68, // 121: grpc.Bridge.SetIsAllMailVisible:output_type -> google.protobuf.Empty + 69, // 122: grpc.Bridge.IsAllMailVisible:output_type -> google.protobuf.BoolValue + 67, // 123: grpc.Bridge.GoOs:output_type -> google.protobuf.StringValue + 68, // 124: grpc.Bridge.TriggerReset:output_type -> google.protobuf.Empty + 67, // 125: grpc.Bridge.Version:output_type -> google.protobuf.StringValue + 67, // 126: grpc.Bridge.LogsPath:output_type -> google.protobuf.StringValue + 67, // 127: grpc.Bridge.LicensePath:output_type -> google.protobuf.StringValue + 67, // 128: grpc.Bridge.ReleaseNotesPageLink:output_type -> google.protobuf.StringValue + 67, // 129: grpc.Bridge.DependencyLicensesLink:output_type -> google.protobuf.StringValue + 67, // 130: grpc.Bridge.LandingPageLink:output_type -> google.protobuf.StringValue + 68, // 131: grpc.Bridge.SetColorSchemeName:output_type -> google.protobuf.Empty + 67, // 132: grpc.Bridge.ColorSchemeName:output_type -> google.protobuf.StringValue + 67, // 133: grpc.Bridge.CurrentEmailClient:output_type -> google.protobuf.StringValue + 68, // 134: grpc.Bridge.ReportBug:output_type -> google.protobuf.Empty + 68, // 135: grpc.Bridge.ExportTLSCertificates:output_type -> google.protobuf.Empty + 68, // 136: grpc.Bridge.ForceLauncher:output_type -> google.protobuf.Empty + 68, // 137: grpc.Bridge.SetMainExecutable:output_type -> google.protobuf.Empty + 68, // 138: grpc.Bridge.Login:output_type -> google.protobuf.Empty + 68, // 139: grpc.Bridge.Login2FA:output_type -> google.protobuf.Empty + 68, // 140: grpc.Bridge.Login2Passwords:output_type -> google.protobuf.Empty + 68, // 141: grpc.Bridge.LoginAbort:output_type -> google.protobuf.Empty + 68, // 142: grpc.Bridge.CheckUpdate:output_type -> google.protobuf.Empty + 68, // 143: grpc.Bridge.InstallUpdate:output_type -> google.protobuf.Empty + 68, // 144: grpc.Bridge.SetIsAutomaticUpdateOn:output_type -> google.protobuf.Empty + 69, // 145: grpc.Bridge.IsAutomaticUpdateOn:output_type -> google.protobuf.BoolValue + 67, // 146: grpc.Bridge.DiskCachePath:output_type -> google.protobuf.StringValue + 68, // 147: grpc.Bridge.SetDiskCachePath:output_type -> google.protobuf.Empty + 68, // 148: grpc.Bridge.SetIsDoHEnabled:output_type -> google.protobuf.Empty + 69, // 149: grpc.Bridge.IsDoHEnabled:output_type -> google.protobuf.BoolValue + 12, // 150: grpc.Bridge.MailServerSettings:output_type -> grpc.ImapSmtpSettings + 68, // 151: grpc.Bridge.SetMailServerSettings:output_type -> google.protobuf.Empty + 67, // 152: grpc.Bridge.Hostname:output_type -> google.protobuf.StringValue + 69, // 153: grpc.Bridge.IsPortFree:output_type -> google.protobuf.BoolValue + 13, // 154: grpc.Bridge.AvailableKeychains:output_type -> grpc.AvailableKeychainsResponse + 68, // 155: grpc.Bridge.SetCurrentKeychain:output_type -> google.protobuf.Empty + 67, // 156: grpc.Bridge.CurrentKeychain:output_type -> google.protobuf.StringValue + 16, // 157: grpc.Bridge.GetUserList:output_type -> grpc.UserListResponse + 14, // 158: grpc.Bridge.GetUser:output_type -> grpc.User + 68, // 159: grpc.Bridge.SetUserSplitMode:output_type -> google.protobuf.Empty + 68, // 160: grpc.Bridge.LogoutUser:output_type -> google.protobuf.Empty + 68, // 161: grpc.Bridge.RemoveUser:output_type -> google.protobuf.Empty + 68, // 162: grpc.Bridge.ConfigureUserAppleMail:output_type -> google.protobuf.Empty + 19, // 163: grpc.Bridge.RunEventStream:output_type -> grpc.StreamEvent + 68, // 164: grpc.Bridge.StopEventStream:output_type -> google.protobuf.Empty + 111, // [111:165] is the sub-list for method output_type + 57, // [57:111] is the sub-list for method input_type + 57, // [57:57] is the sub-list for extension type_name + 57, // [57:57] is the sub-list for extension extendee + 0, // [0:57] is the sub-list for field type_name } func init() { file_bridge_proto_init() } @@ -5641,6 +5712,18 @@ func file_bridge_proto_init() { } } file_bridge_proto_msgTypes[58].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*ImapLoginFailedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bridge_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GenericErrorEvent); i { case 0: return &v.state @@ -5717,6 +5800,7 @@ func file_bridge_proto_init() { (*UserEvent_UserChanged)(nil), (*UserEvent_UserBadEvent)(nil), (*UserEvent_UsedBytesChangedEvent)(nil), + (*UserEvent_ImapLoginFailedEvent)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -5724,7 +5808,7 @@ func file_bridge_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_bridge_proto_rawDesc, NumEnums: 7, - NumMessages: 59, + NumMessages: 60, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/frontend/grpc/bridge.proto b/internal/frontend/grpc/bridge.proto index 957ca153..5d9aeba7 100644 --- a/internal/frontend/grpc/bridge.proto +++ b/internal/frontend/grpc/bridge.proto @@ -448,7 +448,8 @@ message UserEvent { UserDisconnectedEvent userDisconnected = 2; UserChangedEvent userChanged = 3; UserBadEvent userBadEvent = 4; - UsedBytesChangedEvent usedBytesChangedEvent= 5; + UsedBytesChangedEvent usedBytesChangedEvent = 5; + ImapLoginFailedEvent imapLoginFailedEvent = 6; } } @@ -474,6 +475,10 @@ message UsedBytesChangedEvent { int64 usedBytes = 2; } +message ImapLoginFailedEvent { + string username = 1; +} + //********************************************************** // Generic errors //********************************************************** diff --git a/internal/frontend/grpc/event_factory.go b/internal/frontend/grpc/event_factory.go index 98644291..056c107e 100644 --- a/internal/frontend/grpc/event_factory.go +++ b/internal/frontend/grpc/event_factory.go @@ -181,6 +181,10 @@ func NewUsedBytesChangedEvent(userID string, usedBytes int) *StreamEvent { return userEvent(&UserEvent{Event: &UserEvent_UsedBytesChangedEvent{UsedBytesChangedEvent: &UsedBytesChangedEvent{UserID: userID, UsedBytes: int64(usedBytes)}}}) } +func newIMAPLoginFailedEvent(username string) *StreamEvent { + return userEvent(&UserEvent{Event: &UserEvent_ImapLoginFailedEvent{ImapLoginFailedEvent: &ImapLoginFailedEvent{Username: username}}}) +} + func NewGenericErrorEvent(errorCode ErrorCode) *StreamEvent { return genericErrorEvent(&GenericErrorEvent{Code: errorCode}) } diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index f65ee84e..8ec8834a 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -309,6 +309,9 @@ func (s *Service) watchEvents() { case events.UsedSpaceChanged: _ = s.SendEvent(NewUsedBytesChangedEvent(event.UserID, event.UsedSpace)) + case events.IMAPLoginFailed: + _ = s.SendEvent(newIMAPLoginFailedEvent(event.Username)) + case events.UserDeauth: // This is the event the GUI cares about. _ = s.SendEvent(NewUserChangedEvent(event.UserID)) From 62285a141e39ad19c7206f46de5ca909140a3caa Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Wed, 1 Feb 2023 12:58:44 +0100 Subject: [PATCH 022/130] feat(GODT-2144): Delay IMAP/SMTP server start until all users are loaded --- internal/bridge/bridge.go | 36 +++++++++++--------- internal/bridge/bridge_test.go | 4 +++ internal/bridge/imap.go | 61 ++++++++++++++++++++++------------ internal/bridge/smtp.go | 51 +++++++++++++++++++--------- internal/events/serve.go | 59 ++++++++++++++++++++++++++++++++ 5 files changed, 159 insertions(+), 52 deletions(-) create mode 100644 internal/events/serve.go diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index 43cd7087..634181d7 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -188,18 +188,6 @@ func New( //nolint:funlen return nil, nil, fmt.Errorf("failed to initialize bridge: %w", err) } - // Start serving IMAP. - if err := bridge.serveIMAP(); err != nil { - logrus.WithError(err).Error("IMAP error") - bridge.PushError(ErrServeIMAP) - } - - // Start serving SMTP. - if err := bridge.serveSMTP(); err != nil { - logrus.WithError(err).Error("SMTP error") - bridge.PushError(ErrServeSMTP) - } - return bridge, eventCh, nil } @@ -383,15 +371,33 @@ func (bridge *Bridge) init(tlsReporter TLSReporter) error { }) }) - // Attempt to lazy load users when triggered. + // Attempt to lazy load users when triggered. Only load once. + var loaded bool bridge.goLoad = bridge.tasks.Trigger(func(ctx context.Context) { + if loaded { + logrus.Debug("All users are already loaded, skipping") + return + } + logrus.Info("Loading users") if err := bridge.loadUsers(ctx); err != nil { logrus.WithError(err).Error("Failed to load users") - } else { - bridge.publish(events.AllUsersLoaded{}) + return } + + bridge.publish(events.AllUsersLoaded{}) + + // Once all users have been loaded, start the bridge's IMAP and SMTP servers. + if err := bridge.serveIMAP(); err != nil { + logrus.WithError(err).Error("Failed to start IMAP server") + } + + if err := bridge.serveSMTP(); err != nil { + logrus.WithError(err).Error("Failed to start SMTP server") + } + + loaded = true }) defer bridge.goLoad() diff --git a/internal/bridge/bridge_test.go b/internal/bridge/bridge_test.go index 20d5a602..77e6f4a1 100644 --- a/internal/bridge/bridge_test.go +++ b/internal/bridge/bridge_test.go @@ -671,6 +671,10 @@ func withBridgeNoMocks( // Wait for bridge to finish loading users. waitForEvent(t, eventCh, events.AllUsersLoaded{}) + // Wait for bridge to start the IMAP server. + waitForEvent(t, eventCh, events.IMAPServerReady{}) + // Wait for bridge to start the SMTP server. + waitForEvent(t, eventCh, events.SMTPServerReady{}) // Set random IMAP and SMTP ports for the tests. require.NoError(t, bridge.SetIMAPPort(0)) diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index cd3d25ad..358da57f 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -46,28 +46,42 @@ const ( ) func (bridge *Bridge) serveIMAP() error { - if bridge.imapServer == nil { - return fmt.Errorf("no imap server instance running") + if port, err := func() (int, error) { + if bridge.imapServer == nil { + return 0, fmt.Errorf("no IMAP server instance running") + } + + logrus.Info("Starting IMAP server") + + imapListener, err := newListener(bridge.vault.GetIMAPPort(), bridge.vault.GetIMAPSSL(), bridge.tlsConfig) + if err != nil { + return 0, fmt.Errorf("failed to create IMAP listener: %w", err) + } + + bridge.imapListener = imapListener + + if err := bridge.imapServer.Serve(context.Background(), bridge.imapListener); err != nil { + return 0, fmt.Errorf("failed to serve IMAP: %w", err) + } + + if err := bridge.vault.SetIMAPPort(getPort(imapListener.Addr())); err != nil { + return 0, fmt.Errorf("failed to store IMAP port in vault: %w", err) + } + + return getPort(imapListener.Addr()), nil + }(); err != nil { + bridge.publish(events.IMAPServerError{ + Error: err, + }) + + return err + } else { + bridge.publish(events.IMAPServerReady{ + Port: port, + }) + + return nil } - - logrus.Info("Starting IMAP server") - - imapListener, err := newListener(bridge.vault.GetIMAPPort(), bridge.vault.GetIMAPSSL(), bridge.tlsConfig) - if err != nil { - return fmt.Errorf("failed to create IMAP listener: %w", err) - } - - bridge.imapListener = imapListener - - if err := bridge.imapServer.Serve(context.Background(), bridge.imapListener); err != nil { - return fmt.Errorf("failed to serve IMAP: %w", err) - } - - if err := bridge.vault.SetIMAPPort(getPort(imapListener.Addr())); err != nil { - return fmt.Errorf("failed to store IMAP port in vault: %w", err) - } - - return nil } func (bridge *Bridge) restartIMAP() error { @@ -77,6 +91,8 @@ func (bridge *Bridge) restartIMAP() error { if err := bridge.imapListener.Close(); err != nil { return fmt.Errorf("failed to close IMAP listener: %w", err) } + + bridge.publish(events.IMAPServerStopped{}) } return bridge.serveIMAP() @@ -89,6 +105,7 @@ func (bridge *Bridge) closeIMAP(ctx context.Context) error { if err := bridge.imapServer.Close(ctx); err != nil { return fmt.Errorf("failed to close IMAP server: %w", err) } + bridge.imapServer = nil } @@ -98,6 +115,8 @@ func (bridge *Bridge) closeIMAP(ctx context.Context) error { } } + bridge.publish(events.IMAPServerStopped{}) + return nil } diff --git a/internal/bridge/smtp.go b/internal/bridge/smtp.go index 35642e6f..0ecf269d 100644 --- a/internal/bridge/smtp.go +++ b/internal/bridge/smtp.go @@ -22,6 +22,7 @@ import ( "crypto/tls" "fmt" + "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/logging" "github.com/ProtonMail/proton-bridge/v3/internal/constants" @@ -31,26 +32,40 @@ import ( ) func (bridge *Bridge) serveSMTP() error { - logrus.Info("Starting SMTP server") + if port, err := func() (int, error) { + logrus.Info("Starting SMTP server") - smtpListener, err := newListener(bridge.vault.GetSMTPPort(), bridge.vault.GetSMTPSSL(), bridge.tlsConfig) - if err != nil { - return fmt.Errorf("failed to create SMTP listener: %w", err) - } - - bridge.smtpListener = smtpListener - - bridge.tasks.Once(func(context.Context) { - if err := bridge.smtpServer.Serve(smtpListener); err != nil { - logrus.WithError(err).Info("SMTP server stopped") + smtpListener, err := newListener(bridge.vault.GetSMTPPort(), bridge.vault.GetSMTPSSL(), bridge.tlsConfig) + if err != nil { + return 0, fmt.Errorf("failed to create SMTP listener: %w", err) } - }) - if err := bridge.vault.SetSMTPPort(getPort(smtpListener.Addr())); err != nil { - return fmt.Errorf("failed to store SMTP port in vault: %w", err) + bridge.smtpListener = smtpListener + + bridge.tasks.Once(func(context.Context) { + if err := bridge.smtpServer.Serve(smtpListener); err != nil { + logrus.WithError(err).Info("SMTP server stopped") + } + }) + + if err := bridge.vault.SetSMTPPort(getPort(smtpListener.Addr())); err != nil { + return 0, fmt.Errorf("failed to store SMTP port in vault: %w", err) + } + + return getPort(smtpListener.Addr()), nil + }(); err != nil { + bridge.publish(events.SMTPServerError{ + Error: err, + }) + + return err + } else { + bridge.publish(events.SMTPServerReady{ + Port: port, + }) + + return nil } - - return nil } func (bridge *Bridge) restartSMTP() error { @@ -60,6 +75,8 @@ func (bridge *Bridge) restartSMTP() error { return fmt.Errorf("failed to close SMTP: %w", err) } + bridge.publish(events.SMTPServerStopped{}) + bridge.smtpServer = newSMTPServer(bridge, bridge.tlsConfig, bridge.logSMTP) return bridge.serveSMTP() @@ -82,6 +99,8 @@ func (bridge *Bridge) closeSMTP() error { logrus.WithError(err).Debug("Failed to close SMTP server (expected -- we close the listener ourselves)") } + bridge.publish(events.SMTPServerStopped{}) + return nil } diff --git a/internal/events/serve.go b/internal/events/serve.go new file mode 100644 index 00000000..ca6c3500 --- /dev/null +++ b/internal/events/serve.go @@ -0,0 +1,59 @@ +package events + +import "fmt" + +type IMAPServerReady struct { + eventBase + + Port int +} + +func (event IMAPServerReady) String() string { + return fmt.Sprintf("IMAPServerReady: Port %d", event.Port) +} + +type IMAPServerStopped struct { + eventBase +} + +func (event IMAPServerStopped) String() string { + return "IMAPServerStopped" +} + +type IMAPServerError struct { + eventBase + + Error error +} + +func (event IMAPServerError) String() string { + return fmt.Sprintf("IMAPServerError: %v", event.Error) +} + +type SMTPServerReady struct { + eventBase + + Port int +} + +func (event SMTPServerReady) String() string { + return fmt.Sprintf("SMTPServerReady: Port %d", event.Port) +} + +type SMTPServerStopped struct { + eventBase +} + +func (event SMTPServerStopped) String() string { + return "SMTPServerStopped" +} + +type SMTPServerError struct { + eventBase + + Error error +} + +func (event SMTPServerError) String() string { + return fmt.Sprintf("SMTPServerError: %v", event.Error) +} From 2e832520e68efa1cfed3c4b3a456021ed0cd348f Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Wed, 1 Feb 2023 13:11:57 +0100 Subject: [PATCH 023/130] chore: Remove panics from SetGluonDir --- internal/bridge/bridge.go | 28 +++++++++---------- internal/bridge/imap.go | 18 ++++++------ internal/bridge/settings.go | 55 +++++++++++-------------------------- internal/bridge/smtp.go | 18 ++++++------ internal/events/serve.go | 17 ++++++++++++ 5 files changed, 66 insertions(+), 70 deletions(-) diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index 634181d7..699cf551 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -371,14 +371,12 @@ func (bridge *Bridge) init(tlsReporter TLSReporter) error { }) }) - // Attempt to lazy load users when triggered. Only load once. - var loaded bool - bridge.goLoad = bridge.tasks.Trigger(func(ctx context.Context) { - if loaded { - logrus.Debug("All users are already loaded, skipping") - return - } + // We need to load users before we can start the IMAP and SMTP servers. + // We must only start the servers once. + var once sync.Once + // Attempt to load users from the vault when triggered. + bridge.goLoad = bridge.tasks.Trigger(func(ctx context.Context) { logrus.Info("Loading users") if err := bridge.loadUsers(ctx); err != nil { @@ -389,15 +387,15 @@ func (bridge *Bridge) init(tlsReporter TLSReporter) error { bridge.publish(events.AllUsersLoaded{}) // Once all users have been loaded, start the bridge's IMAP and SMTP servers. - if err := bridge.serveIMAP(); err != nil { - logrus.WithError(err).Error("Failed to start IMAP server") - } + once.Do(func() { + if err := bridge.serveIMAP(); err != nil { + logrus.WithError(err).Error("Failed to start IMAP server") + } - if err := bridge.serveSMTP(); err != nil { - logrus.WithError(err).Error("Failed to start SMTP server") - } - - loaded = true + if err := bridge.serveSMTP(); err != nil { + logrus.WithError(err).Error("Failed to start SMTP server") + } + }) }) defer bridge.goLoad() diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index 358da57f..8141cbf9 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -46,7 +46,7 @@ const ( ) func (bridge *Bridge) serveIMAP() error { - if port, err := func() (int, error) { + port, err := func() (int, error) { if bridge.imapServer == nil { return 0, fmt.Errorf("no IMAP server instance running") } @@ -69,19 +69,21 @@ func (bridge *Bridge) serveIMAP() error { } return getPort(imapListener.Addr()), nil - }(); err != nil { + }() + + if err != nil { bridge.publish(events.IMAPServerError{ Error: err, }) return err - } else { - bridge.publish(events.IMAPServerReady{ - Port: port, - }) - - return nil } + + bridge.publish(events.IMAPServerReady{ + Port: port, + }) + + return nil } func (bridge *Bridge) restartIMAP() error { diff --git a/internal/bridge/settings.go b/internal/bridge/settings.go index 1e0b1a0f..667406b2 100644 --- a/internal/bridge/settings.go +++ b/internal/bridge/settings.go @@ -131,26 +131,21 @@ func (bridge *Bridge) SetGluonDir(ctx context.Context, newGluonDir string) error return fmt.Errorf("new gluon dir is the same as the old one") } - if err := bridge.stopEventLoops(); err != nil { - return err + if err := bridge.closeIMAP(context.Background()); err != nil { + return fmt.Errorf("failed to close IMAP: %w", err) } - defer func() { - err := bridge.startEventLoops(ctx) - if err != nil { - panic(err) - } - }() if err := bridge.moveGluonCacheDir(currentGluonDir, newGluonDir); err != nil { logrus.WithError(err).Error("failed to move GluonCacheDir") + if err := bridge.vault.SetGluonDir(currentGluonDir); err != nil { - panic(err) + return fmt.Errorf("failed to revert GluonCacheDir: %w", err) } } gluonDataDir, err := bridge.GetGluonDataDir() if err != nil { - panic(fmt.Errorf("failed to get Gluon Database directory: %w", err)) + return fmt.Errorf("failed to get Gluon Database directory: %w", err) } imapServer, err := newIMAPServer( @@ -166,11 +161,21 @@ func (bridge *Bridge) SetGluonDir(ctx context.Context, newGluonDir string) error bridge.uidValidityGenerator, ) if err != nil { - panic(fmt.Errorf("failed to create new IMAP server: %w", err)) + return fmt.Errorf("failed to create new IMAP server: %w", err) } bridge.imapServer = imapServer + for _, user := range bridge.users { + if err := bridge.addIMAPUser(ctx, user); err != nil { + return fmt.Errorf("failed to add users to new IMAP server: %w", err) + } + } + + if err := bridge.serveIMAP(); err != nil { + return fmt.Errorf("failed to serve IMAP: %w", err) + } + return nil }, bridge.usersLock) } @@ -192,34 +197,6 @@ func (bridge *Bridge) moveGluonCacheDir(oldGluonDir, newGluonDir string) error { return nil } -func (bridge *Bridge) stopEventLoops() error { - if err := bridge.closeIMAP(context.Background()); err != nil { - return fmt.Errorf("failed to close IMAP: %w", err) - } - - if err := bridge.closeSMTP(); err != nil { - return fmt.Errorf("failed to close SMTP: %w", err) - } - return nil -} - -func (bridge *Bridge) startEventLoops(ctx context.Context) error { - for _, user := range bridge.users { - if err := bridge.addIMAPUser(ctx, user); err != nil { - return fmt.Errorf("failed to add users to new IMAP server: %w", err) - } - } - - if err := bridge.serveIMAP(); err != nil { - panic(fmt.Errorf("failed to serve IMAP: %w", err)) - } - - if err := bridge.serveSMTP(); err != nil { - panic(fmt.Errorf("failed to serve SMTP: %w", err)) - } - return nil -} - func (bridge *Bridge) GetProxyAllowed() bool { return bridge.vault.GetProxyAllowed() } diff --git a/internal/bridge/smtp.go b/internal/bridge/smtp.go index 0ecf269d..b6d95158 100644 --- a/internal/bridge/smtp.go +++ b/internal/bridge/smtp.go @@ -32,7 +32,7 @@ import ( ) func (bridge *Bridge) serveSMTP() error { - if port, err := func() (int, error) { + port, err := func() (int, error) { logrus.Info("Starting SMTP server") smtpListener, err := newListener(bridge.vault.GetSMTPPort(), bridge.vault.GetSMTPSSL(), bridge.tlsConfig) @@ -53,19 +53,21 @@ func (bridge *Bridge) serveSMTP() error { } return getPort(smtpListener.Addr()), nil - }(); err != nil { + }() + + if err != nil { bridge.publish(events.SMTPServerError{ Error: err, }) return err - } else { - bridge.publish(events.SMTPServerReady{ - Port: port, - }) - - return nil } + + bridge.publish(events.SMTPServerReady{ + Port: port, + }) + + return nil } func (bridge *Bridge) restartSMTP() error { diff --git a/internal/events/serve.go b/internal/events/serve.go index ca6c3500..a8f866b1 100644 --- a/internal/events/serve.go +++ b/internal/events/serve.go @@ -1,3 +1,20 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + package events import "fmt" From a74d1ce9ca9c46509eacb82707498557a0aeff18 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Wed, 1 Feb 2023 13:38:16 +0100 Subject: [PATCH 024/130] feat(GODT-2144): Handle IMAP/SMTP server errors via event stream --- internal/bridge/errors.go | 5 +---- internal/frontend/cli/frontend.go | 12 ++++++------ internal/frontend/grpc/service.go | 12 ++++++------ 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/internal/bridge/errors.go b/internal/bridge/errors.go index 98377649..ecb897f4 100644 --- a/internal/bridge/errors.go +++ b/internal/bridge/errors.go @@ -22,10 +22,7 @@ import "errors" var ( ErrVaultInsecure = errors.New("the vault is insecure") ErrVaultCorrupt = errors.New("the vault is corrupt") - - ErrServeIMAP = errors.New("failed to serve IMAP") - ErrServeSMTP = errors.New("failed to serve SMTP") - ErrWatchUpdates = errors.New("failed to watch for updates") + ErrWatchUpdates = errors.New("failed to watch for updates") ErrNoSuchUser = errors.New("no such user") ErrUserAlreadyExists = errors.New("user already exists") diff --git a/internal/frontend/cli/frontend.go b/internal/frontend/cli/frontend.go index aac7d258..58ee6c4b 100644 --- a/internal/frontend/cli/frontend.go +++ b/internal/frontend/cli/frontend.go @@ -270,12 +270,6 @@ func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:funle case errors.Is(err, bridge.ErrVaultInsecure): f.notifyCredentialsError() - - case errors.Is(err, bridge.ErrServeIMAP): - f.Println("IMAP server error:", err) - - case errors.Is(err, bridge.ErrServeSMTP): - f.Println("SMTP server error:", err) } } @@ -287,6 +281,12 @@ func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:funle case events.ConnStatusDown: f.notifyInternetOff() + case events.IMAPServerError: + f.Println("IMAP server error:", event.Error) + + case events.SMTPServerError: + f.Println("SMTP server error:", event.Error) + case events.UserDeauth: user, err := f.bridge.GetUserInfo(event.UserID) if err != nil { diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index 8ec8834a..7d0bdfd4 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -256,12 +256,6 @@ func (s *Service) watchEvents() { case errors.Is(err, bridge.ErrVaultInsecure): _ = s.SendEvent(NewKeychainHasNoKeychainEvent()) - - case errors.Is(err, bridge.ErrServeIMAP): - _ = s.SendEvent(NewMailServerSettingsErrorEvent(MailServerSettingsErrorType_IMAP_PORT_STARTUP_ERROR)) - - case errors.Is(err, bridge.ErrServeSMTP): - _ = s.SendEvent(NewMailServerSettingsErrorEvent(MailServerSettingsErrorType_SMTP_PORT_STARTUP_ERROR)) } } @@ -273,6 +267,12 @@ func (s *Service) watchEvents() { case events.ConnStatusDown: _ = s.SendEvent(NewInternetStatusEvent(false)) + case events.IMAPServerError: + _ = s.SendEvent(NewMailServerSettingsErrorEvent(MailServerSettingsErrorType_IMAP_PORT_STARTUP_ERROR)) + + case events.SMTPServerError: + _ = s.SendEvent(NewMailServerSettingsErrorEvent(MailServerSettingsErrorType_SMTP_PORT_STARTUP_ERROR)) + case events.Raise: _ = s.SendEvent(NewShowMainWindowEvent()) From 8894a982f23df72fa4d02fb6d1064176c5ce22e4 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 6 Feb 2023 10:50:47 +0100 Subject: [PATCH 025/130] ci(GODT-2287): add test coverage on devel --- .gitlab-ci.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8a7cc133..5cf27441 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -32,7 +32,7 @@ stages: .rules-branch-and-MR-always: rules: - - if: $CI_COMMIT_BRANCH || $CI_PIPELINE_SOURCE == "merge_request_event" + - if: $CI_COMMIT_BRANCH || $CI_PIPELINE_SOURCE == "merge_request_event" when: always allow_failure: false - when: never @@ -54,6 +54,16 @@ stages: allow_failure: true - when: never +.rules-branch-manual-MR-and-devel-always: + rules: + - if: $CI_COMMIT_BRANCH == "devel" || $CI_PIPELINE_SOURCE == "merge_request_event" + when: always + allow_failure: false + - if: $CI_COMMIT_BRANCH + when: manual + allow_failure: true + - when: never + .after-script-code-coverage: after_script: - go get github.com/boumenot/gocover-cobertura @@ -80,7 +90,7 @@ lint: test-linux: stage: test extends: - - .rules-branch-manual-MR-always + - .rules-branch-manual-MR-and-devel-always - .after-script-code-coverage script: - make test From d82b71de89dea9a012fb647e8a38b2b74031585e Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Fri, 3 Feb 2023 11:47:04 +0100 Subject: [PATCH 026/130] fix(GODT-1804): Only promote content headers if non-empty MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When attaching public key, we take the root mime part, create a new root, and put the old root alongside an additional public key mime part. But when moving the root, we would copy all content headers, even empty ones. So we’d be left with Content-Disposition: "" which would fail to parse. --- go.mod | 2 +- go.sum | 4 +- internal/bridge/send_test.go | 113 ++++++++++++++++++++++++++++ internal/bridge/testdata/invite.eml | 85 +++++++++++++++++++++ internal/user/smtp.go | 2 +- pkg/message/parser/part.go | 14 +++- 6 files changed, 213 insertions(+), 7 deletions(-) create mode 100644 internal/bridge/testdata/invite.eml diff --git a/go.mod b/go.mod index 6c24d229..bc6ff7d5 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/gluon v0.14.2-0.20230202124956-4fa6b6a0b9b5 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.3.1-0.20230202061850-e2fc4deffe20 + github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.4.10 github.com/PuerkitoBio/goquery v1.8.0 diff --git a/go.sum b/go.sum index 2e1e7a17..8f1ce0f2 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230202061850-e2fc4deffe20 h1:EMDPJ/VrXRvlY9xZ9X2HZgdDh6285ikKnrW6psm0cf4= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230202061850-e2fc4deffe20/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b h1:3UX0j2WA3NsqmrjTK769sCIOX2KnISfo8tZdFl7+mRE= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= diff --git a/internal/bridge/send_test.go b/internal/bridge/send_test.go index 7f009f61..b9e6e0ca 100644 --- a/internal/bridge/send_test.go +++ b/internal/bridge/send_test.go @@ -18,10 +18,12 @@ package bridge_test import ( + "bytes" "context" "crypto/tls" "fmt" "net" + "os" "strings" "testing" "time" @@ -217,3 +219,114 @@ func TestBridge_SendDraftFlags(t *testing.T) { }) }) } + +func TestBridge_SendInvite(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + // Create a recipient user. + _, _, err := s.CreateUser("recipient", password) + require.NoError(t, err) + + // Set "attach public keys" to true for the user. + withClient(ctx, t, s, username, password, func(ctx context.Context, client *proton.Client) { + settings, err := client.SetAttachPublicKey(ctx, proton.SetAttachPublicKeyReq{AttachPublicKey: true}) + require.NoError(t, err) + require.Equal(t, proton.Bool(true), settings.AttachPublicKey) + }) + + // The sender should be fully synced. + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, _ *bridge.Mocks) { + syncCh, done := chToType[events.Event, events.SyncFinished](bridge.GetEvents(events.SyncFinished{})) + defer done() + + userID, err := bridge.LoginFull(ctx, username, password, nil, nil) + require.NoError(t, err) + + require.Equal(t, userID, (<-syncCh).UserID) + }) + + // Start the bridge. + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, _ *bridge.Mocks) { + // Get the sender user info. + userInfo, err := bridge.QueryUserInfo(username) + require.NoError(t, err) + + // Connect the sender IMAP client. + imapClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort()))) + require.NoError(t, err) + require.NoError(t, imapClient.Login(userInfo.Addresses[0], string(userInfo.BridgePass))) + defer imapClient.Logout() //nolint:errcheck + + // The message to send. + b, err := os.ReadFile("testdata/invite.eml") + require.NoError(t, err) + + // Save a draft. + require.NoError(t, imapClient.Append("Drafts", []string{imap.DraftFlag}, time.Now(), bytes.NewReader(b))) + + // Assert that the draft exists and is marked as a draft. + { + messages, err := clientFetch(imapClient, "Drafts") + require.NoError(t, err) + require.Len(t, messages, 1) + require.Contains(t, messages[0].Flags, imap.DraftFlag) + } + + // Connect the SMTP client. + smtpClient, err := smtp.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetSMTPPort()))) + require.NoError(t, err) + defer smtpClient.Close() //nolint:errcheck + + // Upgrade to TLS. + require.NoError(t, smtpClient.StartTLS(&tls.Config{InsecureSkipVerify: true})) + + // Authorize with SASL PLAIN. + require.NoError(t, smtpClient.Auth(sasl.NewPlainClient( + userInfo.Addresses[0], + userInfo.Addresses[0], + string(userInfo.BridgePass)), + )) + + // Send the message. + require.NoError(t, smtpClient.SendMail( + userInfo.Addresses[0], + []string{"recipient@" + s.GetDomain()}, + bytes.NewReader(b), + )) + + // Delete the draft: add the \Deleted flag and expunge. + { + status, err := imapClient.Select("Drafts", false) + require.NoError(t, err) + require.Equal(t, uint32(1), status.Messages) + + // Add the \Deleted flag. + require.NoError(t, clientStore(imapClient, 1, 1, true, imap.FormatFlagsOp(imap.AddFlags, true), imap.DeletedFlag)) + + // Expunge. + require.NoError(t, imapClient.Expunge(nil)) + } + + // Assert that the draft is eventually gone. + require.Eventually(t, func() bool { + status, err := imapClient.Select("Drafts", false) + require.NoError(t, err) + return status.Messages == 0 + }, 10*time.Second, 100*time.Millisecond) + + // Assert that the message is eventually in the sent folder. + require.Eventually(t, func() bool { + messages, err := clientFetch(imapClient, "Sent") + require.NoError(t, err) + return len(messages) == 1 + }, 10*time.Second, 100*time.Millisecond) + + // Assert that the message is not marked as a draft. + { + messages, err := clientFetch(imapClient, "Sent") + require.NoError(t, err) + require.Len(t, messages, 1) + require.NotContains(t, messages[0].Flags, imap.DraftFlag) + } + }) + }) +} diff --git a/internal/bridge/testdata/invite.eml b/internal/bridge/testdata/invite.eml new file mode 100644 index 00000000..b9efbc92 --- /dev/null +++ b/internal/bridge/testdata/invite.eml @@ -0,0 +1,85 @@ +From: +To: +Subject: Testing calendar invite +Date: Fri, 3 Feb 2023 01:04:32 +0100 +Message-ID: <000001d93763$183b74e0$48b25ea0$@proton.local> +MIME-Version: 1.0 +Content-Type: text/calendar; method=REQUEST; + charset="utf-8" +Content-Transfer-Encoding: 7bit +X-Mailer: Microsoft Outlook 16.0 +Thread-Index: Adk3Yw5pLdgwsT46RviXb/nfvQlesQAAAmGA +Content-Language: en-gb + +BEGIN:VCALENDAR +PRODID:-//Microsoft Corporation//Outlook 16.0 MIMEDIR//EN +VERSION:2.0 +METHOD:REQUEST +X-MS-OLK-FORCEINSPECTOROPEN:TRUE +BEGIN:VTIMEZONE +TZID:Central European Standard Time +BEGIN:STANDARD +DTSTART:16011028T030000 +RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10 +TZOFFSETFROM:+0200 +TZOFFSETTO:+0100 +END:STANDARD +BEGIN:DAYLIGHT +DTSTART:16010325T020000 +RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3 +TZOFFSETFROM:+0100 +TZOFFSETTO:+0200 +END:DAYLIGHT +END:VTIMEZONE +BEGIN:VEVENT +ATTENDEE;CN=recipient@proton.local;RSVP=TRUE:mailto:recipient@proton.local +CLASS:PUBLIC +CREATED:20230203T000432Z +DESCRIPTION:qweqweqweqweqweqwe/gn\\n +DTEND;TZID="Central European Standard Time":20230203T020000 +DTSTAMP:20230203T000432Z +DTSTART;TZID="Central European Standard Time":20230203T013000 +LAST-MODIFIED:20230203T000432Z +LOCATION:qweqwe +ORGANIZER;CN=username@proton.local:mailto:username@proton.local +PRIORITY:5 +SEQUENCE:0 +SUMMARY;LANGUAGE=en-gb:Testing calendar invite +TRANSP:OPAQUE +UID:040000008200E00074C5B7101A82E008000000003080B2796B37D901000000000000000 + 0100000001236CD1CD93CA9449C6FF1AC4DEAC44E +X-ALT-DESC;FMTTYPE=text/html:

qweqweqweqweqweqw + e

+X-MICROSOFT-CDO-BUSYSTATUS:TENTATIVE +X-MICROSOFT-CDO-IMPORTANCE:1 +X-MICROSOFT-CDO-INTENDEDSTATUS:BUSY +X-MICROSOFT-DISALLOW-COUNTER:FALSE +X-MS-OLK-AUTOSTARTCHECK:FALSE +X-MS-OLK-CONFTYPE:0 +BEGIN:VALARM +TRIGGER:-PT15M +ACTION:DISPLAY +DESCRIPTION:Reminder +END:VALARM +END:VEVENT +END:VCALENDAR + diff --git a/internal/user/smtp.go b/internal/user/smtp.go index 5c0b03be..ed6f399b 100644 --- a/internal/user/smtp.go +++ b/internal/user/smtp.go @@ -120,7 +120,7 @@ func (user *User) sendMail(authID string, from string, to []string, r io.Reader) } // If we have to attach the public key, do it now. - if settings.AttachPublicKey == proton.AttachPublicKeyEnabled { + if settings.AttachPublicKey { key, err := addrKR.GetKey(0) if err != nil { return fmt.Errorf("failed to get sending key: %w", err) diff --git a/pkg/message/parser/part.go b/pkg/message/parser/part.go index 1f1309d2..3248fa3d 100644 --- a/pkg/message/parser/part.go +++ b/pkg/message/parser/part.go @@ -186,9 +186,17 @@ func (p *Part) isMultipartMixed() bool { func getContentHeaders(header message.Header) message.Header { var res message.Header - res.Set("Content-Type", header.Get("Content-Type")) - res.Set("Content-Disposition", header.Get("Content-Disposition")) - res.Set("Content-Transfer-Encoding", header.Get("Content-Transfer-Encoding")) + if contentType := header.Get("Content-Type"); contentType != "" { + res.Set("Content-Type", contentType) + } + + if contentDisposition := header.Get("Content-Disposition"); contentDisposition != "" { + res.Set("Content-Disposition", contentDisposition) + } + + if contentTransferEncoding := header.Get("Content-Transfer-Encoding"); contentTransferEncoding != "" { + res.Set("Content-Transfer-Encoding", contentTransferEncoding) + } return res } From 34cd611a8befbef9367177da63ea5dabcfa06831 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Fri, 3 Feb 2023 16:18:25 +0100 Subject: [PATCH 027/130] chore: Disable funlen linter --- .golangci.yml | 3 --- internal/app/app.go | 4 ++-- internal/app/bridge.go | 2 +- internal/app/migration.go | 1 - internal/bridge/bridge.go | 4 +--- internal/bridge/bug_report.go | 2 +- internal/bridge/imap.go | 3 --- internal/frontend/cli/accounts.go | 2 +- internal/frontend/cli/frontend.go | 4 ++-- internal/frontend/grpc/service.go | 4 +--- internal/frontend/grpc/service_stream.go | 2 +- internal/updater/sync.go | 2 +- internal/user/events.go | 2 +- internal/user/imap.go | 4 +--- internal/user/send_recorder.go | 2 -- internal/user/smtp.go | 7 ++----- internal/user/sync.go | 3 +-- internal/user/user.go | 6 +----- pkg/message/build.go | 4 ++-- pkg/message/parser.go | 2 +- utils/hasher/main.go | 2 +- utils/versioner/main.go | 2 +- 22 files changed, 22 insertions(+), 45 deletions(-) diff --git a/.golangci.yml b/.golangci.yml index 9ac51197..6149b688 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -23,7 +23,6 @@ issues: - path: _test\.go linters: - dupl - - funlen - gochecknoglobals - gochecknoinits - gosec @@ -32,7 +31,6 @@ issues: - path: test linters: - dupl - - funlen - gochecknoglobals - gochecknoinits - gosec @@ -64,7 +62,6 @@ linters: - depguard # Go linter that checks if package imports are in a list of acceptable packages [fast: true, auto-fix: false] - dogsled # Checks assignments with too many blank identifiers (e.g. x, _, _, _, := f()) [fast: true, auto-fix: false] - dupl # Tool for code clone detection [fast: true, auto-fix: false] - - funlen # Tool for detection of long functions [fast: true, auto-fix: false] - gochecknoglobals # Checks that no globals are present in Go code [fast: true, auto-fix: false] - gochecknoinits # Checks that no init functions are present in Go code [fast: true, auto-fix: false] - goconst # Finds repeated strings that could be replaced by a constant [fast: true, auto-fix: false] diff --git a/internal/app/app.go b/internal/app/app.go index 6663a920..3167456f 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -81,7 +81,7 @@ const ( appUsage = "Proton Mail IMAP and SMTP Bridge" ) -func New() *cli.App { //nolint:funlen +func New() *cli.App { app := cli.NewApp() app.Name = constants.FullAppName @@ -156,7 +156,7 @@ func New() *cli.App { //nolint:funlen return app } -func run(c *cli.Context) error { //nolint:funlen +func run(c *cli.Context) error { // Seed the default RNG from the math/rand package. rand.Seed(time.Now().UnixNano()) diff --git a/internal/app/bridge.go b/internal/app/bridge.go index 38ce3c82..ef42697d 100644 --- a/internal/app/bridge.go +++ b/internal/app/bridge.go @@ -47,7 +47,7 @@ const vaultSecretName = "bridge-vault-key" var deleteOldGoIMAPFiles bool //nolint:gochecknoglobals // withBridge creates creates and tears down the bridge. -func withBridge( //nolint:funlen +func withBridge( c *cli.Context, exe string, locations *locations.Locations, diff --git a/internal/app/migration.go b/internal/app/migration.go index 7f187b1b..4c440e6b 100644 --- a/internal/app/migration.go +++ b/internal/app/migration.go @@ -187,7 +187,6 @@ func migrateOldAccount(userID string, store *credentials.Store, v *vault.Vault) return nil } -// nolint:funlen func migratePrefsToVault(vault *vault.Vault, b []byte) error { var prefs struct { IMAPPort int `json:"user_port_imap,,string"` diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index 699cf551..70cfb590 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -128,7 +128,7 @@ type Bridge struct { } // New creates a new bridge. -func New( //nolint:funlen +func New( locator Locator, // the locator to provide paths to store data vault *vault.Vault, // the bridge's encrypted data store autostarter Autostarter, // the autostarter to manage autostart settings @@ -191,7 +191,6 @@ func New( //nolint:funlen return bridge, eventCh, nil } -// nolint:funlen func newBridge( tasks *async.Group, imapEventCh chan imapEvents.Event, @@ -302,7 +301,6 @@ func newBridge( return bridge, nil } -// nolint:funlen func (bridge *Bridge) init(tlsReporter TLSReporter) error { // Enable or disable the proxy at startup. if bridge.vault.GetProxyAllowed() { diff --git a/internal/bridge/bug_report.go b/internal/bridge/bug_report.go index bffc6911..10fb30e0 100644 --- a/internal/bridge/bug_report.go +++ b/internal/bridge/bug_report.go @@ -37,7 +37,7 @@ const ( MaxCompressedFilesCount = 6 ) -func (bridge *Bridge) ReportBug(ctx context.Context, osType, osVersion, description, username, email, client string, attachLogs bool) error { //nolint:funlen +func (bridge *Bridge) ReportBug(ctx context.Context, osType, osVersion, description, username, email, client string, attachLogs bool) error { var account string if info, err := bridge.QueryUserInfo(username); err == nil { diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index 8141cbf9..dc606e0e 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -123,8 +123,6 @@ func (bridge *Bridge) closeIMAP(ctx context.Context) error { } // addIMAPUser connects the given user to gluon. -// -//nolint:funlen func (bridge *Bridge) addIMAPUser(ctx context.Context, user *user.User) error { if bridge.imapServer == nil { return fmt.Errorf("no imap server instance running") @@ -276,7 +274,6 @@ func ApplyGluonConfigPathSuffix(basePath string) string { return filepath.Join(basePath, "backend", "db") } -// nolint:funlen func newIMAPServer( gluonCacheDir, gluonConfigDir string, version *semver.Version, diff --git a/internal/frontend/cli/accounts.go b/internal/frontend/cli/accounts.go index afacb10c..1cfb44ad 100644 --- a/internal/frontend/cli/accounts.go +++ b/internal/frontend/cli/accounts.go @@ -115,7 +115,7 @@ func (f *frontendCLI) showAccountAddressInfo(user bridge.UserInfo, address strin f.Println("") } -func (f *frontendCLI) loginAccount(c *ishell.Context) { //nolint:funlen +func (f *frontendCLI) loginAccount(c *ishell.Context) { f.ShowPrompt(false) defer f.ShowPrompt(true) diff --git a/internal/frontend/cli/frontend.go b/internal/frontend/cli/frontend.go index 58ee6c4b..e22856ca 100644 --- a/internal/frontend/cli/frontend.go +++ b/internal/frontend/cli/frontend.go @@ -40,7 +40,7 @@ type frontendCLI struct { } // New returns a new CLI frontend configured with the given options. -func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan events.Event) *frontendCLI { //nolint:funlen,revive +func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan events.Event) *frontendCLI { //nolint:revive fe := &frontendCLI{ Shell: ishell.New(), bridge: bridge, @@ -261,7 +261,7 @@ func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan e return fe } -func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:funlen,gocyclo +func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:gocyclo // GODT-1949: Better error events. for _, err := range f.bridge.GetErrors() { switch { diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index 7d0bdfd4..9c429378 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -94,8 +94,6 @@ type Service struct { // nolint:structcheck } // NewService returns a new instance of the service. -// -// nolint:funlen func NewService( panicHandler CrashHandler, restarter Restarter, @@ -246,7 +244,7 @@ func (s *Service) WaitUntilFrontendIsReady() { s.initializing.Wait() } -// nolint:funlen,gocyclo +// nolint:gocyclo func (s *Service) watchEvents() { // GODT-1949 Better error events. for _, err := range s.bridge.GetErrors() { diff --git a/internal/frontend/grpc/service_stream.go b/internal/frontend/grpc/service_stream.go index 83d6c4d2..c7243523 100644 --- a/internal/frontend/grpc/service_stream.go +++ b/internal/frontend/grpc/service_stream.go @@ -110,7 +110,7 @@ func (s *Service) SendEvent(event *StreamEvent) error { } // StartEventTest sends all the known event via gRPC. -func (s *Service) StartEventTest() error { //nolint:funlen +func (s *Service) StartEventTest() error { const dummyAddress = "dummy@proton.me" events := []*StreamEvent{ // app diff --git a/internal/updater/sync.go b/internal/updater/sync.go index 440cbd5d..8137a93b 100644 --- a/internal/updater/sync.go +++ b/internal/updater/sync.go @@ -142,7 +142,7 @@ func checksum(path string) (hash string) { // srcDir including app folder. // dstDir including app folder. -func copyRecursively(srcDir, dstDir string) error { //nolint:funlen +func copyRecursively(srcDir, dstDir string) error { return filepath.Walk(srcDir, func(srcPath string, srcInfo os.FileInfo, err error) error { if err != nil { return err diff --git a/internal/user/events.go b/internal/user/events.go index b009a2f6..2b0fc314 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -415,7 +415,7 @@ func (user *User) handleDeleteLabelEvent(ctx context.Context, event proton.Label } // handleMessageEvents handles the given message events. -func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proton.MessageEvent) error { //nolint:funlen +func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proton.MessageEvent) error { for _, event := range messageEvents { ctx = logging.WithLogrusField(ctx, "messageID", event.ID) diff --git a/internal/user/imap.go b/internal/user/imap.go index 4b50a305..7fb51981 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -264,8 +264,6 @@ func (conn *imapConnector) DeleteMailbox(ctx context.Context, labelID imap.Mailb } // CreateMessage creates a new message on the remote. -// -// nolint:funlen func (conn *imapConnector) CreateMessage( ctx context.Context, mailboxID imap.MailboxID, @@ -589,7 +587,7 @@ func toIMAPMessage(message proton.MessageMetadata) imap.Message { } } -func (conn *imapConnector) createDraft(ctx context.Context, literal []byte, addrKR *crypto.KeyRing, sender proton.Address) (proton.Message, error) { //nolint:funlen +func (conn *imapConnector) createDraft(ctx context.Context, literal []byte, addrKR *crypto.KeyRing, sender proton.Address) (proton.Message, error) { // Create a new message parser from the reader. parser, err := parser.New(bytes.NewReader(literal)) if err != nil { diff --git a/internal/user/send_recorder.go b/internal/user/send_recorder.go index c83c9ef1..283b35eb 100644 --- a/internal/user/send_recorder.go +++ b/internal/user/send_recorder.go @@ -218,8 +218,6 @@ func (h *sendRecorder) getWaitCh(hash string) (<-chan struct{}, bool) { // - the Content-Type header of each (leaf) part, // - the Content-Disposition header of each (leaf) part, // - the (decoded) body of each part. -// -// nolint:funlen func getMessageHash(b []byte) (string, error) { section := rfc822.Parse(b) diff --git a/internal/user/smtp.go b/internal/user/smtp.go index ed6f399b..0fb6fafd 100644 --- a/internal/user/smtp.go +++ b/internal/user/smtp.go @@ -47,8 +47,6 @@ import ( ) // sendMail sends an email from the given address to the given recipients. -// -// nolint:funlen func (user *User) sendMail(authID string, from string, to []string, r io.Reader) error { return safe.RLockRet(func() error { ctx, cancel := context.WithCancel(context.Background()) @@ -165,7 +163,7 @@ func (user *User) sendMail(authID string, from string, to []string, r io.Reader) } // sendWithKey sends the message with the given address key. -func sendWithKey( //nolint:funlen +func sendWithKey( ctx context.Context, client *proton.Client, sentry reporter.Reporter, @@ -247,7 +245,7 @@ func sendWithKey( //nolint:funlen return res, nil } -func getParentID( //nolint:funlen +func getParentID( ctx context.Context, client *proton.Client, authAddrID string, @@ -375,7 +373,6 @@ func createDraft( }) } -// nolint:funlen func createAttachments( ctx context.Context, client *proton.Client, diff --git a/internal/user/sync.go b/internal/user/sync.go index 1bba8b10..f584c662 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -87,7 +87,6 @@ func (user *User) doSync(ctx context.Context) error { return nil } -// nolint:funlen func (user *User) sync(ctx context.Context) error { return safe.RLockRet(func() error { return withAddrKRs(user.apiUser, user.apiAddrs, user.vault.KeyPass(), func(_ *crypto.KeyRing, addrKRs map[string]*crypto.KeyRing) error { @@ -218,7 +217,7 @@ func toMB(v uint64) float64 { return float64(v) / float64(Megabyte) } -// nolint:funlen,gocyclo +// nolint:gocyclo func syncMessages( ctx context.Context, userID string, diff --git a/internal/user/user.go b/internal/user/user.go index d7423827..45146a92 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -90,8 +90,6 @@ type User struct { } // New returns a new user. -// -// nolint:funlen func New( ctx context.Context, encVault *vault.User, @@ -101,7 +99,7 @@ func New( crashHandler async.PanicHandler, showAllMail bool, maxSyncMemory uint64, -) (*User, error) { //nolint:funlen +) (*User, error) { logrus.WithField("userID", apiUser.ID).Info("Creating new user") // Get the user's API addresses. @@ -419,8 +417,6 @@ func (user *User) NewIMAPConnectors() (map[string]connector.Connector, error) { } // SendMail sends an email from the given address to the given recipients. -// -// nolint:funlen func (user *User) SendMail(authID string, from string, to []string, r io.Reader) error { defer user.goPollAPIEvents(true) diff --git a/pkg/message/build.go b/pkg/message/build.go index 4811b48e..a6b893f1 100644 --- a/pkg/message/build.go +++ b/pkg/message/build.go @@ -325,7 +325,7 @@ func buildPGPMIMEFallbackRFC822(msg proton.Message, opts JobOptions, buf *bytes. return nil } -func writeMultipartSignedRFC822(header message.Header, body []byte, sig proton.Signature, buf *bytes.Buffer) error { //nolint:funlen +func writeMultipartSignedRFC822(header message.Header, body []byte, sig proton.Signature, buf *bytes.Buffer) error { boundary := newBoundary("").gen() header.SetContentType("multipart/signed", map[string]string{ @@ -427,7 +427,7 @@ func addressEmpty(address *mail.Address) bool { return false } -func getMessageHeader(msg proton.Message, opts JobOptions) message.Header { //nolint:funlen +func getMessageHeader(msg proton.Message, opts JobOptions) message.Header { hdr := toMessageHeader(msg.ParsedHeaders) // SetText will RFC2047-encode. diff --git a/pkg/message/parser.go b/pkg/message/parser.go index 6d5ee23c..cba83aee 100644 --- a/pkg/message/parser.go +++ b/pkg/message/parser.go @@ -433,7 +433,7 @@ func getPlainBody(part *parser.Part) []byte { } } -func parseMessageHeader(h message.Header) (Message, error) { //nolint:funlen +func parseMessageHeader(h message.Header) (Message, error) { var m Message for fields := h.Fields(); fields.Next(); { diff --git a/utils/hasher/main.go b/utils/hasher/main.go index 6bc924f4..1b56df6e 100644 --- a/utils/hasher/main.go +++ b/utils/hasher/main.go @@ -32,7 +32,7 @@ func main() { } } -func createApp() *cli.App { //nolint:funlen +func createApp() *cli.App { app := cli.NewApp() app.Name = "hasher" diff --git a/utils/versioner/main.go b/utils/versioner/main.go index b847b049..0ff57d62 100644 --- a/utils/versioner/main.go +++ b/utils/versioner/main.go @@ -42,7 +42,7 @@ func main() { } } -func createApp() *cli.App { //nolint:funlen +func createApp() *cli.App { app := cli.NewApp() app.Name = "versioner" From ad65bdde9d15e584698b5016bb43dd03ec4ce439 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Mon, 6 Feb 2023 16:30:03 +0100 Subject: [PATCH 028/130] fix(GODT-2326): Fix potential Win32 API deadlock Update gluon so that the store implementation uses `os.Remove` instead of `os.RemoveAll`. The latter has an issue where it can deadlock on windows. See https://github.com/golang/go/issues/36375 for more details. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index bc6ff7d5..bfc85e13 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230202124956-4fa6b6a0b9b5 + github.com/ProtonMail/gluon v0.14.2-0.20230206091703-4a3d7a57eeae github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 8f1ce0f2..8b4c9e27 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230202124956-4fa6b6a0b9b5 h1:AvU75C80KwKiPcAolL0p26zNdjJvr49qlVjgbqY+VsM= -github.com/ProtonMail/gluon v0.14.2-0.20230202124956-4fa6b6a0b9b5/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230206091703-4a3d7a57eeae h1:iJ0CgJEZTBRGX+vwmMrIg2HEGo3+qBJD/PPcDvYqzQg= +github.com/ProtonMail/gluon v0.14.2-0.20230206091703-4a3d7a57eeae/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= From f4a2fb9687f9e394a05f5e237f74a529d99a65fb Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Fri, 3 Feb 2023 15:51:18 +0100 Subject: [PATCH 029/130] test: Add failing test for changing address order while bridge is down --- internal/bridge/bridge_test.go | 63 ++++++++++++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/internal/bridge/bridge_test.go b/internal/bridge/bridge_test.go index 77e6f4a1..c3406628 100644 --- a/internal/bridge/bridge_test.go +++ b/internal/bridge/bridge_test.go @@ -576,6 +576,69 @@ func TestBridge_ChangeCacheDirectory(t *testing.T) { }) } +func TestBridge_ChangeAddressOrder(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, vaultKey []byte) { + // Create a user. + userID, addrID, err := s.CreateUser("imap", password) + require.NoError(t, err) + + // Create a second address for the user. + aliasID, err := s.CreateAddress(userID, "alias@"+s.GetDomain(), password) + require.NoError(t, err) + + // Create 10 messages for the user. + withClient(ctx, t, s, "imap", password, func(ctx context.Context, c *proton.Client) { + createNumMessages(ctx, t, c, addrID, proton.InboxLabel, 10) + }) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, vaultKey, func(b *bridge.Bridge, mocks *bridge.Mocks) { + // Log the user in with its first address. + syncCh, done := chToType[events.Event, events.SyncFinished](b.GetEvents(events.SyncFinished{})) + defer done() + userID, err := b.LoginFull(ctx, "imap", password, nil, nil) + require.NoError(t, err) + require.Equal(t, userID, (<-syncCh).UserID) + + // We should see 10 messages in the inbox. + info, err := b.GetUserInfo(userID) + require.NoError(t, err) + require.True(t, info.State == bridge.Connected) + + client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort())) + require.NoError(t, err) + require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) + defer func() { _ = client.Logout() }() + + status, err := client.Select(`Inbox`, false) + require.NoError(t, err) + require.Equal(t, uint32(10), status.Messages) + }) + + // Make the second address the primary one. + withClient(ctx, t, s, "imap", password, func(ctx context.Context, c *proton.Client) { + require.NoError(t, c.OrderAddresses(ctx, proton.OrderAddressesReq{AddressIDs: []string{aliasID, addrID}})) + }) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, vaultKey, func(b *bridge.Bridge, mocks *bridge.Mocks) { + // We should still see 10 messages in the inbox. + info, err := b.GetUserInfo(userID) + require.NoError(t, err) + require.True(t, info.State == bridge.Connected) + + client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort())) + require.NoError(t, err) + require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) + defer func() { _ = client.Logout() }() + + require.Eventually(t, func() bool { + status, err := client.Select(`Inbox`, false) + require.NoError(t, err) + return status.Messages == 10 + }, 5*time.Second, 100*time.Millisecond) + }) + }) +} + // withEnv creates the full test environment and runs the tests. func withEnv(t *testing.T, tests func(context.Context, *server.Server, *proton.NetCtl, bridge.Locator, []byte), opts ...server.Option) { server := server.New(opts...) From 40aca0fe738c3ae9b6a00f646edcf69edb5b4240 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Fri, 3 Feb 2023 16:03:36 +0100 Subject: [PATCH 030/130] fix(GODT-2336): Recover from changed address order while bridge is down --- internal/user/user.go | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/internal/user/user.go b/internal/user/user.go index 45146a92..ed80773f 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -327,12 +327,25 @@ func (user *User) GetGluonIDs() map[string]string { // GetGluonID returns the gluon ID for the given address, if present. func (user *User) GetGluonID(addrID string) (string, bool) { - gluonID, ok := user.vault.GetGluonIDs()[addrID] - if !ok { + if gluonID, ok := user.vault.GetGluonIDs()[addrID]; ok { + return gluonID, true + } + + if user.vault.AddressMode() != vault.CombinedMode { return "", false } - return gluonID, true + // If there is only one address, return its gluon ID. + // This can happen if we are in combined mode and the primary address ID has changed. + if gluonIDs := maps.Values(user.vault.GetGluonIDs()); len(gluonIDs) == 1 { + if err := user.vault.SetGluonID(addrID, gluonIDs[0]); err != nil { + user.log.WithError(err).Error("Failed to set gluon ID for updated primary address") + } + + return gluonIDs[0], true + } + + return "", false } // SetGluonID sets the gluon ID for the given address. From 29072f0285df5928a89c2f53ed44fe23d7532d83 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Mon, 6 Feb 2023 15:47:11 +0100 Subject: [PATCH 031/130] fix(GODT-2343): Only poll after send if sync is complete --- internal/user/imap.go | 20 ++++++++++++++++++-- internal/user/user.go | 4 +++- 2 files changed, 21 insertions(+), 3 deletions(-) diff --git a/internal/user/imap.go b/internal/user/imap.go index 7fb51981..8be80a4c 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -289,12 +289,28 @@ func (conn *imapConnector) CreateMessage( } else if ok { conn.log.WithField("messageID", messageID).Warn("Message already sent") - message, err := conn.client.GetMessage(ctx, messageID) + // Query the server-side message. + full, err := conn.client.GetFullMessage(ctx, messageID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) if err != nil { return imap.Message{}, nil, fmt.Errorf("failed to fetch message: %w", err) } - return toIMAPMessage(message.MessageMetadata), nil, nil + // Build the message as it is on the server. + if err := safe.RLockRet(func() error { + return withAddrKR(conn.apiUser, conn.apiAddrs[full.AddressID], conn.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error { + var err error + + if literal, err = message.BuildRFC822(addrKR, full.Message, full.AttData, defaultJobOpts()); err != nil { + return err + } + + return nil + }) + }, conn.apiUserLock, conn.apiAddrsLock); err != nil { + return imap.Message{}, nil, fmt.Errorf("failed to build message: %w", err) + } + + return toIMAPMessage(full.MessageMetadata), literal, nil } wantLabelIDs := []string{string(mailboxID)} diff --git a/internal/user/user.go b/internal/user/user.go index ed80773f..350e026b 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -431,7 +431,9 @@ func (user *User) NewIMAPConnectors() (map[string]connector.Connector, error) { // SendMail sends an email from the given address to the given recipients. func (user *User) SendMail(authID string, from string, to []string, r io.Reader) error { - defer user.goPollAPIEvents(true) + if user.vault.SyncStatus().IsComplete() { + defer user.goPollAPIEvents(true) + } if len(to) == 0 { return ErrInvalidRecipient From f3c5e300cd7535d64998262ef38cff17cfa76de1 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Fri, 3 Feb 2023 15:06:27 +0100 Subject: [PATCH 032/130] fix(GODT-2327): Delay event processing until gluon user exists We don't want to start processing events until those events have somewhere to be sent to. Also, to be safe, ensure remove and re-add the gluon user while clearing its sync status. This shouldn't be necessary. fix(GODT-2327): Only start processing events once sync is finished fix(GODT-2327): avoid windows delete all deadlock fix(GODT-2327): Clear update channels whenever clearing sync status fix(GODT-2327): Properly cancel event stream when handling refresh fix(GODT-2327): Remove unnecessary sync abort call fix(GODT-2327): Fix lint issue fix(GODT-2327): Don't retry with abortable context because it's canceled fix(GODT-2327): Loop to retry until sync has complete fix(GODT-2327): Better sleep (with context) --- go.mod | 2 +- go.sum | 4 +- internal/bridge/bridge.go | 2 - internal/bridge/imap.go | 15 ++++ internal/bridge/user.go | 5 +- internal/user/events.go | 11 ++- internal/user/user.go | 150 +++++++++++++++++++++++++------------- 7 files changed, 125 insertions(+), 64 deletions(-) diff --git a/go.mod b/go.mod index bfc85e13..be900dbc 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230206091703-4a3d7a57eeae + github.com/ProtonMail/gluon v0.14.2-0.20230206162331-cf36d870802b github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 8b4c9e27..9df895d5 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230206091703-4a3d7a57eeae h1:iJ0CgJEZTBRGX+vwmMrIg2HEGo3+qBJD/PPcDvYqzQg= -github.com/ProtonMail/gluon v0.14.2-0.20230206091703-4a3d7a57eeae/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230206162331-cf36d870802b h1:v/XwH5Em8gFSpJQErhSCt0XAsIxojFxgrVcfPUEWH7I= +github.com/ProtonMail/gluon v0.14.2-0.20230206162331-cf36d870802b/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index 70cfb590..1a5432cd 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -375,8 +375,6 @@ func (bridge *Bridge) init(tlsReporter TLSReporter) error { // Attempt to load users from the vault when triggered. bridge.goLoad = bridge.tasks.Trigger(func(ctx context.Context) { - logrus.Info("Loading users") - if err := bridge.loadUsers(ctx); err != nil { logrus.WithError(err).Error("Failed to load users") return diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index dc606e0e..37afae0b 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -152,9 +152,22 @@ func (bridge *Bridge) addIMAPUser(ctx context.Context, user *user.User) error { // If the DB was newly created, clear the sync status; gluon's DB was not found. logrus.Warn("IMAP user DB was newly created, clearing sync status") + // Remove the user from IMAP so we can clear the sync status. + if err := bridge.imapServer.RemoveUser(ctx, gluonID, false); err != nil { + return fmt.Errorf("failed to remove IMAP user: %w", err) + } + + // Clear the sync status -- we need to resync all messages. if err := user.ClearSyncStatus(); err != nil { return fmt.Errorf("failed to clear sync status: %w", err) } + + // Add the user back to the IMAP server. + if isNew, err := bridge.imapServer.LoadUser(ctx, imapConn, gluonID, user.GluonKey()); err != nil { + return fmt.Errorf("failed to add IMAP user: %w", err) + } else if isNew { + panic("IMAP user should already have a database") + } } else if status := user.GetSyncStatus(); !status.HasLabels { // Otherwise, the DB already exists -- if the labels are not yet synced, we need to re-create the DB. if err := bridge.imapServer.RemoveUser(ctx, gluonID, true); err != nil { @@ -192,7 +205,9 @@ func (bridge *Bridge) addIMAPUser(ctx context.Context, user *user.User) error { } } + // Trigger a sync for the user, if needed. user.TriggerSync() + return nil } diff --git a/internal/bridge/user.go b/internal/bridge/user.go index 6d355d2a..758fa1f2 100644 --- a/internal/bridge/user.go +++ b/internal/bridge/user.go @@ -330,17 +330,18 @@ func (bridge *Bridge) loginUser(ctx context.Context, client *proton.Client, auth // loadUsers tries to load each user in the vault that isn't already loaded. func (bridge *Bridge) loadUsers(ctx context.Context) error { logrus.WithField("count", len(bridge.vault.GetUserIDs())).Info("Loading users") + defer logrus.Info("Finished loading users") return bridge.vault.ForUser(runtime.NumCPU(), func(user *vault.User) error { log := logrus.WithField("userID", user.UserID()) if user.AuthUID() == "" { - log.Info("Not loading disconnected user") + log.Info("User is not connected (skipping)") return nil } if safe.RLockRet(func() bool { return mapHas(bridge.users, user.UserID()) }, bridge.usersLock) { - log.Debug("Not loading already-loaded user") + log.Info("User is already loaded (skipping)") return nil } diff --git a/internal/user/events.go b/internal/user/events.go index 2b0fc314..03cc0f8e 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -90,8 +90,10 @@ func (user *User) handleRefreshEvent(ctx context.Context, refresh proton.Refresh l.WithError(err).Error("Failed to report refresh to sentry") } - // Cancel and restart ongoing syncs. - user.abortable.Abort() + // Cancel the event stream once this refresh is done. + defer user.pollAbort.Abort() + + // Resync after the refresh. defer user.goSync() return safe.LockRet(func() error { @@ -118,11 +120,8 @@ func (user *User) handleRefreshEvent(ctx context.Context, refresh proton.Refresh user.apiAddrs = groupBy(apiAddrs, func(addr proton.Address) string { return addr.ID }) user.apiLabels = groupBy(apiLabels, func(label proton.Label) string { return label.ID }) - // Reinitialize the update channels. - user.initUpdateCh(user.vault.AddressMode()) - // Clear sync status; we want to sync everything again. - if err := user.vault.ClearSyncStatus(); err != nil { + if err := user.clearSyncStatus(); err != nil { return fmt.Errorf("failed to clear sync status: %w", err) } diff --git a/internal/user/user.go b/internal/user/user.go index 350e026b..824a30e1 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -78,7 +78,8 @@ type User struct { updateChLock safe.RWMutex tasks *async.Group - abortable async.Abortable + syncAbort async.Abortable + pollAbort async.Abortable goSync func() pollAPIEventsCh chan chan struct{} @@ -171,42 +172,6 @@ func New( return nil }) - // Stream events from the API, logging any errors that occur. - // This does nothing until the sync has been marked as complete. - // When we receive an API event, we attempt to handle it. - // If successful, we update the event ID in the vault. - user.tasks.Once(func(ctx context.Context) { - ticker := proton.NewTicker(EventPeriod, EventJitter) - defer ticker.Stop() - - for { - var doneCh chan struct{} - - select { - case <-ctx.Done(): - return - - case doneCh = <-user.pollAPIEventsCh: - // ... - - case <-ticker.C: - // ... - } - - user.log.Debug("Event poll triggered") - - if !user.vault.SyncStatus().IsComplete() { - user.log.Debug("Sync is incomplete, skipping event poll") - } else if err := user.doEventPoll(ctx); err != nil { - user.log.WithError(err).Error("Failed to poll events") - } - - if doneCh != nil { - close(doneCh) - } - } - }) - // When triggered, poll the API for events, optionally blocking until the poll is complete. user.goPollAPIEvents = func(wait bool) { doneCh := make(chan struct{}) @@ -218,18 +183,37 @@ func New( } } - // When triggered, attempt to sync the user. + // When triggered, sync the user and then begin streaming API events. user.goSync = user.tasks.Trigger(func(ctx context.Context) { - user.log.Debug("Sync triggered") + user.log.Info("Sync triggered") - user.abortable.Do(ctx, func(ctx context.Context) { + // Sync the user. + user.syncAbort.Do(ctx, func(ctx context.Context) { if user.vault.SyncStatus().IsComplete() { - user.log.Debug("Sync is already complete, skipping") - } else if err := user.doSync(ctx); err != nil { - user.log.WithError(err).Error("Failed to sync, will retry later") - time.AfterFunc(SyncRetryCooldown, user.goSync) + user.log.Info("Sync already complete, skipping") + return + } + + for { + if err := ctx.Err(); err != nil { + user.log.WithError(err).Error("Sync aborted") + return + } else if err := user.doSync(ctx); err != nil { + user.log.WithError(err).Error("Failed to sync, will retry later") + sleepCtx(ctx, SyncRetryCooldown) + } else { + user.log.Info("Sync complete, starting API event stream") + return + } } }) + + // Once we know the sync has completed, we can start polling for API events. + if user.vault.SyncStatus().IsComplete() { + user.pollAbort.Do(ctx, func(ctx context.Context) { + user.startEvents(ctx) + }) + } }) return user, nil @@ -295,22 +279,21 @@ func (user *User) GetAddressMode() vault.AddressMode { func (user *User) SetAddressMode(_ context.Context, mode vault.AddressMode) error { user.log.WithField("mode", mode).Info("Setting address mode") - user.abortable.Abort() + user.syncAbort.Abort() + user.pollAbort.Abort() defer user.goSync() return safe.LockRet(func() error { - user.initUpdateCh(mode) - if err := user.vault.SetAddressMode(mode); err != nil { return fmt.Errorf("failed to set address mode: %w", err) } - if err := user.vault.ClearSyncStatus(); err != nil { + if err := user.clearSyncStatus(); err != nil { return fmt.Errorf("failed to clear sync status: %w", err) } return nil - }, user.apiAddrsLock, user.updateChLock) + }, user.eventLock, user.apiAddrsLock, user.updateChLock) } // SetShowAllMail sets whether to show the All Mail mailbox. @@ -486,7 +469,8 @@ func (user *User) OnStatusUp(context.Context) { func (user *User) OnStatusDown(context.Context) { user.log.Info("Connection is down") - user.abortable.Abort() + user.syncAbort.Abort() + user.pollAbort.Abort() } // GetSyncStatus returns the sync status of the user. @@ -495,8 +479,30 @@ func (user *User) GetSyncStatus() vault.SyncStatus { } // ClearSyncStatus clears the sync status of the user. +// This also drops any updates in the update channel(s). +// Warning: the gluon user must be removed and re-added if this happens! func (user *User) ClearSyncStatus() error { - return user.vault.ClearSyncStatus() + user.log.Info("Clearing sync status") + + return safe.LockRet(func() error { + return user.clearSyncStatus() + }, user.eventLock, user.apiAddrsLock, user.updateChLock) +} + +// clearSyncStatus clears the sync status of the user. +// This also drops any updates in the update channel(s). +// Warning: the gluon user must be removed and re-added if this happens! +// It is assumed that the eventLock, apiAddrsLock and updateChLock are already locked. +func (user *User) clearSyncStatus() error { + user.log.Info("Clearing sync status") + + user.initUpdateCh(user.vault.AddressMode()) + + if err := user.vault.ClearSyncStatus(); err != nil { + return fmt.Errorf("failed to clear sync status: %w", err) + } + + return nil } // Logout logs the user out from the API. @@ -574,6 +580,40 @@ func (user *User) initUpdateCh(mode vault.AddressMode) { } } +// startEvents streams events from the API, logging any errors that occur. +// This does nothing until the sync has been marked as complete. +// When we receive an API event, we attempt to handle it. +// If successful, we update the event ID in the vault. +func (user *User) startEvents(ctx context.Context) { + ticker := proton.NewTicker(EventPeriod, EventJitter) + defer ticker.Stop() + + for { + var doneCh chan struct{} + + select { + case <-ctx.Done(): + return + + case doneCh = <-user.pollAPIEventsCh: + // ... + + case <-ticker.C: + // ... + } + + user.log.Debug("Event poll triggered") + + if err := user.doEventPoll(ctx); err != nil { + user.log.WithError(err).Error("Failed to poll events") + } + + if doneCh != nil { + close(doneCh) + } + } +} + // doEventPoll is called whenever API events should be polled. func (user *User) doEventPoll(ctx context.Context) error { user.eventLock.Lock() @@ -643,3 +683,11 @@ func b32(b bool) uint32 { return 0 } + +// sleepCtx sleeps for the given duration, or until the context is canceled. +func sleepCtx(ctx context.Context, d time.Duration) { + select { + case <-ctx.Done(): + case <-time.After(d): + } +} From c6576dfc4b222fb75cdc95165aea2f309b6ec684 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 7 Feb 2023 17:53:53 +0100 Subject: [PATCH 033/130] fix(GODT-2327): Remove unnecessary sync when changing address mode --- internal/user/user.go | 1 - 1 file changed, 1 deletion(-) diff --git a/internal/user/user.go b/internal/user/user.go index 824a30e1..a5cffba6 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -281,7 +281,6 @@ func (user *User) SetAddressMode(_ context.Context, mode vault.AddressMode) erro user.syncAbort.Abort() user.pollAbort.Abort() - defer user.goSync() return safe.LockRet(func() error { if err := user.vault.SetAddressMode(mode); err != nil { From 31dce412769cf2f9a2de387bba904e5feb8f949f Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 7 Feb 2023 15:36:13 +0100 Subject: [PATCH 034/130] test: Fix race condition with initialization of messageIDs Need to make sure the messageIDs slice is created properly before it is used async in a different goroutine. --- internal/bridge/user_event_test.go | 14 +++++--------- internal/user/events.go | 4 +--- 2 files changed, 6 insertions(+), 12 deletions(-) diff --git a/internal/bridge/user_event_test.go b/internal/bridge/user_event_test.go index 4bac18ea..e8d06d31 100644 --- a/internal/bridge/user_event_test.go +++ b/internal/bridge/user_event_test.go @@ -113,12 +113,13 @@ func TestBridge_User_BadMessage_NoBadEvent(t *testing.T) { var messageIDs []string + // Create 10 more messages for the user, generating events. + withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { + messageIDs = createNumMessages(ctx, t, c, addrID, proton.InboxLabel, 10) + }) + // If bridge attempts to sync the new messages, it should get a BadRequest error. s.AddStatusHook(func(req *http.Request) (int, bool) { - if len(messageIDs) < 3 { - return 0, false - } - if strings.Contains(req.URL.Path, "/mail/v4/messages/"+messageIDs[2]) { return http.StatusUnprocessableEntity, true } @@ -126,11 +127,6 @@ func TestBridge_User_BadMessage_NoBadEvent(t *testing.T) { return 0, false }) - // Create 10 more messages for the user, generating events. - withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { - messageIDs = createNumMessages(ctx, t, c, addrID, proton.InboxLabel, 10) - }) - // Remove messages withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { require.NoError(t, c.DeleteMessage(ctx, messageIDs...)) diff --git a/internal/user/events.go b/internal/user/events.go index 03cc0f8e..1c88864e 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -420,9 +420,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto switch event.Action { case proton.EventCreate: - updates, err := user.handleCreateMessageEvent( - logging.WithLogrusField(ctx, "action", "create message"), - event) + updates, err := user.handleCreateMessageEvent(logging.WithLogrusField(ctx, "action", "create message"), event) if err != nil { if rerr := user.reporter.ReportMessageWithContext("Failed to apply create message event", reporter.Context{ "error": err, From c9d496956ce1250d4475d99f8f9ec5f0432b32ee Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 7 Feb 2023 17:32:44 +0100 Subject: [PATCH 035/130] test: Refactor account management, fix map-random-order race condition Some SMTP tests made use of disabled addresses. We stored addresses in a map, meaning the order was randomized. This lead to tests sometimes attempting to authenticate over SMTP using a disabled address, failing. --- tests/bridge_test.go | 14 +-- tests/ctx_helper_test.go | 4 +- tests/ctx_test.go | 161 ++++++++++++++++++------------ tests/features/user/login.feature | 4 +- tests/imap_test.go | 26 ++--- tests/smtp_test.go | 18 ++-- tests/user_test.go | 55 +++++----- 7 files changed, 154 insertions(+), 128 deletions(-) diff --git a/tests/bridge_test.go b/tests/bridge_test.go index 9e57773a..45f6e67a 100644 --- a/tests/bridge_test.go +++ b/tests/bridge_test.go @@ -68,10 +68,10 @@ func (s *scenario) theUserChangesTheSMTPPortTo(port int) error { func (s *scenario) theUserSetsTheAddressModeOfUserTo(user, mode string) error { switch mode { case "split": - return s.t.bridge.SetAddressMode(context.Background(), s.t.getUserID(user), vault.SplitMode) + return s.t.bridge.SetAddressMode(context.Background(), s.t.getUserByName(user).getUserID(), vault.SplitMode) case "combined": - return s.t.bridge.SetAddressMode(context.Background(), s.t.getUserID(user), vault.CombinedMode) + return s.t.bridge.SetAddressMode(context.Background(), s.t.getUserByName(user).getUserID(), vault.CombinedMode) default: return fmt.Errorf("unknown address mode %q", mode) @@ -156,7 +156,7 @@ func (s *scenario) bridgeSendsADeauthEventForUser(username string) error { return errors.New("expected deauth event, got none") } - if wantUserID := s.t.getUserID(username); event.UserID != wantUserID { + if wantUserID := s.t.getUserByName(username).getUserID(); event.UserID != wantUserID { return fmt.Errorf("expected deauth event for user %s, got %s", wantUserID, event.UserID) } @@ -169,7 +169,7 @@ func (s *scenario) bridgeSendsAnAddressCreatedEventForUser(username string) erro return errors.New("expected address created event, got none") } - if wantUserID := s.t.getUserID(username); event.UserID != wantUserID { + if wantUserID := s.t.getUserByName(username).getUserID(); event.UserID != wantUserID { return fmt.Errorf("expected address created event for user %s, got %s", wantUserID, event.UserID) } @@ -182,7 +182,7 @@ func (s *scenario) bridgeSendsAnAddressDeletedEventForUser(username string) erro return errors.New("expected address deleted event, got none") } - if wantUserID := s.t.getUserID(username); event.UserID != wantUserID { + if wantUserID := s.t.getUserByName(username).getUserID(); event.UserID != wantUserID { return fmt.Errorf("expected address deleted event for user %s, got %s", wantUserID, event.UserID) } @@ -195,7 +195,7 @@ func (s *scenario) bridgeSendsSyncStartedAndFinishedEventsForUser(username strin return errors.New("expected sync started event, got none") } - if wantUserID := s.t.getUserID(username); startEvent.UserID != wantUserID { + if wantUserID := s.t.getUserByName(username).getUserID(); startEvent.UserID != wantUserID { return fmt.Errorf("expected sync started event for user %s, got %s", wantUserID, startEvent.UserID) } @@ -204,7 +204,7 @@ func (s *scenario) bridgeSendsSyncStartedAndFinishedEventsForUser(username strin return errors.New("expected sync finished event, got none") } - if wantUserID := s.t.getUserID(username); finishEvent.UserID != wantUserID { + if wantUserID := s.t.getUserByName(username).getUserID(); finishEvent.UserID != wantUserID { return fmt.Errorf("expected sync finished event for user %s, got %s", wantUserID, finishEvent.UserID) } diff --git a/tests/ctx_helper_test.go b/tests/ctx_helper_test.go index 4bf0103c..3c803b5e 100644 --- a/tests/ctx_helper_test.go +++ b/tests/ctx_helper_test.go @@ -43,7 +43,7 @@ func (t *testCtx) withProton(fn func(*proton.Manager) error) error { // withClient executes the given function with a client that is logged in as the given (known) user. func (t *testCtx) withClient(ctx context.Context, username string, fn func(context.Context, *proton.Client) error) error { - return t.withClientPass(ctx, username, t.getUserPass(t.getUserID(username)), fn) + return t.withClientPass(ctx, username, t.getUserByName(username).getUserPass(), fn) } // withClient executes the given function with a client that is logged in with the given username and password. @@ -108,7 +108,7 @@ func (t *testCtx) withAddrKR( return err } - keyPass, err := salt.SaltForKey([]byte(t.getUserPass(t.getUserID(username))), user.Keys.Primary().ID) + keyPass, err := salt.SaltForKey([]byte(t.getUserByName(username).getUserPass()), user.Keys.Primary().ID) if err != nil { return err } diff --git a/tests/ctx_test.go b/tests/ctx_test.go index 0c9db06c..2089ea89 100644 --- a/tests/ctx_test.go +++ b/tests/ctx_test.go @@ -40,12 +40,85 @@ import ( "github.com/emersion/go-imap/client" "github.com/google/uuid" "github.com/sirupsen/logrus" - "golang.org/x/exp/maps" "google.golang.org/grpc" ) var defaultVersion = semver.MustParse("3.0.6") +type testUser struct { + name string // the test user name + userID string // the user's account ID + addresses []*testAddr // the user's addresses + userPass string // the user's account password + bridgePass string // the user's bridge password +} + +func newTestUser(userID, name, userPass string) *testUser { + return &testUser{ + userID: userID, + name: name, + userPass: userPass, + } +} + +func (user *testUser) getName() string { + return user.name +} + +func (user *testUser) getUserID() string { + return user.userID +} + +func (user *testUser) getEmails() []string { + return xslices.Map(user.addresses, func(addr *testAddr) string { + return addr.email + }) +} + +func (user *testUser) getAddrID(email string) string { + for _, addr := range user.addresses { + if addr.email == email { + return addr.addrID + } + } + + panic(fmt.Sprintf("unknown email %q", email)) +} + +func (user *testUser) addAddress(addrID, email string) { + user.addresses = append(user.addresses, newTestAddr(addrID, email)) +} + +func (user *testUser) remAddress(addrID string) { + user.addresses = xslices.Filter(user.addresses, func(addr *testAddr) bool { + return addr.addrID != addrID + }) +} + +func (user *testUser) getUserPass() string { + return user.userPass +} + +func (user *testUser) getBridgePass() string { + return user.bridgePass +} + +func (user *testUser) setBridgePass(pass string) { + user.bridgePass = pass +} + +type testAddr struct { + addrID string // the remote address ID + email string // the test address email +} + +func newTestAddr(addrID, email string) *testAddr { + return &testAddr{ + addrID: addrID, + email: email, + } +} + type testCtx struct { // These are the objects supporting the test. dir string @@ -70,13 +143,11 @@ type testCtx struct { clientConn *grpc.ClientConn clientEventCh *queue.QueuedChannel[*frontend.StreamEvent] - // These maps hold expected userIDByName, their primary addresses and bridge passwords. - userUUIDByName map[string]string - addrUUIDByName map[string]string - userIDByName map[string]string - userAddrByEmail map[string]map[string]string - userPassByID map[string]string - userBridgePassByID map[string][]byte + // These maps hold test objects created during the test. + userByID map[string]*testUser + userUUIDByName map[string]string + addrByID map[string]*testAddr + addrUUIDByName map[string]string // These are the IMAP and SMTP clients used to connect to bridge. imapClients map[string]*imapClient @@ -115,12 +186,10 @@ func newTestCtx(tb testing.TB) *testCtx { events: newEventCollector(), reporter: newReportRecorder(tb), - userUUIDByName: make(map[string]string), - addrUUIDByName: make(map[string]string), - userIDByName: make(map[string]string), - userAddrByEmail: make(map[string]map[string]string), - userPassByID: make(map[string]string), - userBridgePassByID: make(map[string][]byte), + userByID: make(map[string]*testUser), + userUUIDByName: make(map[string]string), + addrByID: make(map[string]*testAddr), + addrUUIDByName: make(map[string]string), imapClients: make(map[string]*imapClient), smtpClients: make(map[string]*smtpClient), @@ -192,62 +261,22 @@ func (t *testCtx) afterStep(st *godog.Step, status godog.StepResultStatus) { logrus.Debugf("Finished step (%v): %s", status, st.Text) } -func (t *testCtx) getName(wantUserID string) string { - for name, userID := range t.userIDByName { - if userID == wantUserID { - return name +func (t *testCtx) addUser(userID, name, userPass string) { + t.userByID[userID] = newTestUser(userID, name, userPass) +} + +func (t *testCtx) getUserByName(name string) *testUser { + for _, user := range t.userByID { + if user.name == name { + return user } } - panic(fmt.Sprintf("unknown user ID %q", wantUserID)) + panic(fmt.Sprintf("user %q not found", name)) } -func (t *testCtx) getUserID(username string) string { - return t.userIDByName[username] -} - -func (t *testCtx) setUserID(username, userID string) { - t.userIDByName[username] = userID -} - -func (t *testCtx) getUserAddrID(userID, email string) string { - return t.userAddrByEmail[userID][email] -} - -func (t *testCtx) getUserAddrs(userID string) []string { - return maps.Keys(t.userAddrByEmail[userID]) -} - -func (t *testCtx) setUserAddr(userID, addrID, email string) { - if _, ok := t.userAddrByEmail[userID]; !ok { - t.userAddrByEmail[userID] = make(map[string]string) - } - - t.userAddrByEmail[userID][email] = addrID -} - -func (t *testCtx) unsetUserAddr(userID, wantAddrID string) { - for email, addrID := range t.userAddrByEmail[userID] { - if addrID == wantAddrID { - delete(t.userAddrByEmail[userID], email) - } - } -} - -func (t *testCtx) getUserPass(userID string) string { - return t.userPassByID[userID] -} - -func (t *testCtx) setUserPass(userID, pass string) { - t.userPassByID[userID] = pass -} - -func (t *testCtx) getUserBridgePass(userID string) string { - return string(t.userBridgePassByID[userID]) -} - -func (t *testCtx) setUserBridgePass(userID string, pass []byte) { - t.userBridgePassByID[userID] = pass +func (t *testCtx) getUserByID(userID string) *testUser { + return t.userByID[userID] } func (t *testCtx) getMBoxID(userID string, name string) string { @@ -256,7 +285,7 @@ func (t *testCtx) getMBoxID(userID string, name string) string { var labelID string - if err := t.withClient(ctx, t.getName(userID), func(ctx context.Context, client *proton.Client) error { + if err := t.withClient(ctx, t.getUserByID(userID).getName(), func(ctx context.Context, client *proton.Client) error { labels, err := client.GetLabels(ctx, proton.LabelTypeLabel, proton.LabelTypeFolder, proton.LabelTypeSystem) if err != nil { panic(err) diff --git a/tests/features/user/login.feature b/tests/features/user/login.feature index 385a7984..3edfdb79 100644 --- a/tests/features/user/login.feature +++ b/tests/features/user/login.feature @@ -14,8 +14,8 @@ Feature: A user can login Then user "[user:user]" is not listed Scenario: Login to nonexistent account - When the user logs in with username "[user:other]" and password "unknown" - Then user "[user:other]" is not listed + When the user logs in with username "nonexistent" and password "unknown" + Then user "nonexistent" is not listed Scenario: Login to account without internet Given the internet is turned off diff --git a/tests/imap_test.go b/tests/imap_test.go index 2f2cf448..8cae5707 100644 --- a/tests/imap_test.go +++ b/tests/imap_test.go @@ -38,35 +38,35 @@ import ( ) func (s *scenario) userConnectsIMAPClient(username, clientID string) error { - return s.t.newIMAPClient(s.t.getUserID(username), clientID) + return s.t.newIMAPClient(s.t.getUserByName(username).getUserID(), clientID) } func (s *scenario) userConnectsIMAPClientOnPort(username, clientID string, port int) error { - return s.t.newIMAPClientOnPort(s.t.getUserID(username), clientID, port) + return s.t.newIMAPClientOnPort(s.t.getUserByName(username).getUserID(), clientID, port) } func (s *scenario) userConnectsAndAuthenticatesIMAPClient(username, clientID string) error { - return s.userConnectsAndAuthenticatesIMAPClientWithAddress(username, clientID, s.t.getUserAddrs(s.t.getUserID(username))[0]) + return s.userConnectsAndAuthenticatesIMAPClientWithAddress(username, clientID, s.t.getUserByName(username).getEmails()[0]) } func (s *scenario) userConnectsAndAuthenticatesIMAPClientWithAddress(username, clientID, address string) error { - if err := s.t.newIMAPClient(s.t.getUserID(username), clientID); err != nil { + if err := s.t.newIMAPClient(s.t.getUserByName(username).getUserID(), clientID); err != nil { return err } userID, client := s.t.getIMAPClient(clientID) - return client.Login(address, s.t.getUserBridgePass(userID)) + return client.Login(address, s.t.getUserByID(userID).getBridgePass()) } func (s *scenario) userConnectsAndCanNotAuthenticateIMAPClientWithAddress(username, clientID, address string) error { - if err := s.t.newIMAPClient(s.t.getUserID(username), clientID); err != nil { + if err := s.t.newIMAPClient(s.t.getUserByName(username).getUserID(), clientID); err != nil { return err } userID, client := s.t.getIMAPClient(clientID) - if err := client.Login(address, s.t.getUserBridgePass(userID)); err == nil { + if err := client.Login(address, s.t.getUserByID(userID).getBridgePass()); err == nil { return fmt.Errorf("expected error, got nil") } @@ -76,19 +76,19 @@ func (s *scenario) userConnectsAndCanNotAuthenticateIMAPClientWithAddress(userna func (s *scenario) imapClientCanAuthenticate(clientID string) error { userID, client := s.t.getIMAPClient(clientID) - return client.Login(s.t.getUserAddrs(userID)[0], s.t.getUserBridgePass(userID)) + return client.Login(s.t.getUserByID(userID).getEmails()[0], s.t.getUserByID(userID).getBridgePass()) } func (s *scenario) imapClientCanAuthenticateWithAddress(clientID string, address string) error { userID, client := s.t.getIMAPClient(clientID) - return client.Login(address, s.t.getUserBridgePass(userID)) + return client.Login(address, s.t.getUserByID(userID).getBridgePass()) } func (s *scenario) imapClientCannotAuthenticate(clientID string) error { userID, client := s.t.getIMAPClient(clientID) - if err := client.Login(s.t.getUserAddrs(userID)[0], s.t.getUserBridgePass(userID)); err == nil { + if err := client.Login(s.t.getUserByID(userID).getEmails()[0], s.t.getUserByID(userID).getBridgePass()); err == nil { return fmt.Errorf("expected error, got nil") } @@ -98,7 +98,7 @@ func (s *scenario) imapClientCannotAuthenticate(clientID string) error { func (s *scenario) imapClientCannotAuthenticateWithAddress(clientID, address string) error { userID, client := s.t.getIMAPClient(clientID) - if err := client.Login(address, s.t.getUserBridgePass(userID)); err == nil { + if err := client.Login(address, s.t.getUserByID(userID).getBridgePass()); err == nil { return fmt.Errorf("expected error, got nil") } @@ -108,7 +108,7 @@ func (s *scenario) imapClientCannotAuthenticateWithAddress(clientID, address str func (s *scenario) imapClientCannotAuthenticateWithIncorrectUsername(clientID string) error { userID, client := s.t.getIMAPClient(clientID) - if err := client.Login(s.t.getUserAddrs(userID)[0]+"bad", s.t.getUserBridgePass(userID)); err == nil { + if err := client.Login(s.t.getUserByID(userID).getEmails()[0]+"bad", s.t.getUserByID(userID).getBridgePass()); err == nil { return fmt.Errorf("expected error, got nil") } @@ -118,7 +118,7 @@ func (s *scenario) imapClientCannotAuthenticateWithIncorrectUsername(clientID st func (s *scenario) imapClientCannotAuthenticateWithIncorrectPassword(clientID string) error { userID, client := s.t.getIMAPClient(clientID) - if err := client.Login(s.t.getUserAddrs(userID)[0], s.t.getUserBridgePass(userID)+"bad"); err == nil { + if err := client.Login(s.t.getUserByID(userID).getEmails()[0], s.t.getUserByID(userID).getBridgePass()+"bad"); err == nil { return fmt.Errorf("expected error, got nil") } diff --git a/tests/smtp_test.go b/tests/smtp_test.go index 26c1fe29..430b83af 100644 --- a/tests/smtp_test.go +++ b/tests/smtp_test.go @@ -27,25 +27,25 @@ import ( ) func (s *scenario) userConnectsSMTPClient(username, clientID string) error { - return s.t.newSMTPClient(s.t.getUserID(username), clientID) + return s.t.newSMTPClient(s.t.getUserByName(username).getUserID(), clientID) } func (s *scenario) userConnectsSMTPClientOnPort(username, clientID string, port int) error { - return s.t.newSMTPClientOnPort(s.t.getUserID(username), clientID, port) + return s.t.newSMTPClientOnPort(s.t.getUserByName(username).getUserID(), clientID, port) } func (s *scenario) userConnectsAndAuthenticatesSMTPClient(username, clientID string) error { - return s.userConnectsAndAuthenticatesSMTPClientWithAddress(username, clientID, s.t.getUserAddrs(s.t.getUserID(username))[0]) + return s.userConnectsAndAuthenticatesSMTPClientWithAddress(username, clientID, s.t.getUserByName(username).getEmails()[0]) } func (s *scenario) userConnectsAndAuthenticatesSMTPClientWithAddress(username, clientID, address string) error { - if err := s.t.newSMTPClient(s.t.getUserID(username), clientID); err != nil { + if err := s.t.newSMTPClient(s.t.getUserByName(username).getUserID(), clientID); err != nil { return err } userID, client := s.t.getSMTPClient(clientID) - s.t.pushError(client.Auth(smtp.PlainAuth("", address, s.t.getUserBridgePass(userID), constants.Host))) + s.t.pushError(client.Auth(smtp.PlainAuth("", address, s.t.getUserByID(userID).getBridgePass(), constants.Host))) return nil } @@ -53,7 +53,7 @@ func (s *scenario) userConnectsAndAuthenticatesSMTPClientWithAddress(username, c func (s *scenario) smtpClientCanAuthenticate(clientID string) error { userID, client := s.t.getSMTPClient(clientID) - if err := client.Auth(smtp.PlainAuth("", s.t.getUserAddrs(userID)[0], s.t.getUserBridgePass(userID), constants.Host)); err != nil { + if err := client.Auth(smtp.PlainAuth("", s.t.getUserByID(userID).getEmails()[0], s.t.getUserByID(userID).getBridgePass(), constants.Host)); err != nil { return fmt.Errorf("expected no error, got %v", err) } @@ -63,7 +63,7 @@ func (s *scenario) smtpClientCanAuthenticate(clientID string) error { func (s *scenario) smtpClientCannotAuthenticate(clientID string) error { userID, client := s.t.getSMTPClient(clientID) - if err := client.Auth(smtp.PlainAuth("", s.t.getUserAddrs(userID)[0], s.t.getUserBridgePass(userID), constants.Host)); err == nil { + if err := client.Auth(smtp.PlainAuth("", s.t.getUserByID(userID).getEmails()[0], s.t.getUserByID(userID).getBridgePass(), constants.Host)); err == nil { return fmt.Errorf("expected error, got nil") } @@ -73,7 +73,7 @@ func (s *scenario) smtpClientCannotAuthenticate(clientID string) error { func (s *scenario) smtpClientCannotAuthenticateWithIncorrectUsername(clientID string) error { userID, client := s.t.getSMTPClient(clientID) - if err := client.Auth(smtp.PlainAuth("", s.t.getUserAddrs(userID)[0]+"bad", s.t.getUserBridgePass(userID), constants.Host)); err == nil { + if err := client.Auth(smtp.PlainAuth("", s.t.getUserByID(userID).getEmails()[0]+"bad", s.t.getUserByID(userID).getBridgePass(), constants.Host)); err == nil { return fmt.Errorf("expected error, got nil") } @@ -83,7 +83,7 @@ func (s *scenario) smtpClientCannotAuthenticateWithIncorrectUsername(clientID st func (s *scenario) smtpClientCannotAuthenticateWithIncorrectPassword(clientID string) error { userID, client := s.t.getSMTPClient(clientID) - if err := client.Auth(smtp.PlainAuth("", s.t.getUserAddrs(userID)[0], s.t.getUserBridgePass(userID)+"bad", constants.Host)); err == nil { + if err := client.Auth(smtp.PlainAuth("", s.t.getUserByID(userID).getEmails()[0], s.t.getUserByID(userID).getBridgePass()+"bad", constants.Host)); err == nil { return fmt.Errorf("expected error, got nil") } diff --git a/tests/user_test.go b/tests/user_test.go index 044d52f4..989a914c 100644 --- a/tests/user_test.go +++ b/tests/user_test.go @@ -32,7 +32,6 @@ import ( "github.com/bradenaw/juniper/xslices" "github.com/cucumber/godog" "github.com/google/uuid" - "golang.org/x/exp/slices" ) func (s *scenario) thereExistsAnAccountWithUsernameAndPassword(username, password string) error { @@ -52,7 +51,7 @@ func (s *scenario) theAccountHasAdditionalDisabledAddress(username, address stri } func (s *scenario) theAccountHasAdditionalAddressWithoutKeys(username, address string) error { - userID := s.t.getUserID(username) + userID := s.t.getUserByName(username).getUserID() // Decrypt the user's encrypted ID for use with quark. userDecID, err := s.t.runQuarkCmd(context.Background(), "encryption:id", "--decrypt", userID) @@ -65,7 +64,8 @@ func (s *scenario) theAccountHasAdditionalAddressWithoutKeys(username, address s context.Background(), "user:create:address", string(userDecID), - s.t.getUserPass(userID), + s.t.getUserByID(userID).getUserPass(), + address, ); err != nil { return err @@ -78,15 +78,15 @@ func (s *scenario) theAccountHasAdditionalAddressWithoutKeys(username, address s } // Set the new address of the user. - s.t.setUserAddr(userID, addr[len(addr)-1].ID, address) + s.t.getUserByID(userID).addAddress(addr[len(addr)-1].ID, address) return nil }) } func (s *scenario) theAccountNoLongerHasAdditionalAddress(username, address string) error { - userID := s.t.getUserID(username) - addrID := s.t.getUserAddrID(userID, address) + userID := s.t.getUserByName(username).getUserID() + addrID := s.t.getUserByName(username).getAddrID(address) if err := s.t.withClient(context.Background(), username, func(ctx context.Context, c *proton.Client) error { if err := c.DisableAddress(ctx, addrID); err != nil { @@ -98,7 +98,7 @@ func (s *scenario) theAccountNoLongerHasAdditionalAddress(username, address stri return err } - s.t.unsetUserAddr(userID, addrID) + s.t.getUserByID(userID).remAddress(addrID) return nil } @@ -184,8 +184,8 @@ func (s *scenario) theAddressOfAccountHasTheFollowingMessagesInMailbox(address, ctx, cancel := context.WithCancel(context.Background()) defer cancel() - userID := s.t.getUserID(username) - addrID := s.t.getUserAddrID(userID, address) + userID := s.t.getUserByName(username).getUserID() + addrID := s.t.getUserByName(username).getAddrID(address) mboxID := s.t.getMBoxID(userID, mailbox) wantMessages, err := unmarshalTable[Message](table) @@ -219,8 +219,8 @@ func (s *scenario) theAddressOfAccountHasMessagesInMailbox(address, username str ctx, cancel := context.WithCancel(context.Background()) defer cancel() - userID := s.t.getUserID(username) - addrID := s.t.getUserAddrID(userID, address) + userID := s.t.getUserByName(username).getUserID() + addrID := s.t.getUserByName(username).getAddrID(address) mboxID := s.t.getMBoxID(userID, mailbox) return s.t.createMessages(ctx, username, addrID, iterator.Collect(iterator.Map(iterator.Counter(count), func(idx int) proton.ImportReq { @@ -262,7 +262,7 @@ func (s *scenario) theFollowingFieldsWereChangedInDraftForAddressOfAccount(draft defer cancel() return s.t.withClient(ctx, username, func(ctx context.Context, c *proton.Client) error { - return s.t.withAddrKR(ctx, c, username, s.t.getUserAddrID(s.t.getUserID(username), address), func(_ context.Context, addrKR *crypto.KeyRing) error { + return s.t.withAddrKR(ctx, c, username, s.t.getUserByName(username).getAddrID(address), func(_ context.Context, addrKR *crypto.KeyRing) error { var changes proton.DraftTemplate if wantMessages[0].From != "" { @@ -311,7 +311,7 @@ func (s *scenario) drafAtIndexWasMovedToTrashForAddressOfAccount(draftIndex int, defer cancel() return s.t.withClient(ctx, username, func(ctx context.Context, c *proton.Client) error { - return s.t.withAddrKR(ctx, c, username, s.t.getUserAddrID(s.t.getUserID(username), address), func(_ context.Context, addrKR *crypto.KeyRing) error { + return s.t.withAddrKR(ctx, c, username, s.t.getUserByName(username).getAddrID(address), func(_ context.Context, addrKR *crypto.KeyRing) error { if err := c.UnlabelMessages(ctx, []string{draftID}, proton.DraftsLabel); err != nil { return fmt.Errorf("failed to unlabel draft") } @@ -329,7 +329,7 @@ func (s *scenario) userLogsInWithUsernameAndPassword(username, password string) if err != nil { s.t.pushError(err) } else { - if userID != s.t.getUserID(username) { + if userID != s.t.getUserByName(username).getUserID() { return errors.New("user ID mismatch") } @@ -338,18 +338,18 @@ func (s *scenario) userLogsInWithUsernameAndPassword(username, password string) return err } - s.t.setUserBridgePass(userID, info.BridgePass) + s.t.getUserByID(userID).setBridgePass(string(info.BridgePass)) } return nil } func (s *scenario) userLogsOut(username string) error { - return s.t.bridge.LogoutUser(context.Background(), s.t.getUserID(username)) + return s.t.bridge.LogoutUser(context.Background(), s.t.getUserByName(username).getUserID()) } func (s *scenario) userIsDeleted(username string) error { - return s.t.bridge.DeleteUser(context.Background(), s.t.getUserID(username)) + return s.t.bridge.DeleteUser(context.Background(), s.t.getUserByName(username).getUserID()) } func (s *scenario) theAuthOfUserIsRevoked(username string) error { @@ -359,7 +359,7 @@ func (s *scenario) theAuthOfUserIsRevoked(username string) error { } func (s *scenario) userIsListedAndConnected(username string) error { - user, err := s.t.bridge.GetUserInfo(s.t.getUserID(username)) + user, err := s.t.bridge.GetUserInfo(s.t.getUserByName(username).getUserID()) if err != nil { return err } @@ -382,7 +382,7 @@ func (s *scenario) userIsEventuallyListedAndConnected(username string) error { } func (s *scenario) userIsListedButNotConnected(username string) error { - user, err := s.t.bridge.GetUserInfo(s.t.getUserID(username)) + user, err := s.t.bridge.GetUserInfo(s.t.getUserByName(username).getUserID()) if err != nil { return err } @@ -399,7 +399,7 @@ func (s *scenario) userIsListedButNotConnected(username string) error { } func (s *scenario) userIsNotListed(username string) error { - if slices.Contains(s.t.bridge.GetUserIDs(), s.t.getUserID(username)) { + if _, err := s.t.bridge.QueryUserInfo(username); !errors.Is(err, bridge.ErrNoSuchUser) { return errors.New("user listed") } @@ -411,7 +411,7 @@ func (s *scenario) userFinishesSyncing(username string) error { } func (s *scenario) addAdditionalAddressToAccount(username, address string, disabled bool) error { - userID := s.t.getUserID(username) + userID := s.t.getUserByName(username).getUserID() // Decrypt the user's encrypted ID for use with quark. userDecID, err := s.t.runQuarkCmd(context.Background(), "encryption:id", "--decrypt", userID) @@ -429,7 +429,7 @@ func (s *scenario) addAdditionalAddressToAccount(username, address string, disab args = append(args, string(userDecID), - s.t.getUserPass(userID), + s.t.getUserByID(userID).getUserPass(), address, ) @@ -449,7 +449,7 @@ func (s *scenario) addAdditionalAddressToAccount(username, address string, disab } // Set the new address of the user. - s.t.setUserAddr(userID, addr[len(addr)-1].ID, address) + s.t.getUserByID(userID).addAddress(addr[len(addr)-1].ID, address) return nil }) @@ -503,14 +503,11 @@ func (s *scenario) createUserAccount(username, password string, disabled bool) e return err } - // Set the ID of the user. - s.t.setUserID(username, user.ID) - - // Set the password of the user. - s.t.setUserPass(user.ID, password) + // Add the test user. + s.t.addUser(user.ID, username, password) // Set the address of the user. - s.t.setUserAddr(user.ID, addr[0].ID, addr[0].Email) + s.t.getUserByID(user.ID).addAddress(addr[0].ID, addr[0].Email) return nil }) From a79fce907e555469f83f6bfb4a630b38058cfc2e Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 7 Feb 2023 16:02:51 +0100 Subject: [PATCH 036/130] test: Bump GPA to fix flaky test TestBridge_User_BadMessage_NoBadEvent It was necessary to return an actual proton.APIError json object in order for our detection to work properly in one of the tests. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index be900dbc..fa2a2b88 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/gluon v0.14.2-0.20230206162331-cf36d870802b github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b + github.com/ProtonMail/go-proton-api v0.3.1-0.20230207140717-7eee7f487b13 github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.4.10 github.com/PuerkitoBio/goquery v1.8.0 diff --git a/go.sum b/go.sum index 9df895d5..553ce168 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b h1:3UX0j2WA3NsqmrjTK769sCIOX2KnISfo8tZdFl7+mRE= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230203120457-1849bf7d578b/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230207140717-7eee7f487b13 h1:VmLI4lVyYGJPQXAWaZXxvu0coEooVzqdTU185cq8ULo= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230207140717-7eee7f487b13/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= From c4ef1a24c0ef58adf29beb9bce3c2a41545b07db Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 7 Feb 2023 15:35:45 +0100 Subject: [PATCH 037/130] fix(GODT-2347): Prevent updates from being dropped if goroutine doesn't start fast If the install handler goroutine is busy, the update is dropped. This was intended to prevent two installs from happening at once. However, it also means that updates can be dropped at startup if the goroutine isn't spawned soon enough. A fix is to allow all jobs through and just reject ones that are for an old version. --- internal/bridge/updates.go | 33 +++++++++------------------------ 1 file changed, 9 insertions(+), 24 deletions(-) diff --git a/internal/bridge/updates.go b/internal/bridge/updates.go index 9b0ea252..4208ce5c 100644 --- a/internal/bridge/updates.go +++ b/internal/bridge/updates.go @@ -32,19 +32,7 @@ func (bridge *Bridge) CheckForUpdates() { } func (bridge *Bridge) InstallUpdate(version updater.VersionInfo) { - log := logrus.WithFields(logrus.Fields{ - "version": version.Version, - "current": bridge.curVersion, - "channel": bridge.vault.GetUpdateChannel(), - }) - - select { - case bridge.installCh <- installJob{version: version, silent: false}: - log.Info("The update will be installed manually") - - default: - log.Info("An update is already being installed") - } + bridge.installCh <- installJob{version: version, silent: false} } func (bridge *Bridge) handleUpdate(version updater.VersionInfo) { @@ -89,17 +77,7 @@ func (bridge *Bridge) handleUpdate(version updater.VersionInfo) { default: safe.RLock(func() { - if version.Version.GreaterThan(bridge.newVersion) { - log.Info("An update is available") - - select { - case bridge.installCh <- installJob{version: version, silent: true}: - log.Info("The update will be installed silently") - - default: - log.Info("An update is already being installed") - } - } + bridge.installCh <- installJob{version: version, silent: true} }, bridge.newVersionLock) } } @@ -117,6 +95,12 @@ func (bridge *Bridge) installUpdate(ctx context.Context, job installJob) { "channel": bridge.vault.GetUpdateChannel(), }) + if !job.version.Version.GreaterThan(bridge.newVersion) { + return + } + + log.WithField("silent", job.silent).Info("An update is available") + bridge.publish(events.UpdateAvailable{ Version: job.version, Compatible: true, @@ -142,6 +126,7 @@ func (bridge *Bridge) installUpdate(ctx context.Context, job installJob) { Silent: job.silent, Error: err, }) + default: log.Info("The update was installed successfully") From 1c88ce3cc0e5d81c33e31321623aee6fc366bce2 Mon Sep 17 00:00:00 2001 From: Romain Le Jeune Date: Wed, 8 Feb 2023 10:06:53 +0000 Subject: [PATCH 038/130] feat(GODT-2255): Randomize the focus service port. --- README.md | 29 ++++----- internal/app/app.go | 13 ++-- internal/app/singleinstance.go | 4 +- internal/bridge/bridge.go | 2 +- internal/bridge/bridge_test.go | 5 +- internal/focus/client.go | 19 ++++-- internal/focus/focus_test.go | 60 +++++++++++++++++-- internal/focus/service.go | 37 ++++++++---- .../frontend/bridge-gui/bridge-gui/main.cpp | 16 ++++- .../bridgepp/FocusGRPC/FocusGRPCClient.cpp | 35 ++++++++++- .../bridgepp/FocusGRPC/FocusGRPCClient.h | 5 +- internal/frontend/grpc/service.go | 18 ++---- internal/frontend/grpc/service_methods.go | 5 +- internal/frontend/grpc/types.go | 4 -- internal/{frontend/grpc => service}/config.go | 19 +++++- .../{frontend/grpc => service}/config_test.go | 6 +- internal/service/types.go | 22 +++++++ tests/ctx_bridge_test.go | 3 +- 18 files changed, 226 insertions(+), 76 deletions(-) rename internal/{frontend/grpc => service}/config.go (79%) rename internal/{frontend/grpc => service}/config_test.go (93%) create mode 100644 internal/service/types.go diff --git a/README.md b/README.md index 60f890ed..0fd5c853 100644 --- a/README.md +++ b/README.md @@ -67,25 +67,26 @@ There are now three types of system folders which Bridge recognises: |--------|-------------------------------------|-----------------------------------------------------|-------------------------------------|---------------------------------------| | config | %APPDATA%\protonmail\bridge-v3 | ~/Library/Application Support/protonmail/bridge-v3 | ~/.config/protonmail/bridge-v3 | $XDG_CONFIG_HOME/protonmail/bridge-v3 | | cache | %LOCALAPPDATA%\protonmail\bridge-v3 | ~/Library/Caches/protonmail/bridge-v3 | ~/.cache/protonmail/bridge-v3 | $XDG_CACHE_HOME/protonmail/bridge-v3 | -| data | %APPDATA%\protonmail\bridge-v3 | ~/Library/Application Support/protonmail/bridge-v3 | ~/.local/share/protonmail/bridge-v3 | $XDG_DATA_HOME/protonmail/bridge-v3 | +| data | %APPDATA%\protonmail\bridge-v3 | ~/Library/Application Support/protonmail/bridge-v3 | ~/.local/share/protonmail/bridge-v3 | $XDG_DATA_HOME/protonmail/bridge-v3 | | temp | %LOCALAPPDATA%\Temp | $TMPDIR if non-empty, else /tmp | $TMPDIR if non-empty, else /tmp | $TMPDIR if non-empty, else /tmp | ## Files -| | Base Dir | Path | -|-----------------------|----------|----------------------------| -| bridge lock file | cache | bridge.lock | -| bridge-gui lock file | cache | bridge-gui.lock | -| vault | config | vault.enc | -| gRPC server json | config | grpcServerConfig.json | -| gRPC client json | config | grpcClientConfig_.json | -| Logs | data | logs | -| gluon DB | data | gluon/backend/db | -| gluon messages | data | gluon/backend/store | -| Update files | data | updates | -| sentry cache | data | sentry_cache | -| Mac/Linux File Socket | temp | bridge{4_DIGITS} | +| | Base Dir | Path | +|------------------------|----------|----------------------------| +| bridge lock file | cache | bridge.lock | +| bridge-gui lock file | cache | bridge-gui.lock | +| vault | config | vault.enc | +| gRPC server json | config | grpcServerConfig.json | +| gRPC client json | config | grpcClientConfig_.json | +| gRPC Focus server json | config | grpcFocusServerConfig.json | +| Logs | data | logs | +| gluon DB | data | gluon/backend/db | +| gluon messages | data | gluon/backend/store | +| Update files | data | updates | +| sentry cache | data | sentry_cache | +| Mac/Linux File Socket | temp | bridge{4_DIGITS} | diff --git a/internal/app/app.go b/internal/app/app.go index 3167456f..3a259a26 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -208,7 +208,12 @@ func run(c *cli.Context) error { } // Ensure we are the only instance running. - return withSingleInstance(locations, version, func() error { + settings, err := locations.ProvideSettingsPath() + if err != nil { + logrus.WithError(err).Error("Failed to get settings path") + } + + return withSingleInstance(settings, locations.GetLockFile(), version, func() error { // Unlock the encrypted vault. return WithVault(locations, func(v *vault.Vault, insecure, corrupt bool) error { // Report insecure vault. @@ -278,15 +283,15 @@ func run(c *cli.Context) error { } // If there's another instance already running, try to raise it and exit. -func withSingleInstance(locations *locations.Locations, version *semver.Version, fn func() error) error { +func withSingleInstance(settingPath, lockFile string, version *semver.Version, fn func() error) error { logrus.Debug("Checking for other instances") defer logrus.Debug("Single instance stopped") - lock, err := checkSingleInstance(locations.GetLockFile(), version) + lock, err := checkSingleInstance(settingPath, lockFile, version) if err != nil { logrus.Info("Another instance is already running; raising it") - if ok := focus.TryRaise(); !ok { + if ok := focus.TryRaise(settingPath); !ok { return fmt.Errorf("another instance is already running but it could not be raised") } diff --git a/internal/app/singleinstance.go b/internal/app/singleinstance.go index da9ce775..4e6b6dc7 100644 --- a/internal/app/singleinstance.go +++ b/internal/app/singleinstance.go @@ -34,7 +34,7 @@ import ( // // For macOS and Linux when already running version is older than this instance // it will kill old and continue with this new bridge (i.e. no error returned). -func checkSingleInstance(lockFilePath string, curVersion *semver.Version) (*os.File, error) { +func checkSingleInstance(settingPath, lockFilePath string, curVersion *semver.Version) (*os.File, error) { if lock, err := singleinstance.CreateLockFile(lockFilePath); err == nil { logrus.WithField("path", lockFilePath).Debug("Created lock file; no other instance is running") return lock, nil @@ -44,7 +44,7 @@ func checkSingleInstance(lockFilePath string, curVersion *semver.Version) (*os.F // We couldn't create the lock file, so another instance is probably running. // Check if it's an older version of the app. - lastVersion, ok := focus.TryVersion() + lastVersion, ok := focus.TryVersion(settingPath) if !ok { return nil, fmt.Errorf("failed to determine version of running instance") } diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index 1a5432cd..75b3b428 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -251,7 +251,7 @@ func newBridge( return nil, fmt.Errorf("failed to create IMAP server: %w", err) } - focusService, err := focus.NewService(curVersion) + focusService, err := focus.NewService(locator, curVersion) if err != nil { return nil, fmt.Errorf("failed to create focus service: %w", err) } diff --git a/internal/bridge/bridge_test.go b/internal/bridge/bridge_test.go index c3406628..ec4f5b83 100644 --- a/internal/bridge/bridge_test.go +++ b/internal/bridge/bridge_test.go @@ -123,8 +123,11 @@ func TestBridge_Focus(t *testing.T) { raiseCh, done := bridge.GetEvents(events.Raise{}) defer done() + settingsFolder, err := locator.ProvideSettingsPath() + require.NoError(t, err) + // Simulate a focus event. - focus.TryRaise() + focus.TryRaise(settingsFolder) // Wait for the event. require.IsType(t, events.Raise{}, <-raiseCh) diff --git a/internal/focus/client.go b/internal/focus/client.go index 0c5d8834..773c2e9e 100644 --- a/internal/focus/client.go +++ b/internal/focus/client.go @@ -21,9 +21,11 @@ import ( "context" "fmt" "net" + "path/filepath" "github.com/Masterminds/semver/v3" "github.com/ProtonMail/proton-bridge/v3/internal/focus/proto" + "github.com/ProtonMail/proton-bridge/v3/internal/service" "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/grpc/credentials/insecure" @@ -32,10 +34,10 @@ import ( // TryRaise tries to raise the application by dialing the focus service. // It returns true if the service is running and the application was told to raise. -func TryRaise() bool { +func TryRaise(settingsPath string) bool { var raised bool - if err := withClientConn(context.Background(), func(ctx context.Context, client proto.FocusClient) error { + if err := withClientConn(context.Background(), settingsPath, func(ctx context.Context, client proto.FocusClient) error { if _, err := client.Raise(ctx, &emptypb.Empty{}); err != nil { return fmt.Errorf("failed to call client.Raise: %w", err) } @@ -53,10 +55,10 @@ func TryRaise() bool { // TryVersion tries to determine the version of the running application instance. // It returns the version and true if the version could be determined. -func TryVersion() (*semver.Version, bool) { +func TryVersion(settingsPath string) (*semver.Version, bool) { var version *semver.Version - if err := withClientConn(context.Background(), func(ctx context.Context, client proto.FocusClient) error { + if err := withClientConn(context.Background(), settingsPath, func(ctx context.Context, client proto.FocusClient) error { raw, err := client.Version(ctx, &emptypb.Empty{}) if err != nil { return fmt.Errorf("failed to call client.Version: %w", err) @@ -78,10 +80,15 @@ func TryVersion() (*semver.Version, bool) { return version, true } -func withClientConn(ctx context.Context, fn func(context.Context, proto.FocusClient) error) error { +func withClientConn(ctx context.Context, settingsPath string, fn func(context.Context, proto.FocusClient) error) error { + var config = service.Config{} + err := config.Load(filepath.Join(settingsPath, serverConfigFileName)) + if err != nil { + return err + } cc, err := grpc.DialContext( ctx, - net.JoinHostPort(Host, fmt.Sprint(Port)), + net.JoinHostPort(Host, fmt.Sprint(config.Port)), grpc.WithTransportCredentials(insecure.NewCredentials()), ) if err != nil { diff --git a/internal/focus/focus_test.go b/internal/focus/focus_test.go index b6dd359b..059d243d 100644 --- a/internal/focus/focus_test.go +++ b/internal/focus/focus_test.go @@ -18,19 +18,25 @@ package focus import ( + "os" "testing" "github.com/Masterminds/semver/v3" + "github.com/ProtonMail/proton-bridge/v3/internal/locations" "github.com/stretchr/testify/require" ) func TestFocus_Raise(t *testing.T) { + tmpDir := t.TempDir() + locations := locations.New(newTestLocationsProvider(tmpDir), "config-name") // Start the focus service. - service, err := NewService(semver.MustParse("1.2.3")) + service, err := NewService(locations, semver.MustParse("1.2.3")) require.NoError(t, err) + settingsFolder, err := locations.ProvideSettingsPath() + require.NoError(t, err) // Try to dial it, it should succeed. - require.True(t, TryRaise()) + require.True(t, TryRaise(settingsFolder)) // The service should report a raise call. <-service.GetRaiseCh() @@ -39,16 +45,60 @@ func TestFocus_Raise(t *testing.T) { service.Close() // Try to dial it, it should fail. - require.False(t, TryRaise()) + require.False(t, TryRaise(settingsFolder)) } func TestFocus_Version(t *testing.T) { + tmpDir := t.TempDir() + locations := locations.New(newTestLocationsProvider(tmpDir), "config-name") // Start the focus service. - _, err := NewService(semver.MustParse("1.2.3")) + _, err := NewService(locations, semver.MustParse("1.2.3")) + require.NoError(t, err) + + settingsFolder, err := locations.ProvideSettingsPath() require.NoError(t, err) // Try to dial it, it should succeed. - version, ok := TryVersion() + version, ok := TryVersion(settingsFolder) require.True(t, ok) require.Equal(t, "1.2.3", version.String()) } + +type TestLocationsProvider struct { + config, data, cache string +} + +func newTestLocationsProvider(dir string) *TestLocationsProvider { + config, err := os.MkdirTemp(dir, "config") + if err != nil { + panic(err) + } + + data, err := os.MkdirTemp(dir, "data") + if err != nil { + panic(err) + } + + cache, err := os.MkdirTemp(dir, "cache") + if err != nil { + panic(err) + } + + return &TestLocationsProvider{ + config: config, + data: data, + cache: cache, + } +} + +func (provider *TestLocationsProvider) UserConfig() string { + return provider.config +} + +func (provider *TestLocationsProvider) UserData() string { + return provider.data +} + +func (provider *TestLocationsProvider) UserCache() string { + return provider.cache +} diff --git a/internal/focus/service.go b/internal/focus/service.go index a7728dfb..ab2d0127 100644 --- a/internal/focus/service.go +++ b/internal/focus/service.go @@ -25,16 +25,16 @@ import ( "github.com/Masterminds/semver/v3" "github.com/ProtonMail/proton-bridge/v3/internal/focus/proto" + "github.com/ProtonMail/proton-bridge/v3/internal/service" "github.com/sirupsen/logrus" "google.golang.org/grpc" "google.golang.org/protobuf/types/known/emptypb" ) -// Host is the local host to listen on. -const Host = "127.0.0.1" - -// Port is the port to listen on. -var Port = 1042 // nolint:gochecknoglobals +const ( + Host = "127.0.0.1" + serverConfigFileName = "grpcFocusServerConfig.json" +) // Service is a gRPC service that can be used to raise the application. type Service struct { @@ -47,26 +47,39 @@ type Service struct { // NewService creates a new focus service. // It listens on the local host and port 1042 (by default). -func NewService(version *semver.Version) (*Service, error) { - service := &Service{ +func NewService(locator service.Locator, version *semver.Version) (*Service, error) { + serv := &Service{ server: grpc.NewServer(), raiseCh: make(chan struct{}, 1), version: version, } - proto.RegisterFocusServer(service.server, service) + proto.RegisterFocusServer(serv.server, serv) - if listener, err := net.Listen("tcp", net.JoinHostPort(Host, fmt.Sprint(Port))); err != nil { - logrus.WithError(err).Warn("Failed to start focus service") + if listener, err := net.Listen("tcp", net.JoinHostPort(Host, fmt.Sprint(0))); err != nil { + logrus.WithError(err).Warn("Failed to start focus serv") } else { + config := service.Config{} + // retrieve the port assigned by the system, so that we can put it in the config file. + address, ok := listener.Addr().(*net.TCPAddr) + if !ok { + return nil, fmt.Errorf("could not retrieve gRPC service listener address") + } + config.Port = address.Port + if path, err := service.SaveGRPCServerConfigFile(locator, &config, serverConfigFileName); err != nil { + logrus.WithError(err).WithField("path", path).Warn("Could not write focus gRPC service config file") + } else { + logrus.WithField("path", path).Info("Successfully saved gRPC Focus service config file") + } + go func() { - if err := service.server.Serve(listener); err != nil { + if err := serv.server.Serve(listener); err != nil { fmt.Printf("failed to serve: %v", err) } }() } - return service, nil + return serv, nil } // Raise implements the gRPC FocusService interface; it raises the application. diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 7e2f89c7..b71a1606 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -229,8 +229,21 @@ bool isBridgeRunning() { void focusOtherInstance() { try { FocusGRPCClient client; + GRPCConfig sc; + QString const path = FocusGRPCClient::grpcFocusServerConfigPath(); + QFile file(path); + if (file.exists()) { + if (!sc.load(path)) { + throw Exception("The gRPC focus service configuration file is invalid."); + } + } + else { + throw Exception("Server did not provide gRPC Focus service configuration."); + } + + QString error; - if (!client.connectToServer(5000, &error)) { + if (!client.connectToServer(5000, sc.port, &error)) { throw Exception(QString("Could not connect to bridge focus service for a raise call: %1").arg(error)); } if (!client.raise().ok()) { @@ -344,6 +357,7 @@ int main(int argc, char *argv[]) { } // before launching bridge, we remove any trailing service config file, because we need to make sure we get a newly generated one. + FocusGRPCClient::removeServiceConfigFile(); GRPCClient::removeServiceConfigFile(); launchBridge(cliOptions.bridgeArgs); } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.cpp index ca1e751e..3f9be02f 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.cpp @@ -17,6 +17,7 @@ #include "FocusGRPCClient.h" +#include "../BridgeUtils.h" #include "../Exception/Exception.h" @@ -29,7 +30,6 @@ namespace { Empty empty; ///< Empty protobuf message, re-used across calls. -qint64 const port = 1042; ///< The port for the focus service. QString const hostname = "127.0.0.1"; ///< The hostname of the focus service. @@ -39,12 +39,43 @@ QString const hostname = "127.0.0.1"; ///< The hostname of the focus service. namespace bridgepp { +//**************************************************************************************************************************************************** +/// \return the gRPC Focus server config file name +//**************************************************************************************************************************************************** +QString grpcFocusServerConfigFilename() { + return "grpcFocusServerConfig.json"; +} + + +//**************************************************************************************************************************************************** +/// \return The absolute path of the focus service config path. +//**************************************************************************************************************************************************** +QString FocusGRPCClient::grpcFocusServerConfigPath() { + return QDir(userConfigDir()).absoluteFilePath(grpcFocusServerConfigFilename()); +} + + +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +void FocusGRPCClient::removeServiceConfigFile() { + QString const path = grpcFocusServerConfigPath(); + if (!QFile(path).exists()) { + return; + } + if (!QFile().remove(path)) { + throw Exception("Could not remove gRPC focus service config file."); + } +} + + //**************************************************************************************************************************************************** /// \param[in] timeoutMs The timeout for the connexion. +/// \param[in] port The gRPC server port. /// \param[out] outError if not null and the function returns false. /// \return true iff the connexion was successfully established. //**************************************************************************************************************************************************** -bool FocusGRPCClient::connectToServer(qint64 timeoutMs, QString *outError) { +bool FocusGRPCClient::connectToServer(qint64 timeoutMs, quint16 port, QString *outError) { try { QString const address = QString("%1:%2").arg(hostname).arg(port); channel_ = grpc::CreateChannel(address.toStdString(), grpc::InsecureChannelCredentials()); diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.h index 6b6bd9e8..2c597fac 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.h @@ -31,6 +31,9 @@ namespace bridgepp { /// \brief Focus GRPC client class //********************************************************************************************************************** class FocusGRPCClient { +public: // static member functions + static void removeServiceConfigFile(); ///< Delete the service config file. + static QString grpcFocusServerConfigPath(); ///< Return the path of the gRPC Focus server config file. public: // member functions. FocusGRPCClient() = default; ///< Default constructor. FocusGRPCClient(FocusGRPCClient const &) = delete; ///< Disabled copy-constructor. @@ -38,7 +41,7 @@ public: // member functions. ~FocusGRPCClient() = default; ///< Destructor. FocusGRPCClient &operator=(FocusGRPCClient const &) = delete; ///< Disabled assignment operator. FocusGRPCClient &operator=(FocusGRPCClient &&) = delete; ///< Disabled move assignment operator. - bool connectToServer(qint64 timeoutMs, QString *outError = nullptr); ///< Connect to the focus server + bool connectToServer(qint64 timeoutMs, quint16 port, QString *outError = nullptr); ///< Connect to the focus server grpc::Status raise(); ///< Performs the 'raise' call. grpc::Status version(QString &outVersion); ///< Performs the 'version' call. diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index 9c429378..732ef823 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -38,6 +38,7 @@ import ( "github.com/ProtonMail/proton-bridge/v3/internal/certs" "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/safe" + "github.com/ProtonMail/proton-bridge/v3/internal/service" "github.com/ProtonMail/proton-bridge/v3/internal/updater" "github.com/bradenaw/juniper/xslices" "github.com/elastic/go-sysinfo" @@ -97,7 +98,7 @@ type Service struct { // nolint:structcheck func NewService( panicHandler CrashHandler, restarter Restarter, - locations Locator, + locations service.Locator, bridge *bridge.Bridge, eventCh <-chan events.Event, quitCh <-chan struct{}, @@ -109,7 +110,7 @@ func NewService( logrus.WithError(err).Panic("Could not generate gRPC TLS config") } - config := Config{ + config := service.Config{ Cert: string(certPEM), Token: uuid.NewString(), } @@ -140,7 +141,7 @@ func NewService( config.Port = address.Port } - if path, err := saveGRPCServerConfigFile(locations, &config); err != nil { + if path, err := service.SaveGRPCServerConfigFile(locations, &config, serverConfigFileName); err != nil { logrus.WithError(err).WithField("path", path).Panic("Could not write gRPC service config file") } else { logrus.WithField("path", path).Info("Successfully saved gRPC service config file") @@ -486,17 +487,6 @@ func newTLSConfig() (*tls.Config, []byte, error) { }, certPEM, nil } -func saveGRPCServerConfigFile(locations Locator, config *Config) (string, error) { - settingsPath, err := locations.ProvideSettingsPath() - if err != nil { - return "", err - } - - configPath := filepath.Join(settingsPath, serverConfigFileName) - - return configPath, config.save(configPath) -} - // validateServerToken verify that the server token provided by the client is valid. func validateServerToken(ctx context.Context, wantToken string) error { values, ok := metadata.FromIncomingContext(ctx) diff --git a/internal/frontend/grpc/service_methods.go b/internal/frontend/grpc/service_methods.go index 749c09f7..8d71c67c 100644 --- a/internal/frontend/grpc/service_methods.go +++ b/internal/frontend/grpc/service_methods.go @@ -32,6 +32,7 @@ import ( "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/frontend/theme" "github.com/ProtonMail/proton-bridge/v3/internal/safe" + "github.com/ProtonMail/proton-bridge/v3/internal/service" "github.com/ProtonMail/proton-bridge/v3/internal/updater" "github.com/ProtonMail/proton-bridge/v3/pkg/keychain" "github.com/ProtonMail/proton-bridge/v3/pkg/ports" @@ -51,8 +52,8 @@ func (s *Service) CheckTokens(ctx context.Context, clientConfigPath *wrapperspb. path := clientConfigPath.Value logEntry := s.log.WithField("path", path) - var clientConfig Config - if err := clientConfig.load(path); err != nil { + var clientConfig service.Config + if err := clientConfig.Load(path); err != nil { logEntry.WithError(err).Error("Could not read gRPC client config file") return nil, err diff --git a/internal/frontend/grpc/types.go b/internal/frontend/grpc/types.go index 72aa819d..f92f8b3b 100644 --- a/internal/frontend/grpc/types.go +++ b/internal/frontend/grpc/types.go @@ -26,7 +26,3 @@ type Restarter interface { AddFlags(flags ...string) Override(exe string) } - -type Locator interface { - ProvideSettingsPath() (string, error) -} diff --git a/internal/frontend/grpc/config.go b/internal/service/config.go similarity index 79% rename from internal/frontend/grpc/config.go rename to internal/service/config.go index 03842e63..7392b1ba 100644 --- a/internal/frontend/grpc/config.go +++ b/internal/service/config.go @@ -15,11 +15,12 @@ // You should have received a copy of the GNU General Public License // along with Proton Mail Bridge. If not, see . -package grpc +package service import ( "encoding/json" "os" + "path/filepath" ) // Config is a structure containing the service configuration data that are exchanged by the gRPC server and client. @@ -53,8 +54,8 @@ func (s *Config) _save(path string) error { return json.NewEncoder(f).Encode(s) } -// load loads a gRPC service configuration from file. -func (s *Config) load(path string) error { +// Load loads a gRPC service configuration from file. +func (s *Config) Load(path string) error { f, err := os.Open(path) //nolint:errcheck,gosec if err != nil { return err @@ -64,3 +65,15 @@ func (s *Config) load(path string) error { return json.NewDecoder(f).Decode(s) } + +// SaveGRPCServerConfigFile save GRPC configuration file. +func SaveGRPCServerConfigFile(locations Locator, config *Config, filename string) (string, error) { + settingsPath, err := locations.ProvideSettingsPath() + if err != nil { + return "", err + } + + configPath := filepath.Join(settingsPath, filename) + + return configPath, config.save(configPath) +} diff --git a/internal/frontend/grpc/config_test.go b/internal/service/config_test.go similarity index 93% rename from internal/frontend/grpc/config_test.go rename to internal/service/config_test.go index 432c74ba..ecc3a4e4 100644 --- a/internal/frontend/grpc/config_test.go +++ b/internal/service/config_test.go @@ -15,7 +15,7 @@ // You should have received a copy of the GNU General Public License // along with Proton Mail Bridge. If not, see . -package grpc +package service import ( "path/filepath" @@ -46,11 +46,11 @@ func TestConfig(t *testing.T) { require.NoError(t, conf1.save(tempFilePath)) conf2 := Config{} - require.NoError(t, conf2.load(tempFilePath)) + require.NoError(t, conf2.Load(tempFilePath)) require.Equal(t, conf1, conf2) // failure to load - require.Error(t, conf2.load(tempFilePath+"_")) + require.Error(t, conf2.Load(tempFilePath+"_")) // failure to save require.Error(t, conf2.save(filepath.Join(tempDir, "non/existing/folder", tempFileName))) diff --git a/internal/service/types.go b/internal/service/types.go new file mode 100644 index 00000000..faa77624 --- /dev/null +++ b/internal/service/types.go @@ -0,0 +1,22 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge.Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + +package service + +type Locator interface { + ProvideSettingsPath() (string, error) +} diff --git a/tests/ctx_bridge_test.go b/tests/ctx_bridge_test.go index 3d7a75bd..cb0a2446 100644 --- a/tests/ctx_bridge_test.go +++ b/tests/ctx_bridge_test.go @@ -36,6 +36,7 @@ import ( "github.com/ProtonMail/proton-bridge/v3/internal/cookies" "github.com/ProtonMail/proton-bridge/v3/internal/events" frontend "github.com/ProtonMail/proton-bridge/v3/internal/frontend/grpc" + "github.com/ProtonMail/proton-bridge/v3/internal/service" "github.com/ProtonMail/proton-bridge/v3/internal/useragent" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/sirupsen/logrus" @@ -262,7 +263,7 @@ func (t *testCtx) initFrontendClient() error { return fmt.Errorf("could not read grpcServerConfig.json: %w", err) } - var cfg frontend.Config + var cfg service.Config if err := json.Unmarshal(b, &cfg); err != nil { return fmt.Errorf("could not unmarshal grpcServerConfig.json: %w", err) From d1f1c390f626f1b3111ceb398e71235156463cf1 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 7 Feb 2023 13:02:43 +0100 Subject: [PATCH 039/130] test: Bump test timeout from 5m to 10m --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 18881bfc..0ee97f5f 100644 --- a/Makefile +++ b/Makefile @@ -222,7 +222,7 @@ change-copyright-year: ./utils/missing_license.sh change-year test: gofiles - go test -v -timeout=5m -p=1 -count=1 -coverprofile=/tmp/coverage.out -run=${TESTRUN} ./internal/... ./pkg/... + go test -v -timeout=10m -p=1 -count=1 -coverprofile=/tmp/coverage.out -run=${TESTRUN} ./internal/... ./pkg/... test-race: gofiles go test -v -timeout=30m -p=1 -count=1 -race -failfast -run=${TESTRUN} ./internal/... ./pkg/... From a740a8f962f67fb62492bdb0be6b7fdc9ab31069 Mon Sep 17 00:00:00 2001 From: Romain LE JEUNE Date: Wed, 8 Feb 2023 15:13:15 +0100 Subject: [PATCH 040/130] feat(GODT-2278): properly override server_name for go. --- internal/sentry/reporter.go | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/internal/sentry/reporter.go b/internal/sentry/reporter.go index f9697f00..33456d56 100644 --- a/internal/sentry/reporter.go +++ b/internal/sentry/reporter.go @@ -43,6 +43,7 @@ func init() { //nolint:gochecknoinits Release: constants.Revision, BeforeSend: EnhanceSentryEvent, Transport: sentrySyncTransport, + ServerName: getProtectedHostname(), }); err != nil { logrus.WithError(err).Error("Failed to initialize sentry options") } @@ -63,7 +64,6 @@ type Reporter struct { appVersion string identifier Identifier hostArch string - serverName string } type Identifier interface { @@ -85,7 +85,6 @@ func NewReporter(appName, appVersion string, identifier Identifier) *Reporter { appVersion: appVersion, identifier: identifier, hostArch: getHostArch(), - serverName: getProtectedHostname(), } } @@ -137,12 +136,11 @@ func (r *Reporter) scopedReport(context map[string]interface{}, doReport func()) } tags := map[string]string{ - "OS": runtime.GOOS, - "Client": r.appName, - "Version": r.appVersion, - "UserAgent": r.identifier.GetUserAgent(), - "HostArch": r.hostArch, - "server_name": r.serverName, + "OS": runtime.GOOS, + "Client": r.appName, + "Version": r.appVersion, + "UserAgent": r.identifier.GetUserAgent(), + "HostArch": r.hostArch, } sentry.WithScope(func(scope *sentry.Scope) { From cdff2ef79214b60f6e7208e6c82ef27f025ef936 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Wed, 8 Feb 2023 16:09:24 +0100 Subject: [PATCH 041/130] fix(GODT-2351): Bump GPA to properly handle net.OpError and add tests --- go.mod | 2 +- go.sum | 4 +-- internal/bridge/user.go | 1 + internal/bridge/user_event_test.go | 58 ++++++++++++++++++++++++++++++ internal/bridge/user_test.go | 46 ++++++++++++++++++++++++ 5 files changed, 108 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fa2a2b88..f8a5cf6d 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/gluon v0.14.2-0.20230206162331-cf36d870802b github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.3.1-0.20230207140717-7eee7f487b13 + github.com/ProtonMail/go-proton-api v0.3.1-0.20230208134215-f345f51a344b github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.4.10 github.com/PuerkitoBio/goquery v1.8.0 diff --git a/go.sum b/go.sum index 553ce168..ef6a6f6b 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230207140717-7eee7f487b13 h1:VmLI4lVyYGJPQXAWaZXxvu0coEooVzqdTU185cq8ULo= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230207140717-7eee7f487b13/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230208134215-f345f51a344b h1:fHDSfYQ0/zmfRBGDyhNOXtoIDVaL8elarYaiJAGgtj8= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230208134215-f345f51a344b/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= diff --git a/internal/bridge/user.go b/internal/bridge/user.go index 758fa1f2..6aed8503 100644 --- a/internal/bridge/user.go +++ b/internal/bridge/user.go @@ -380,6 +380,7 @@ func (bridge *Bridge) loadUser(ctx context.Context, user *vault.User) error { logrus.WithError(err).Warn("Failed to clear user secrets") } } + return fmt.Errorf("failed to create API client: %w", err) } diff --git a/internal/bridge/user_event_test.go b/internal/bridge/user_event_test.go index e8d06d31..e7a02a28 100644 --- a/internal/bridge/user_event_test.go +++ b/internal/bridge/user_event_test.go @@ -20,6 +20,7 @@ package bridge_test import ( "context" "fmt" + "net" "net/http" "strings" "sync/atomic" @@ -291,6 +292,63 @@ func TestBridge_User_Network_NoBadEvents(t *testing.T) { }) } +func TestBridge_User_DropConn_NoBadEvent(t *testing.T) { + l, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + + dropListener := proton.NewListener(l, proton.NewDropConn) + defer func() { _ = dropListener.Close() }() + + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + // Create a user. + _, addrID, err := s.CreateUser("user", password) + require.NoError(t, err) + + // Create 10 messages for the user. + withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { + createNumMessages(ctx, t, c, addrID, proton.InboxLabel, 10) + }) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + userLoginAndSync(ctx, t, bridge, "user", password) + + mocks.Reporter.EXPECT().ReportMessageWithContext(gomock.Any(), gomock.Any()).AnyTimes() + + // Create 10 more messages for the user, generating events. + withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { + createNumMessages(ctx, t, c, addrID, proton.InboxLabel, 10) + }) + + var count int + + // The first 10 times bridge attempts to sync any of the messages, drop the connection. + s.AddStatusHook(func(req *http.Request) (int, bool) { + if strings.Contains(req.URL.Path, "/mail/v4/messages") { + if count++; count < 10 { + dropListener.DropAll() + } + } + + return 0, false + }) + + info, err := bridge.QueryUserInfo("user") + require.NoError(t, err) + + client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort())) + require.NoError(t, err) + require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) + defer func() { _ = client.Logout() }() + + // The IMAP client will eventually see 20 messages. + require.Eventually(t, func() bool { + status, err := client.Status("INBOX", []imap.StatusItem{imap.StatusMessages}) + return err == nil && status.Messages == 20 + }, 10*time.Second, 100*time.Millisecond) + }) + }, server.WithListener(dropListener)) +} + // userLoginAndSync logs in user and waits until user is fully synced. func userLoginAndSync( ctx context.Context, diff --git a/internal/bridge/user_test.go b/internal/bridge/user_test.go index 4c70f3a9..417e7bd7 100644 --- a/internal/bridge/user_test.go +++ b/internal/bridge/user_test.go @@ -20,6 +20,8 @@ package bridge_test import ( "context" "fmt" + "net" + "net/http" "testing" "time" @@ -61,6 +63,50 @@ func TestBridge_Login(t *testing.T) { }) } +func TestBridge_Login_DropConn(t *testing.T) { + l, err := net.Listen("tcp", "127.0.0.1:0") + require.NoError(t, err) + + dropListener := proton.NewListener(l, proton.NewDropConn) + defer func() { _ = dropListener.Close() }() + + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + // Login the user. + userID, err := bridge.LoginFull(ctx, username, password, nil, nil) + require.NoError(t, err) + + // The user is now connected. + require.Equal(t, []string{userID}, bridge.GetUserIDs()) + require.Equal(t, []string{userID}, getConnectedUserIDs(t, bridge)) + }) + + // Whether to allow the user to be created. + var allowUser bool + + s.AddStatusHook(func(req *http.Request) (int, bool) { + // Drop any request to the users endpoint. + if !allowUser && req.URL.Path == "/core/v4/users" { + dropListener.DropAll() + } + + // After the ping request, allow the user to be created. + if req.URL.Path == "/tests/ping" { + allowUser = true + } + + return 0, false + }) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + // The user is eventually connected. + require.Eventually(t, func() bool { + return len(bridge.GetUserIDs()) == 1 && len(getConnectedUserIDs(t, bridge)) == 1 + }, 5*time.Second, 100*time.Millisecond) + }) + }, server.WithListener(dropListener)) +} + func TestBridge_LoginTwice(t *testing.T) { withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { From 2b75fcf7731fbcef3e6524076ae0353c92a54ff7 Mon Sep 17 00:00:00 2001 From: Romain Le Jeune Date: Thu, 9 Feb 2023 10:44:18 +0000 Subject: [PATCH 042/130] feat(GODT-2352): use go-build-finalize macro to build vault-editor for both mac arch --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 0ee97f5f..795cf8b0 100644 --- a/Makefile +++ b/Makefile @@ -112,7 +112,7 @@ versioner: go build ${BUILD_FLAGS} -o versioner utils/versioner/main.go vault-editor: - go build -tags debug -o vault-editor utils/vault-editor/main.go + $(call go-build-finalize,"-tags=debug","vault-editor","./utils/vault-editor/main.go") hasher: go build -o hasher utils/hasher/main.go From afa95d479959234512ab990200f2954c96c7d646 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Thu, 9 Feb 2023 12:36:44 +0100 Subject: [PATCH 043/130] fix(GODT-2351): Bump GPA to automatically retry on net.OpError --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f8a5cf6d..cf7bbd2b 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/gluon v0.14.2-0.20230206162331-cf36d870802b github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.3.1-0.20230208134215-f345f51a344b + github.com/ProtonMail/go-proton-api v0.3.1-0.20230209105544-b185be77ce15 github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.4.10 github.com/PuerkitoBio/goquery v1.8.0 diff --git a/go.sum b/go.sum index ef6a6f6b..3b64f79c 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230208134215-f345f51a344b h1:fHDSfYQ0/zmfRBGDyhNOXtoIDVaL8elarYaiJAGgtj8= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230208134215-f345f51a344b/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230209105544-b185be77ce15 h1:OiyETrhilrJGS4WXqKXdTO7LnzaDb00/4F3W4JqICrM= +github.com/ProtonMail/go-proton-api v0.3.1-0.20230209105544-b185be77ce15/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= From 5f930c262c482659f91aaf03f256400d3d418c56 Mon Sep 17 00:00:00 2001 From: Romain LE JEUNE Date: Thu, 9 Feb 2023 13:01:27 +0100 Subject: [PATCH 044/130] feat(GODT-2352): only copy resource file when needed. --- Makefile | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 795cf8b0..8d490b6e 100644 --- a/Makefile +++ b/Makefile @@ -96,9 +96,9 @@ endif ifeq "${GOOS}" "windows" go-build-finalize= \ - powershell Copy-Item ${ROOT_DIR}/${RESOURCE_FILE} ${4} && \ - $(call go-build,$(1),$(2),$(3)) && \ - powershell Remove-Item ${4} -Force + $(if $(4),powershell Copy-Item ${ROOT_DIR}/${RESOURCE_FILE} ${4} &&,) \ + $(call go-build,$(1),$(2),$(3)) \ + $(if $(4), && powershell Remove-Item ${4} -Force,) endif ${EXE_NAME}: gofiles ${RESOURCE_FILE} From 8b9265ad96acb398185de5395793671e364ea988 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Thu, 9 Feb 2023 16:24:40 +0100 Subject: [PATCH 045/130] feat(GODT-2283): Limit max import size to 30MB (bump GPA to v0.4.0) --- go.mod | 2 +- go.sum | 4 ++-- internal/bridge/sync_test.go | 7 +++++-- internal/user/imap.go | 9 +++++++-- tests/ctx_helper_test.go | 11 ++++++++--- 5 files changed, 23 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index cf7bbd2b..d46e2155 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/gluon v0.14.2-0.20230206162331-cf36d870802b github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.3.1-0.20230209105544-b185be77ce15 + github.com/ProtonMail/go-proton-api v0.4.0 github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.4.10 github.com/PuerkitoBio/goquery v1.8.0 diff --git a/go.sum b/go.sum index 3b64f79c..df711095 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230209105544-b185be77ce15 h1:OiyETrhilrJGS4WXqKXdTO7LnzaDb00/4F3W4JqICrM= -github.com/ProtonMail/go-proton-api v0.3.1-0.20230209105544-b185be77ce15/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.4.0 h1:Tw8Ieuc355ljPqpIzh/uttpE+5ia0z8GA/ca5iyl/9w= +github.com/ProtonMail/go-proton-api v0.4.0/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= diff --git a/internal/bridge/sync_test.go b/internal/bridge/sync_test.go index 357cbab1..329a42c5 100644 --- a/internal/bridge/sync_test.go +++ b/internal/bridge/sync_test.go @@ -431,7 +431,7 @@ func createMessages(ctx context.Context, t *testing.T, c *proton.Client, addrID, _, ok := addrKRs[addrID] require.True(t, ok) - res, err := stream.Collect(ctx, c.ImportMessages( + str, err := c.ImportMessages( ctx, addrKRs[addrID], runtime.NumCPU(), @@ -446,7 +446,10 @@ func createMessages(ctx context.Context, t *testing.T, c *proton.Client, addrID, Message: message, } })..., - )) + ) + require.NoError(t, err) + + res, err := stream.Collect(ctx, str) require.NoError(t, err) return xslices.Map(res, func(res proton.ImportRes) string { diff --git a/internal/user/imap.go b/internal/user/imap.go index 8be80a4c..84fc8943 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -538,7 +538,7 @@ func (conn *imapConnector) importMessage( messageID = msg.ID } else { - res, err := stream.Collect(ctx, conn.client.ImportMessages(ctx, addrKR, 1, 1, []proton.ImportReq{{ + str, err := conn.client.ImportMessages(ctx, addrKR, 1, 1, []proton.ImportReq{{ Metadata: proton.ImportMetadata{ AddressID: conn.addrID, LabelIDs: labelIDs, @@ -546,7 +546,12 @@ func (conn *imapConnector) importMessage( Flags: flags, }, Message: literal, - }}...)) + }}...) + if err != nil { + return fmt.Errorf("failed to prepare message for import: %w", err) + } + + res, err := stream.Collect(ctx, str) if err != nil { return fmt.Errorf("failed to import message: %w", err) } diff --git a/tests/ctx_helper_test.go b/tests/ctx_helper_test.go index 3c803b5e..04c4c51b 100644 --- a/tests/ctx_helper_test.go +++ b/tests/ctx_helper_test.go @@ -124,14 +124,19 @@ func (t *testCtx) withAddrKR( func (t *testCtx) createMessages(ctx context.Context, username, addrID string, req []proton.ImportReq) error { return t.withClient(ctx, username, func(ctx context.Context, c *proton.Client) error { return t.withAddrKR(ctx, c, username, addrID, func(ctx context.Context, addrKR *crypto.KeyRing) error { - if _, err := stream.Collect(ctx, c.ImportMessages( + str, err := c.ImportMessages( ctx, addrKR, runtime.NumCPU(), runtime.NumCPU(), req..., - )); err != nil { - return err + ) + if err != nil { + return fmt.Errorf("failed to prepare messages for import: %w", err) + } + + if _, err := stream.Collect(ctx, str); err != nil { + return fmt.Errorf("failed to import messages: %w", err) } return nil From 0823d393ed7c972e79fa49e5aa690045c0ec386c Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Thu, 9 Feb 2023 16:25:21 +0100 Subject: [PATCH 046/130] feat(GODT-1264): creation and visibility of the 'Scheduled' system label. feat(GODT-1264): typo in error message feat(GODT-1264): fix split mode broken by previous commit. --- go.mod | 2 +- go.sum | 4 +-- internal/bridge/bridge_test.go | 2 +- internal/bridge/sync_test.go | 45 ++++++++++++++++++++++++++++++++++ internal/user/imap.go | 17 ++++++++++--- internal/user/sync.go | 32 +++++++++++++++++++++++- internal/user/user.go | 7 +++++- 7 files changed, 100 insertions(+), 9 deletions(-) diff --git a/go.mod b/go.mod index d46e2155..28168d93 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230206162331-cf36d870802b + github.com/ProtonMail/gluon v0.14.2-0.20230207142445-9f98ae47a031 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.0 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index df711095..bf8875d9 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230206162331-cf36d870802b h1:v/XwH5Em8gFSpJQErhSCt0XAsIxojFxgrVcfPUEWH7I= -github.com/ProtonMail/gluon v0.14.2-0.20230206162331-cf36d870802b/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230207142445-9f98ae47a031 h1:QxHAyLmGqBtxTybgDwXwqvcA8auTcTGo8ivcEh2IIr8= +github.com/ProtonMail/gluon v0.14.2-0.20230207142445-9f98ae47a031/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/internal/bridge/bridge_test.go b/internal/bridge/bridge_test.go index ec4f5b83..992d241f 100644 --- a/internal/bridge/bridge_test.go +++ b/internal/bridge/bridge_test.go @@ -770,7 +770,7 @@ func withBridge( }) } -func waitForEvent[T any](t *testing.T, eventCh <-chan events.Event, wantEvent T) { +func waitForEvent[T any](t *testing.T, eventCh <-chan events.Event, _ T) { t.Helper() for event := range eventCh { diff --git a/internal/bridge/sync_test.go b/internal/bridge/sync_test.go index 329a42c5..db9854ad 100644 --- a/internal/bridge/sync_test.go +++ b/internal/bridge/sync_test.go @@ -24,6 +24,7 @@ import ( "os" "path/filepath" "runtime" + "strings" "sync/atomic" "testing" "time" @@ -43,6 +44,8 @@ import ( "github.com/stretchr/testify/require" ) +const scheduled = "Scheduled" + func TestBridge_Sync(t *testing.T) { numMsg := 1 << 8 @@ -468,3 +471,45 @@ func countBytesRead(ctl *proton.NetCtl, fn func()) uint64 { return read } + +func TestBridge_ScheduledLabel(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + hasScheduledSystemLabel := func(imapClient *client.Client) bool { + return xslices.Any(clientList(imapClient), func(mailboxInfo *imap.MailboxInfo) bool { return mailboxInfo.Name == scheduled }) + } + + _, _, err := s.CreateUser(username, password) + require.NoError(t, err) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(b *bridge.Bridge, _ *bridge.Mocks) { + // Perform initial sync + syncCh, done := chToType[events.Event, events.SyncFinished](b.GetEvents(events.SyncFinished{})) + defer done() + userID, err := b.LoginFull(ctx, username, password, nil, nil) + require.NoError(t, err) + require.Equal(t, userID, (<-syncCh).UserID) + + // connect an IMAP client + info, err := b.GetUserInfo(userID) + require.NoError(t, err) + imapClient, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort())) + require.NoError(t, err) + require.NoError(t, imapClient.Login(info.Addresses[0], string(info.BridgePass))) + defer func() { _ = imapClient.Logout() }() + + // Scheduled mailbox is empty. It's not listed. + require.False(t, hasScheduledSystemLabel(imapClient)) + + // Add a message to the Schedule mailbox. It's now listed. + require.NoError(t, imapClient.Append(scheduled, []string{}, time.Now(), strings.NewReader("To: no_reply@pm.me"))) + require.True(t, hasScheduledSystemLabel(imapClient)) + + // delete message from Scheduled. The mailbox is now empty and not listed anymore + _, err = imapClient.Select(scheduled, false) + require.NoError(t, err) + require.NoError(t, clientStore(imapClient, 1, 1, true, imap.FormatFlagsOp(imap.AddFlags, true), imap.DeletedFlag)) + require.NoError(t, imapClient.Expunge(nil)) + require.False(t, hasScheduledSystemLabel(imapClient)) + }) + }) +} diff --git a/internal/user/imap.go b/internal/user/imap.go index 84fc8943..e144f3da 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -505,9 +505,20 @@ func (conn *imapConnector) GetUpdates() <-chan imap.Update { }, conn.updateChLock) } -// IsMailboxVisible returns whether this mailbox should be visible over IMAP. -func (conn *imapConnector) IsMailboxVisible(_ context.Context, mailboxID imap.MailboxID) bool { - return atomic.LoadUint32(&conn.showAllMail) != 0 || mailboxID != proton.AllMailLabel +// GetMailboxVisibility returns the visibility of a mailbox over IMAP. +func (conn *imapConnector) GetMailboxVisibility(_ context.Context, mailboxID imap.MailboxID) imap.MailboxVisibility { + switch mailboxID { + case proton.AllMailLabel: + if atomic.LoadUint32(&conn.showAllMail) != 0 { + return imap.Visible + } + return imap.Hidden + + case proton.AllScheduledLabel: + return imap.HiddenIfEmpty + default: + return imap.Visible + } } // Close the connector will no longer be used and all resources should be closed/released. diff --git a/internal/user/sync.go b/internal/user/sync.go index f584c662..a46c81f4 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -43,7 +43,31 @@ import ( "golang.org/x/exp/slices" ) -// doSync begins syncing the users data. +// syncSystemLabels ensures that system labels are all known to gluon. +func (user *User) syncSystemLabels(ctx context.Context) error { + return safe.RLockRet(func() error { + var updates []imap.Update + + for _, label := range xslices.Filter(maps.Values(user.apiLabels), func(label proton.Label) bool { return label.Type == proton.LabelTypeSystem }) { + if !wantLabel(label) { + continue + } + + for _, updateCh := range xslices.Unique(maps.Values(user.updateCh)) { + update := newSystemMailboxCreatedUpdate(imap.MailboxID(label.ID), label.Name) + updateCh.Enqueue(update) + updates = append(updates, update) + } + } + if err := waitOnIMAPUpdates(ctx, updates); err != nil { + return fmt.Errorf("could not sync system labels: %w", err) + } + + return nil + }, user.apiUserLock, user.apiAddrsLock, user.apiLabelsLock, user.updateChLock) +} + +// doSync begins syncing the user's data. // It first ensures the latest event ID is known; if not, it fetches it. // It sends a SyncStarted event and then either SyncFinished or SyncFailed // depending on whether the sync was successful. @@ -658,6 +682,9 @@ func newSystemMailboxCreatedUpdate(labelID imap.MailboxID, labelName string) *im case proton.StarredLabel: attrs = attrs.Add(imap.AttrFlagged) + + case proton.AllScheduledLabel: + labelName = "Scheduled" // API actual name is "All Scheduled" } return imap.NewMailboxCreated(imap.Mailbox{ @@ -720,6 +747,9 @@ func wantLabel(label proton.Label) bool { case proton.StarredLabel: return true + case proton.AllScheduledLabel: + return true + default: return false } diff --git a/internal/user/user.go b/internal/user/user.go index a5cffba6..ae85d7a9 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -190,7 +190,12 @@ func New( // Sync the user. user.syncAbort.Do(ctx, func(ctx context.Context) { if user.vault.SyncStatus().IsComplete() { - user.log.Info("Sync already complete, skipping") + user.log.Info("Sync already complete, only system label will be updated") + if err := user.syncSystemLabels(ctx); err != nil { + user.log.WithError(err).Error("Failed to update system labels") + return + } + user.log.Info("System label update complete, starting API event stream") return } From 473be3d485a042725d58740dfcc5908a76a9f0f7 Mon Sep 17 00:00:00 2001 From: Romain LE JEUNE Date: Mon, 13 Feb 2023 20:31:32 +0100 Subject: [PATCH 047/130] feat(GODT-2357): Hide DSN_SENTRY and use single setting point for DSN_SENTRY. --- BUILDS.md | 2 +- Makefile | 10 ++++++---- internal/frontend/.gitignore | 2 +- .../bridge-gui/{Version.h.in => BuildConfig.h.in} | 1 + .../frontend/bridge-gui/bridge-gui/CMakeLists.txt | 12 ++---------- .../frontend/bridge-gui/bridge-gui/QMLBackend.cpp | 2 +- internal/frontend/bridge-gui/bridge-gui/QMLBackend.h | 2 +- .../frontend/bridge-gui/bridge-gui/SentryUtils.cpp | 2 +- internal/frontend/bridge-gui/bridge-gui/build.ps1 | 5 +++++ internal/frontend/bridge-gui/bridge-gui/build.sh | 4 ++++ internal/frontend/bridge-gui/bridge-gui/main.cpp | 5 ++--- 11 files changed, 25 insertions(+), 22 deletions(-) rename internal/frontend/bridge-gui/bridge-gui/{Version.h.in => BuildConfig.h.in} (95%) diff --git a/BUILDS.md b/BUILDS.md index 8c07ed6a..8f43485c 100644 --- a/BUILDS.md +++ b/BUILDS.md @@ -11,7 +11,7 @@ * libglvnd and libsecret development files (linux) To enable the sending of crash reports using Sentry please set the -`main.DSNSentry` value with the client key of your sentry project before build. +`DSN_SENTRY` environment variable with the client key of your sentry project before build. Otherwise, the sending of crash reports will be disabled. ## Build diff --git a/Makefile b/Makefile index 8d490b6e..b1feec17 100644 --- a/Makefile +++ b/Makefile @@ -30,9 +30,10 @@ BUILD_FLAGS_GUI:=-tags='${BUILD_TAGS} build_qt' GO_LDFLAGS:=$(addprefix -X github.com/ProtonMail/proton-bridge/v3/internal/constants., Version=${APP_VERSION} Revision=${REVISION} BuildTime=${BUILD_TIME}) GO_LDFLAGS+=-X "github.com/ProtonMail/proton-bridge/v3/internal/constants.FullAppName=${APP_FULL_NAME}" -ifneq "${BUILD_LDFLAGS}" "" - GO_LDFLAGS+=${BUILD_LDFLAGS} +ifneq "${DSN_SENTRY}" "" + GO_LDFLAGS+=-X github.com/ProtonMail/proton-bridge/v3/internal/constants.DSNSentry=${DSN_SENTRY} endif + GO_LDFLAGS_LAUNCHER:=${GO_LDFLAGS} ifeq "${TARGET_OS}" "windows" #GO_LDFLAGS+=-H=windowsgui # Disabled so we can inspect trace logs from the bridge for debugging. @@ -154,7 +155,8 @@ ${EXE_TARGET}: check-build-essentials ${EXE_NAME} BRIDGE_VENDOR="${APP_VENDOR}" \ BRIDGE_APP_VERSION=${APP_VERSION} \ BRIDGE_REVISION=${REVISION} \ - BRIDGE_BUILD_TIME=${BUILD_TIME} \ + BRIDGE_DSN_SENTRY=${DSN_SENTRY} \ + BRIDGE_BUILD_TIME=${BUILD_TIME} \ BRIDGE_GUI_BUILD_CONFIG=Release \ BRIDGE_INSTALL_PATH=${ROOT_DIR}/${DEPLOY_DIR}/${GOOS} \ ./build.sh install @@ -326,7 +328,7 @@ clean-vendor: clean-gui: cd internal/frontend/bridge-gui/ && \ - rm -f Version.h && \ + rm -f BuildConfig.h && \ rm -rf cmake-build-*/ clean-vcpkg: diff --git a/internal/frontend/.gitignore b/internal/frontend/.gitignore index 976250b8..f20600dd 100644 --- a/internal/frontend/.gitignore +++ b/internal/frontend/.gitignore @@ -10,5 +10,5 @@ rcc_cgo_*.go *.qmlc # Generated file -bridge-gui/bridge-gui/Version.h +bridge-gui/bridge-gui/BuildConfig.h bridge-gui/bridge-gui/Resources.rc diff --git a/internal/frontend/bridge-gui/bridge-gui/Version.h.in b/internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in similarity index 95% rename from internal/frontend/bridge-gui/bridge-gui/Version.h.in rename to internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in index a9081306..afcc58a5 100644 --- a/internal/frontend/bridge-gui/bridge-gui/Version.h.in +++ b/internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in @@ -24,5 +24,6 @@ #define PROJECT_VER "@BRIDGE_APP_VERSION@" #define PROJECT_REVISION "@BRIDGE_REVISION@" #define PROJECT_BUILD_TIME "@BRIDGE_BUILD_TIME@" +#define PROJECT_DSN_SENTRY "@BRIDGE_DSN_SENTRY@" #endif // BRIDGE_GUI_VERSION_H diff --git a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt index e64ff118..cf40a5e8 100644 --- a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt @@ -85,20 +85,12 @@ message(STATUS "Using Qt ${Qt6_VERSION}") #***************************************************************************************************************************************************** find_package(sentry CONFIG REQUIRED) -set(DSN_SENTRY "https://ea31dfe8574849108fb8ba044fec3620@api.protonmail.ch/core/v4/reports/sentry/7") -set(SENTRY_CONFIG_GENERATED_FILE_DIR ${CMAKE_CURRENT_BINARY_DIR}/sentry-generated) -set(SENTRY_CONFIG_FILE ${SENTRY_CONFIG_GENERATED_FILE_DIR}/project_sentry_config.h) -file(GENERATE OUTPUT ${SENTRY_CONFIG_FILE} CONTENT - "// AUTO GENERATED FILE, DO NOT MODIFY\n#pragma once\nconst char* SentryDNS=\"${DSN_SENTRY}\";\nconst char* SentryProductID=\"bridge-mail@${BRIDGE_APP_VERSION}\";\n" -) - - #***************************************************************************************************************************************************** # Source files and output #***************************************************************************************************************************************************** -configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Version.h.in ${CMAKE_CURRENT_SOURCE_DIR}/Version.h) +configure_file(${CMAKE_CURRENT_SOURCE_DIR}/BuildConfig.h.in ${CMAKE_CURRENT_SOURCE_DIR}/BuildConfig.h) if (NOT TARGET bridgepp) add_subdirectory(../bridgepp bridgepp) @@ -122,7 +114,7 @@ add_executable(bridge-gui EventStreamWorker.cpp EventStreamWorker.h main.cpp Pch.h - Version.h + BuildConfig.h QMLBackend.cpp QMLBackend.h UserList.cpp UserList.h SentryUtils.cpp SentryUtils.h diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp index 015eb9da..62eeb668 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp @@ -18,7 +18,7 @@ #include "QMLBackend.h" #include "EventStreamWorker.h" -#include "Version.h" +#include "BuildConfig.h" #include #include #include diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h index f4d28d96..d570ba0a 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h @@ -21,7 +21,7 @@ #include "MacOS/DockIcon.h" -#include "Version.h" +#include "BuildConfig.h" #include "UserList.h" #include #include diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index 6dafef9f..e2470412 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -16,7 +16,7 @@ // along with Proton Mail Bridge. If not, see . #include "SentryUtils.h" -#include "Version.h" +#include "BuildConfig.h" #include #include diff --git a/internal/frontend/bridge-gui/bridge-gui/build.ps1 b/internal/frontend/bridge-gui/bridge-gui/build.ps1 index 20bd2f49..b11821c3 100644 --- a/internal/frontend/bridge-gui/bridge-gui/build.ps1 +++ b/internal/frontend/bridge-gui/bridge-gui/build.ps1 @@ -76,6 +76,9 @@ function check_exit() { Write-host "Running build for version $bridgeVersion - $buildConfig in $buildDir" $REVISION_HASH = git rev-parse --short=10 HEAD +$bridgeDsnSentry = ($env:BRIDGE_DSN_SENTRY) +$bridgeBuidTime = ($env:BRIDGE_BUILD_TIME) + git submodule update --init --recursive $vcpkgRoot . $vcpkgBootstrap -disableMetrics . $vcpkgExe install sentry-native:x64-windows grpc:x64-windows --clean-after-build @@ -85,6 +88,8 @@ git submodule update --init --recursive $vcpkgRoot -DBRIDGE_VENDOR="$bridgeVendor" ` -DBRIDGE_REVISION=$REVISION_HASH ` -DBRIDGE_APP_VERSION="$bridgeVersion" ` + -DBRIDGE_BUILD_TIME="$bridgeBuidTime" ` + -DBRIDGE_DSN_SENTRY="$bridgeDsnSentry" ` -S . -B $buildDir check_exit "CMake failed" diff --git a/internal/frontend/bridge-gui/bridge-gui/build.sh b/internal/frontend/bridge-gui/bridge-gui/build.sh index c47663d5..832749e2 100755 --- a/internal/frontend/bridge-gui/bridge-gui/build.sh +++ b/internal/frontend/bridge-gui/bridge-gui/build.sh @@ -56,6 +56,8 @@ BUILD_CONFIG=${BRIDGE_GUI_BUILD_CONFIG:-Debug} BUILD_DIR=$(echo "./cmake-build-${BUILD_CONFIG}" | tr '[:upper:]' '[:lower:]') VCPKG_ROOT="${BRIDGE_REPO_ROOT}/extern/vcpkg" BRIDGE_REVISION=$(git rev-parse --short=10 HEAD) +BRIDGE_DSN_SENTRY=${BRIDGE_DSN_SENTRY} +BRIDGE_BUILD_TIME=${BRIDGE_BUILD_TIME} git submodule update --init --recursive ${VCPKG_ROOT} check_exit "Failed to initialize vcpkg as a submodule." @@ -94,6 +96,8 @@ cmake \ -DBRIDGE_APP_FULL_NAME="${BRIDGE_APP_FULL_NAME}" \ -DBRIDGE_VENDOR="${BRIDGE_VENDOR}" \ -DBRIDGE_REVISION="${BRIDGE_REVISION}" \ + -DBRIDGE_DSN_SENTRY="${BRIDGE_DSN_SENTRY}" \ + -DBRIDGE_BRIDGE_TIME="${BRIDGE_BRIDGE_TIME}" \ -DBRIDGE_APP_VERSION="${BRIDGE_APP_VERSION}" "${BRIDGE_CMAKE_MACOS_OPTS}" \ -G Ninja \ -S . \ diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index b71a1606..9d39f9e3 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -21,7 +21,7 @@ #include "CommandLine.h" #include "QMLBackend.h" #include "SentryUtils.h" -#include "Version.h" +#include "BuildConfig.h" #include #include #include @@ -29,7 +29,6 @@ #include #include #include -#include #ifdef Q_OS_MACOS @@ -306,7 +305,7 @@ void closeBridgeApp() { int main(int argc, char *argv[]) { // Init sentry. sentry_options_t *sentryOptions = sentry_options_new(); - sentry_options_set_dsn(sentryOptions, SentryDNS); + sentry_options_set_dsn(sentryOptions, PROJECT_DSN_SENTRY); { const QString sentryCachePath = sentryCacheDir(); sentry_options_set_database_path(sentryOptions, sentryCachePath.toStdString().c_str()); From c1921a811bfcf842cc9d82b65e31ae67b3cdedfa Mon Sep 17 00:00:00 2001 From: Romain LE JEUNE Date: Tue, 14 Feb 2023 17:07:45 +0100 Subject: [PATCH 048/130] ci: always use the 'eventually' variant step and remove others. --- Makefile | 2 +- tests/bdd_test.go | 4 -- tests/features/imap/mailbox/create.feature | 12 ++--- .../imap/mailbox/hide_all_mail.feature | 6 +-- tests/features/imap/mailbox/list.feature | 2 +- tests/features/imap/message/copy.feature | 14 +++--- tests/features/imap/message/create.feature | 24 +++++----- tests/features/imap/message/delete.feature | 6 +-- .../imap/message/delete_from_trash.feature | 18 ++++---- tests/features/imap/message/drafts.feature | 8 ++-- tests/features/imap/message/fetch.feature | 4 +- tests/features/imap/message/import.feature | 6 +-- tests/features/imap/message/move.feature | 28 +++++------ .../imap/message/move_without_support.feature | 4 +- tests/features/imap/migration.feature | 2 +- tests/features/user/addressmode.feature | 46 +++++++++---------- tests/features/user/login.feature | 10 ++-- tests/features/user/relogin.feature | 2 +- tests/features/user/sync.feature | 2 +- 19 files changed, 98 insertions(+), 102 deletions(-) diff --git a/Makefile b/Makefile index b1feec17..0d85f5fc 100644 --- a/Makefile +++ b/Makefile @@ -230,7 +230,7 @@ test-race: gofiles go test -v -timeout=30m -p=1 -count=1 -race -failfast -run=${TESTRUN} ./internal/... ./pkg/... test-integration: gofiles - go test -v -timeout=10m -p=1 -count=1 github.com/ProtonMail/proton-bridge/v3/tests + go test -v -timeout=20m -p=1 -count=1 github.com/ProtonMail/proton-bridge/v3/tests test-integration-debug: gofiles dlv test github.com/ProtonMail/proton-bridge/v3/tests -- -test.v -test.timeout=10m -test.parallel=1 -test.count=1 diff --git a/tests/bdd_test.go b/tests/bdd_test.go index 2fcb1e5d..f67caa70 100644 --- a/tests/bdd_test.go +++ b/tests/bdd_test.go @@ -162,7 +162,6 @@ func TestFeatures(testingT *testing.T) { ctx.Step(`^user "([^"]*)" logs out$`, s.userLogsOut) ctx.Step(`^user "([^"]*)" is deleted$`, s.userIsDeleted) ctx.Step(`^the auth of user "([^"]*)" is revoked$`, s.theAuthOfUserIsRevoked) - ctx.Step(`^user "([^"]*)" is listed and connected$`, s.userIsListedAndConnected) ctx.Step(`^user "([^"]*)" is eventually listed and connected$`, s.userIsEventuallyListedAndConnected) ctx.Step(`^user "([^"]*)" is listed but not connected$`, s.userIsListedButNotConnected) ctx.Step(`^user "([^"]*)" is not listed$`, s.userIsNotListed) @@ -184,7 +183,6 @@ func TestFeatures(testingT *testing.T) { ctx.Step(`^IMAP client "([^"]*)" creates "([^"]*)"$`, s.imapClientCreatesMailbox) ctx.Step(`^IMAP client "([^"]*)" deletes "([^"]*)"$`, s.imapClientDeletesMailbox) ctx.Step(`^IMAP client "([^"]*)" renames "([^"]*)" to "([^"]*)"$`, s.imapClientRenamesMailboxTo) - ctx.Step(`^IMAP client "([^"]*)" sees the following mailbox info:$`, s.imapClientSeesTheFollowingMailboxInfo) ctx.Step(`^IMAP client "([^"]*)" eventually sees the following mailbox info:$`, s.imapClientEventuallySeesTheFollowingMailboxInfo) ctx.Step(`^IMAP client "([^"]*)" sees the following mailbox info for "([^"]*)":$`, s.imapClientSeesTheFollowingMailboxInfoForMailbox) ctx.Step(`^IMAP client "([^"]*)" sees "([^"]*)"$`, s.imapClientSeesMailbox) @@ -195,9 +193,7 @@ func TestFeatures(testingT *testing.T) { ctx.Step(`^IMAP client "([^"]*)" copies all messages from "([^"]*)" to "([^"]*)"$`, s.imapClientCopiesAllMessagesFromTo) ctx.Step(`^IMAP client "([^"]*)" moves the message with subject "([^"]*)" from "([^"]*)" to "([^"]*)"$`, s.imapClientMovesTheMessageWithSubjectFromTo) ctx.Step(`^IMAP client "([^"]*)" moves all messages from "([^"]*)" to "([^"]*)"$`, s.imapClientMovesAllMessagesFromTo) - ctx.Step(`^IMAP client "([^"]*)" sees the following messages in "([^"]*)":$`, s.imapClientSeesTheFollowingMessagesInMailbox) ctx.Step(`^IMAP client "([^"]*)" eventually sees the following messages in "([^"]*)":$`, s.imapClientEventuallySeesTheFollowingMessagesInMailbox) - ctx.Step(`^IMAP client "([^"]*)" sees (\d+) messages in "([^"]*)"$`, s.imapClientSeesMessagesInMailbox) ctx.Step(`^IMAP client "([^"]*)" eventually sees (\d+) messages in "([^"]*)"$`, s.imapClientEventuallySeesMessagesInMailbox) ctx.Step(`^IMAP client "([^"]*)" marks message (\d+) as deleted$`, s.imapClientMarksMessageAsDeleted) ctx.Step(`^IMAP client "([^"]*)" marks the message with subject "([^"]*)" as deleted$`, s.imapClientMarksTheMessageWithSubjectAsDeleted) diff --git a/tests/features/imap/mailbox/create.feature b/tests/features/imap/mailbox/create.feature index ce0e6349..e89ffc7c 100644 --- a/tests/features/imap/mailbox/create.feature +++ b/tests/features/imap/mailbox/create.feature @@ -37,7 +37,7 @@ Feature: IMAP create mailbox Then it succeeds When IMAP client "1" creates "Labels/l3" Then it succeeds - Then IMAP client "1" sees the following mailbox info: + Then IMAP client "1" eventually sees the following mailbox info: | name | | INBOX | | Drafts | @@ -65,7 +65,7 @@ Feature: IMAP create mailbox Then it succeeds When IMAP client "1" creates "Folders/f2/f22" Then it succeeds - Then IMAP client "1" sees the following mailbox info: + Then IMAP client "1" eventually sees the following mailbox info: | name | | INBOX | | Drafts | @@ -89,7 +89,7 @@ Feature: IMAP create mailbox And the user logs in with username "[user:user]" and password "password" And user "[user:user]" finishes syncing And user "[user:user]" connects and authenticates IMAP client "2" - Then IMAP client "2" sees the following mailbox info: + Then IMAP client "2" eventually sees the following mailbox info: | name | | INBOX | | Drafts | @@ -119,7 +119,7 @@ Feature: IMAP create mailbox Then it succeeds When IMAP client "1" creates "Folders/f2/f22" Then it succeeds - Then IMAP client "1" sees the following mailbox info: + Then IMAP client "1" eventually sees the following mailbox info: | name | | INBOX | | Drafts | @@ -143,7 +143,7 @@ Feature: IMAP create mailbox Then it succeeds When IMAP client "1" renames "Folders/f1/f12" to "Folders/f2/f12" Then it succeeds - Then IMAP client "1" sees the following mailbox info: + Then IMAP client "1" eventually sees the following mailbox info: | name | | INBOX | | Drafts | @@ -167,7 +167,7 @@ Feature: IMAP create mailbox And the user logs in with username "[user:user]" and password "password" And user "[user:user]" finishes syncing And user "[user:user]" connects and authenticates IMAP client "2" - Then IMAP client "2" sees the following mailbox info: + Then IMAP client "2" eventually sees the following mailbox info: | name | | INBOX | | Drafts | diff --git a/tests/features/imap/mailbox/hide_all_mail.feature b/tests/features/imap/mailbox/hide_all_mail.feature index ba4e7ba1..9a450e8f 100644 --- a/tests/features/imap/mailbox/hide_all_mail.feature +++ b/tests/features/imap/mailbox/hide_all_mail.feature @@ -7,7 +7,7 @@ Feature: IMAP Hide All Mail And user "[user:user]" connects and authenticates IMAP client "1" Scenario: Hide All Mail Mailbox - Given IMAP client "1" sees the following mailbox info: + Given IMAP client "1" eventually sees the following mailbox info: | name | | INBOX | | Drafts | @@ -20,7 +20,7 @@ Feature: IMAP Hide All Mail | Folders | | Labels | When the user hides All Mail - Then IMAP client "1" sees the following mailbox info: + Then IMAP client "1" eventually sees the following mailbox info: | name | | INBOX | | Drafts | @@ -32,7 +32,7 @@ Feature: IMAP Hide All Mail | Folders | | Labels | When the user shows All Mail - Then IMAP client "1" sees the following mailbox info: + Then IMAP client "1" eventually sees the following mailbox info: | name | | INBOX | | Drafts | diff --git a/tests/features/imap/mailbox/list.feature b/tests/features/imap/mailbox/list.feature index 934409fd..f93fc15f 100644 --- a/tests/features/imap/mailbox/list.feature +++ b/tests/features/imap/mailbox/list.feature @@ -9,7 +9,7 @@ Feature: IMAP list mailboxes And the user logs in with username "[user:user]" and password "password" And user "[user:user]" finishes syncing And user "[user:user]" connects and authenticates IMAP client "1" - Then IMAP client "1" sees the following mailbox info: + Then IMAP client "1" eventually sees the following mailbox info: | name | | INBOX | | Drafts | diff --git a/tests/features/imap/message/copy.feature b/tests/features/imap/message/copy.feature index 3c97b3ef..016fa323 100644 --- a/tests/features/imap/message/copy.feature +++ b/tests/features/imap/message/copy.feature @@ -17,22 +17,22 @@ Feature: IMAP copy messages Scenario: Copy message to label When IMAP client "1" copies the message with subject "foo" from "INBOX" to "Labels/label" And it succeeds - Then IMAP client "1" sees the following messages in "INBOX": + Then IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | | jane.doe@mail.com | name@[domain] | bar | true | - And IMAP client "1" sees the following messages in "Labels/label": + And IMAP client "1" eventually sees the following messages in "Labels/label": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | Scenario: Copy all messages to label When IMAP client "1" copies all messages from "INBOX" to "Labels/label" And it succeeds - Then IMAP client "1" sees the following messages in "INBOX": + Then IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | | jane.doe@mail.com | name@[domain] | bar | true | - And IMAP client "1" sees the following messages in "Labels/label": + And IMAP client "1" eventually sees the following messages in "Labels/label": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | | jane.doe@mail.com | name@[domain] | bar | true | @@ -43,14 +43,14 @@ Feature: IMAP copy messages Then IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | unread | | jane.doe@mail.com | name@[domain] | bar | true | - And IMAP client "1" sees the following messages in "Folders/mbox": + And IMAP client "1" eventually sees the following messages in "Folders/mbox": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | Scenario: Copy all messages to folder does move When IMAP client "1" copies all messages from "INBOX" to "Folders/mbox" And it succeeds - Then IMAP client "1" sees the following messages in "Folders/mbox": + Then IMAP client "1" eventually sees the following messages in "Folders/mbox": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | | jane.doe@mail.com | name@[domain] | bar | true | @@ -66,7 +66,7 @@ Feature: IMAP copy messages And IMAP client "1" eventually sees 0 messages in "Sent" Scenario: Copy message from All mail moves from the original location - Given IMAP client "1" sees the following messages in "INBOX": + Given IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | | jane.doe@mail.com | name@[domain] | bar | true | diff --git a/tests/features/imap/message/create.feature b/tests/features/imap/message/create.feature index 733c26c7..367197da 100644 --- a/tests/features/imap/message/create.feature +++ b/tests/features/imap/message/create.feature @@ -12,10 +12,10 @@ Feature: IMAP create messages | from | to | subject | body | | john.doe@email.com | [user:user]@[domain] | foo | bar | Then it succeeds - And IMAP client "1" sees the following messages in "INBOX": + And IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | body | | john.doe@email.com | [user:user]@[domain] | foo | bar | - And IMAP client "1" sees the following messages in "All Mail": + And IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | body | | john.doe@email.com | [user:user]@[domain] | foo | bar | @@ -37,10 +37,10 @@ Feature: IMAP create messages | from | to | subject | body | | [user:user]@[domain] | john.doe@email.com | foo | bar | Then it succeeds - And IMAP client "1" sees the following messages in "Sent": + And IMAP client "1" eventually sees the following messages in "Sent": | from | to | subject | body | | [user:user]@[domain] | john.doe@email.com | foo | bar | - And IMAP client "1" sees the following messages in "All Mail": + And IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | body | | [user:user]@[domain] | john.doe@email.com | foo | bar | @@ -49,10 +49,10 @@ Feature: IMAP create messages | from | to | subject | body | | [alias:alias]@[domain] | john.doe@email.com | foo | bar | Then it succeeds - And IMAP client "1" sees the following messages in "Sent": + And IMAP client "1" eventually sees the following messages in "Sent": | from | to | subject | body | | [alias:alias]@[domain] | john.doe@email.com | foo | bar | - And IMAP client "1" sees the following messages in "All Mail": + And IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | body | | [alias:alias]@[domain] | john.doe@email.com | foo | bar | @@ -61,10 +61,10 @@ Feature: IMAP create messages | from | to | subject | body | | john.doe@email.com | john.doe2@[domain] | foo | bar | Then it succeeds - And IMAP client "1" sees the following messages in "INBOX": + And IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | body | | john.doe@email.com | john.doe2@[domain] | foo | bar | - And IMAP client "1" sees the following messages in "All Mail": + And IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | body | | john.doe@email.com | john.doe2@[domain] | foo | bar | @@ -73,10 +73,10 @@ Feature: IMAP create messages | from | to | subject | body | | john.doe@email.com | john.doe2@[domain] | foo | bar | Then it succeeds - And IMAP client "1" sees the following messages in "Sent": + And IMAP client "1" eventually sees the following messages in "Sent": | from | to | subject | body | | john.doe@email.com | john.doe2@[domain] | foo | bar | - And IMAP client "1" sees the following messages in "All Mail": + And IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | body | | john.doe@email.com | john.doe2@[domain] | foo | bar | @@ -85,7 +85,7 @@ Feature: IMAP create messages | from | to | subject | body | | john.doe@email.com | john.doe2@[domain] | foo | bar | And it succeeds - And IMAP client "1" sees the following messages in "Sent": + And IMAP client "1" eventually sees the following messages in "Sent": | from | to | subject | body | | john.doe@email.com | john.doe2@[domain] | foo | bar | And it succeeds @@ -93,7 +93,7 @@ Feature: IMAP create messages | from | to | subject | body | | john.doe@email.com | john.doe2@[domain] | foo | bar | And it succeeds - And IMAP client "1" sees the following messages in "Sent": + And IMAP client "1" eventually sees the following messages in "Sent": | from | to | subject | body | | john.doe@email.com | john.doe2@[domain] | foo | bar | | john.doe@email.com | john.doe2@[domain] | foo | bar | diff --git a/tests/features/imap/message/delete.feature b/tests/features/imap/message/delete.feature index ffe7619d..32e04229 100644 --- a/tests/features/imap/message/delete.feature +++ b/tests/features/imap/message/delete.feature @@ -18,14 +18,14 @@ Feature: IMAP remove messages from mailbox Then IMAP client "1" sees that message 2 has the flag "\Deleted" When IMAP client "1" expunges And it succeeds - Then IMAP client "1" sees 9 messages in "Folders/mbox" + Then IMAP client "1" eventually sees 9 messages in "Folders/mbox" Scenario: Mark all messages as deleted and EXPUNGE When IMAP client "1" selects "Folders/mbox" And IMAP client "1" marks all messages as deleted And IMAP client "1" expunges And it succeeds - Then IMAP client "1" sees 0 messages in "Folders/mbox" + Then IMAP client "1" eventually sees 0 messages in "Folders/mbox" Scenario: Mark messages as undeleted and EXPUNGE When IMAP client "1" selects "Folders/mbox" @@ -37,7 +37,7 @@ Feature: IMAP remove messages from mailbox And it succeeds When IMAP client "1" expunges And it succeeds - Then IMAP client "1" sees 2 messages in "Folders/mbox" + Then IMAP client "1" eventually sees 2 messages in "Folders/mbox" Scenario: Not possible to delete from All Mail and expunge does nothing When IMAP client "1" selects "All Mail" diff --git a/tests/features/imap/message/delete_from_trash.feature b/tests/features/imap/message/delete_from_trash.feature index 7797f130..fdc5105e 100644 --- a/tests/features/imap/message/delete_from_trash.feature +++ b/tests/features/imap/message/delete_from_trash.feature @@ -20,14 +20,14 @@ Feature: IMAP remove messages from Trash Then it succeeds When IMAP client "1" marks the message with subject "foo" as deleted Then it succeeds - And IMAP client "1" sees 2 messages in "Trash" - And IMAP client "1" sees 2 messages in "All Mail" - And IMAP client "1" sees 1 messages in "Labels/label" + And IMAP client "1" eventually sees 2 messages in "Trash" + And IMAP client "1" eventually sees 2 messages in "All Mail" + And IMAP client "1" eventually sees 1 messages in "Labels/label" When IMAP client "1" expunges Then it succeeds - And IMAP client "1" sees 1 messages in "Trash" - And IMAP client "1" sees 2 messages in "All Mail" - And IMAP client "1" sees 1 messages in "Labels/label" + And IMAP client "1" eventually sees 1 messages in "Trash" + And IMAP client "1" eventually sees 2 messages in "All Mail" + And IMAP client "1" eventually sees 1 messages in "Labels/label" Scenario Outline: Message in Trash only is permanently deleted Given the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Trash": @@ -41,9 +41,9 @@ Feature: IMAP remove messages from Trash And IMAP client "1" selects "Trash" When IMAP client "1" marks the message with subject "foo" as deleted Then it succeeds - And IMAP client "1" sees 2 messages in "Trash" - And IMAP client "1" sees 2 messages in "All Mail" + And IMAP client "1" eventually sees 2 messages in "Trash" + And IMAP client "1" eventually sees 2 messages in "All Mail" When IMAP client "1" expunges Then it succeeds - And IMAP client "1" sees 1 messages in "Trash" + And IMAP client "1" eventually sees 1 messages in "Trash" And IMAP client "1" eventually sees 1 messages in "All Mail" \ No newline at end of file diff --git a/tests/features/imap/message/drafts.feature b/tests/features/imap/message/drafts.feature index 8ebed248..6f185418 100644 --- a/tests/features/imap/message/drafts.feature +++ b/tests/features/imap/message/drafts.feature @@ -15,7 +15,7 @@ Feature: IMAP Draft messages Then IMAP client "1" eventually sees the following messages in "Drafts": | body | | This is a dra | - And IMAP client "1" sees 1 messages in "Drafts" + And IMAP client "1" eventually sees 1 messages in "Drafts" Scenario: Draft edited locally When IMAP client "1" marks message 1 as deleted @@ -33,7 +33,7 @@ Feature: IMAP Draft messages And IMAP client "1" eventually sees the following messages in "Drafts": | to | subject | body | | someone@example.com | Basic Draft | This is a draft, but longer | - And IMAP client "1" sees 1 messages in "Drafts" + And IMAP client "1" eventually sees 1 messages in "Drafts" Scenario: Draft edited remotely When the following fields were changed in draft 1 for address "[user:user]@[domain]" of account "[user:user]": @@ -42,12 +42,12 @@ Feature: IMAP Draft messages Then IMAP client "1" eventually sees the following messages in "Drafts": | to | subject | body | | someone@example.com | Basic Draft | This is a draft body, but longer | - And IMAP client "1" sees 1 messages in "Drafts" + And IMAP client "1" eventually sees 1 messages in "Drafts" Scenario: Draft moved to trash remotely When draft 1 for address "[user:user]@[domain]" of account "[user:user] was moved to trash Then IMAP client "1" eventually sees the following messages in "Trash": | body | | This is a dra | - And IMAP client "1" sees 0 messages in "Drafts" + And IMAP client "1" eventually sees 0 messages in "Drafts" diff --git a/tests/features/imap/message/fetch.feature b/tests/features/imap/message/fetch.feature index 7c4d6fcc..f72461b4 100644 --- a/tests/features/imap/message/fetch.feature +++ b/tests/features/imap/message/fetch.feature @@ -13,7 +13,7 @@ Feature: IMAP Fetch And user "[user:user]" connects and authenticates IMAP client "1" Scenario: Fetch very old message - Given IMAP client "1" sees the following messages in "INBOX": + Given IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | date | | john.doe@mail.com | [user:user]@[domain] | foo | 13 Aug 82 00:00 +0000 | Then IMAP client "1" sees header "X-Original-Date: Sun, 13 Jul 1969 00:00:00 +0000" in message with subject "foo" in "INBOX" @@ -21,6 +21,6 @@ Feature: IMAP Fetch Scenario: Fetch from deleted cache When the user deletes the gluon cache - Then IMAP client "1" sees the following messages in "INBOX": + Then IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | date | | john.doe@mail.com | [user:user]@[domain] | foo | 13 Aug 82 00:00 +0000 | diff --git a/tests/features/imap/message/import.feature b/tests/features/imap/message/import.feature index a3c36f0a..b70ad4c7 100644 --- a/tests/features/imap/message/import.feature +++ b/tests/features/imap/message/import.feature @@ -104,7 +104,7 @@ Feature: IMAP import messages And IMAP client "1" eventually sees the following messages in "Sent": | from | to | subject | body | | foo@example.com | bridgetest@pm.test | Hello | Hello | - And IMAP client "1" sees 0 messages in "Inbox" + And IMAP client "1" eventually sees 0 messages in "Inbox" Scenario: Import non-received message to Inbox When IMAP client "1" appends the following message to "Inbox": @@ -119,7 +119,7 @@ Feature: IMAP import messages And IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | body | | foo@example.com | bridgetest@pm.test | Hello | Hello | - And IMAP client "1" sees 0 messages in "Sent" + And IMAP client "1" eventually sees 0 messages in "Sent" Scenario: Import non-received message to Sent When IMAP client "1" appends the following message to "Sent": @@ -134,7 +134,7 @@ Feature: IMAP import messages And IMAP client "1" eventually sees the following messages in "Sent": | from | to | subject | body | | foo@example.com | bridgetest@pm.test | Hello | Hello | - And IMAP client "1" sees 0 messages in "Inbox" + And IMAP client "1" eventually sees 0 messages in "Inbox" Scenario Outline: Import message without sender to When IMAP client "1" appends the following message to "": diff --git a/tests/features/imap/message/move.feature b/tests/features/imap/message/move.feature index 272498d8..289f258a 100644 --- a/tests/features/imap/message/move.feature +++ b/tests/features/imap/message/move.feature @@ -24,11 +24,11 @@ Feature: IMAP move messages Scenario: Move message from folder to label (keeps in folder) When IMAP client "1" moves the message with subject "foo" from "INBOX" to "Labels/label" And it succeeds - And IMAP client "1" sees the following messages in "INBOX": + And IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | | jane.doe@mail.com | name@[domain] | bar | true | - And IMAP client "1" sees the following messages in "Labels/label": + And IMAP client "1" eventually sees the following messages in "Labels/label": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | @@ -41,56 +41,56 @@ Feature: IMAP move messages And IMAP client "target" selects "Labels/label" And IMAP clients "source" and "target" move message with subject "foo" of "[user:user]" to "Labels/label" by APPEND DELETE EXPUNGE And it succeeds - Then IMAP client "source" sees the following messages in "INBOX": + Then IMAP client "source" eventually sees the following messages in "INBOX": | from | to | subject | unread | | jane.doe@mail.com | name@[domain] | bar | true | - And IMAP client "target" sees the following messages in "Labels/label": + And IMAP client "target" eventually sees the following messages in "Labels/label": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | Scenario: Move message from label to folder When IMAP client "1" moves the message with subject "baz" from "Labels/label2" to "Folders/mbox" And it succeeds - And IMAP client "1" sees the following messages in "Folders/mbox": + And IMAP client "1" eventually sees the following messages in "Folders/mbox": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | baz | false | - And IMAP client "1" sees 0 messages in "Labels/label2" + And IMAP client "1" eventually sees 0 messages in "Labels/label2" Scenario: Move message from label to label When IMAP client "1" moves the message with subject "baz" from "Labels/label2" to "Labels/label" And it succeeds - And IMAP client "1" sees the following messages in "Labels/label": + And IMAP client "1" eventually sees the following messages in "Labels/label": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | baz | false | - And IMAP client "1" sees 0 messages in "Labels/label2" + And IMAP client "1" eventually sees 0 messages in "Labels/label2" Scenario: Move message from system label to system label When IMAP client "1" moves the message with subject "foo" from "INBOX" to "Trash" And it succeeds - And IMAP client "1" sees the following messages in "INBOX": + And IMAP client "1" eventually sees the following messages in "INBOX": | from | to | subject | unread | | jane.doe@mail.com | name@[domain] | bar | true | - And IMAP client "1" sees the following messages in "Trash": + And IMAP client "1" eventually sees the following messages in "Trash": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | Scenario: Move message from folder to system label When IMAP client "1" moves the message with subject "baz" from "Labels/label2" to "Folders/mbox" And it succeeds - And IMAP client "1" sees the following messages in "Folders/mbox": + And IMAP client "1" eventually sees the following messages in "Folders/mbox": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | baz | false | When IMAP client "1" moves the message with subject "baz" from "Folders/mbox" to "Trash" And it succeeds - And IMAP client "1" sees 0 messages in "Folders/mbox" - And IMAP client "1" sees the following messages in "Trash": + And IMAP client "1" eventually sees 0 messages in "Folders/mbox" + And IMAP client "1" eventually sees the following messages in "Trash": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | baz | false | Scenario: Move message from All Mail is not possible When IMAP client "1" moves the message with subject "baz" from "All Mail" to "Folders/folder" Then it fails - And IMAP client "1" sees the following messages in "All Mail": + And IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | | jane.doe@mail.com | name@[domain] | bar | true | diff --git a/tests/features/imap/message/move_without_support.feature b/tests/features/imap/message/move_without_support.feature index bdf583b7..ca81095e 100644 --- a/tests/features/imap/message/move_without_support.feature +++ b/tests/features/imap/message/move_without_support.feature @@ -34,8 +34,8 @@ Feature: IMAP move messages by append and delete (without MOVE support, e.g., Ou And IMAP client "source" selects "" And IMAP client "target" selects "" When IMAP clients "source" and "target" move message with subject "subj2" of "[user:user]" to "" by - And IMAP client "source" sees 1 messages in "" - And IMAP client "source" sees the following messages in "": + And IMAP client "source" eventually sees 1 messages in "" + And IMAP client "source" eventually sees the following messages in "": | from | to | subject | | sndr1@[domain] | rcvr1@[domain] | subj1 | And IMAP client "target" eventually sees 1 messages in "" diff --git a/tests/features/imap/migration.feature b/tests/features/imap/migration.feature index 136257f1..4d6a11a9 100644 --- a/tests/features/imap/migration.feature +++ b/tests/features/imap/migration.feature @@ -17,7 +17,7 @@ Feature: Bridge can fully sync an account Scenario: The user changes the gluon path When the user changes the gluon path And user "[user:user]" connects and authenticates IMAP client "2" - Then IMAP client "2" sees the following messages in "INBOX": + Then IMAP client "2" eventually sees the following messages in "INBOX": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | foo | false | | jane.doe@mail.com | name@[domain] | bar | true | diff --git a/tests/features/user/addressmode.feature b/tests/features/user/addressmode.feature index d447a4c1..714e2e3c 100644 --- a/tests/features/user/addressmode.feature +++ b/tests/features/user/addressmode.feature @@ -20,30 +20,30 @@ Feature: Address mode Scenario: The user is in combined mode When user "[user:user]" connects and authenticates IMAP client "1" with address "[user:user]@[domain]" - Then IMAP client "1" sees the following messages in "Folders/one": + Then IMAP client "1" eventually sees the following messages in "Folders/one": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | - And IMAP client "1" sees the following messages in "Folders/two": + And IMAP client "1" eventually sees the following messages in "Folders/two": | from | to | subject | unread | | c@[domain] | c@[domain] | three | true | | d@[domain] | d@[domain] | four | false | - And IMAP client "1" sees the following messages in "All Mail": + And IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | | c@[domain] | c@[domain] | three | true | | d@[domain] | d@[domain] | four | false | When user "[user:user]" connects and authenticates IMAP client "2" with address "[alias:alias]@[domain]" - Then IMAP client "2" sees the following messages in "Folders/one": + Then IMAP client "2" eventually sees the following messages in "Folders/one": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | - And IMAP client "2" sees the following messages in "Folders/two": + And IMAP client "2" eventually sees the following messages in "Folders/two": | from | to | subject | unread | | c@[domain] | c@[domain] | three | true | | d@[domain] | d@[domain] | four | false | - And IMAP client "2" sees the following messages in "All Mail": + And IMAP client "2" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | @@ -54,22 +54,22 @@ Feature: Address mode Given the user sets the address mode of user "[user:user]" to "split" And user "[user:user]" finishes syncing When user "[user:user]" connects and authenticates IMAP client "1" with address "[user:user]@[domain]" - Then IMAP client "1" sees the following messages in "Folders/one": + Then IMAP client "1" eventually sees the following messages in "Folders/one": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | - And IMAP client "1" sees 0 messages in "Folders/two" - And IMAP client "1" sees the following messages in "All Mail": + And IMAP client "1" eventually sees 0 messages in "Folders/two" + And IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | When user "[user:user]" connects and authenticates IMAP client "2" with address "[alias:alias]@[domain]" - Then IMAP client "2" sees 0 messages in "Folders/one" - And IMAP client "2" sees the following messages in "Folders/two": + Then IMAP client "2" eventually sees 0 messages in "Folders/one" + And IMAP client "2" eventually sees the following messages in "Folders/two": | from | to | subject | unread | | c@[domain] | c@[domain] | three | true | | d@[domain] | d@[domain] | four | false | - And IMAP client "2" sees the following messages in "All Mail": + And IMAP client "2" eventually sees the following messages in "All Mail": | from | to | subject | unread | | c@[domain] | c@[domain] | three | true | | d@[domain] | d@[domain] | four | false | @@ -80,14 +80,14 @@ Feature: Address mode And the user sets the address mode of user "[user:user]" to "combined" And user "[user:user]" finishes syncing When user "[user:user]" connects and authenticates IMAP client "1" with address "[user:user]@[domain]" - Then IMAP client "1" sees the following messages in "All Mail": + Then IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | | c@[domain] | c@[domain] | three | true | | d@[domain] | d@[domain] | four | false | When user "[user:user]" connects and authenticates IMAP client "2" with address "[alias:alias]@[domain]" - Then IMAP client "2" sees the following messages in "All Mail": + Then IMAP client "2" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | @@ -96,14 +96,14 @@ Feature: Address mode Scenario: The user adds an address while in combined mode When user "[user:user]" connects and authenticates IMAP client "1" with address "[user:user]@[domain]" - Then IMAP client "1" sees the following messages in "All Mail": + Then IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | | c@[domain] | c@[domain] | three | true | | d@[domain] | d@[domain] | four | false | When user "[user:user]" connects and authenticates IMAP client "2" with address "[alias:alias]@[domain]" - Then IMAP client "2" sees the following messages in "All Mail": + Then IMAP client "2" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | @@ -112,7 +112,7 @@ Feature: Address mode Given the account "[user:user]" has additional address "other@[domain]" And bridge sends an address created event for user "[user:user]" When user "[user:user]" connects and authenticates IMAP client "3" with address "other@[domain]" - Then IMAP client "3" sees the following messages in "All Mail": + Then IMAP client "3" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | @@ -123,12 +123,12 @@ Feature: Address mode Given the user sets the address mode of user "[user:user]" to "split" And user "[user:user]" finishes syncing When user "[user:user]" connects and authenticates IMAP client "1" with address "[user:user]@[domain]" - And IMAP client "1" sees the following messages in "All Mail": + And IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | When user "[user:user]" connects and authenticates IMAP client "2" with address "[alias:alias]@[domain]" - And IMAP client "2" sees the following messages in "All Mail": + And IMAP client "2" eventually sees the following messages in "All Mail": | from | to | subject | unread | | c@[domain] | c@[domain] | three | true | | d@[domain] | d@[domain] | four | false | @@ -139,14 +139,14 @@ Feature: Address mode Scenario: The user deletes an address while in combined mode When user "[user:user]" connects and authenticates IMAP client "1" with address "[user:user]@[domain]" - Then IMAP client "1" sees the following messages in "All Mail": + Then IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | | c@[domain] | c@[domain] | three | true | | d@[domain] | d@[domain] | four | false | When user "[user:user]" connects and authenticates IMAP client "2" with address "[alias:alias]@[domain]" - Then IMAP client "2" sees the following messages in "All Mail": + Then IMAP client "2" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | @@ -161,12 +161,12 @@ Feature: Address mode Given the user sets the address mode of user "[user:user]" to "split" And user "[user:user]" finishes syncing When user "[user:user]" connects and authenticates IMAP client "1" with address "[user:user]@[domain]" - And IMAP client "1" sees the following messages in "All Mail": + And IMAP client "1" eventually sees the following messages in "All Mail": | from | to | subject | unread | | a@[domain] | a@[domain] | one | true | | b@[domain] | b@[domain] | two | false | When user "[user:user]" connects and authenticates IMAP client "2" with address "[alias:alias]@[domain]" - And IMAP client "2" sees the following messages in "All Mail": + And IMAP client "2" eventually sees the following messages in "All Mail": | from | to | subject | unread | | c@[domain] | c@[domain] | three | true | | d@[domain] | d@[domain] | four | false | diff --git a/tests/features/user/login.feature b/tests/features/user/login.feature index 3edfdb79..1e512431 100644 --- a/tests/features/user/login.feature +++ b/tests/features/user/login.feature @@ -7,7 +7,7 @@ Feature: A user can login Scenario: Login to account When the user logs in with username "[user:user]" and password "password" - Then user "[user:user]" is listed and connected + Then user "[user:user]" is eventually listed and connected Scenario: Login to account with wrong password When the user logs in with username "[user:user]" and password "wrong" @@ -24,11 +24,11 @@ Feature: A user can login Scenario: Login to account with caps When the user logs in with username "[user:MixedCaps]" and password "password" - Then user "[user:MixedCaps]" is listed and connected + Then user "[user:MixedCaps]" is eventually listed and connected Scenario: Login to account with disabled primary When the user logs in with username "[user:disabled]" and password "password" - Then user "[user:disabled]" is listed and connected + Then user "[user:disabled]" is eventually listed and connected Scenario: Login to account without internet but the connection is later restored When the user logs in with username "[user:user]" and password "password" @@ -42,5 +42,5 @@ Feature: A user can login Given there exists an account with username "[user:additional]" and password "password" When the user logs in with username "[user:user]" and password "password" And the user logs in with username "[user:additional]" and password "password" - Then user "[user:user]" is listed and connected - And user "[user:additional]" is listed and connected \ No newline at end of file + Then user "[user:user]" is eventually listed and connected + And user "[user:additional]" is eventually listed and connected \ No newline at end of file diff --git a/tests/features/user/relogin.feature b/tests/features/user/relogin.feature index 2da7b437..021a6696 100644 --- a/tests/features/user/relogin.feature +++ b/tests/features/user/relogin.feature @@ -8,7 +8,7 @@ Feature: A logged out user can login again When user "[user:user]" logs out And bridge restarts And the user logs in with username "[user:user]" and password "password" - Then user "[user:user]" is listed and connected + Then user "[user:user]" is eventually listed and connected Scenario: Cannot login to removed account When user "[user:user]" is deleted diff --git a/tests/features/user/sync.feature b/tests/features/user/sync.feature index 5f0fbf91..260eea3d 100644 --- a/tests/features/user/sync.feature +++ b/tests/features/user/sync.feature @@ -21,7 +21,7 @@ Feature: Bridge can fully sync an account Then bridge sends sync started and finished events for user "[user:user]" When bridge restarts And user "[user:user]" connects and authenticates IMAP client "1" - Then IMAP client "1" sees the following mailbox info: + Then IMAP client "1" eventually sees the following mailbox info: | name | total | unread | | INBOX | 0 | 0 | | Drafts | 0 | 0 | From 13db1b0db848e3ce4f43ae0dc8847c54e79ce703 Mon Sep 17 00:00:00 2001 From: Romain Le Jeune Date: Tue, 14 Feb 2023 16:27:55 +0000 Subject: [PATCH 049/130] feat(GODT-2356): unify sentry release description and add more context to it. --- Makefile | 8 +++-- cmd/launcher/main.go | 2 +- internal/app/app.go | 2 +- internal/constants/constants.go | 3 ++ .../bridge-gui/bridge-gui/BuildConfig.h.in | 1 + .../bridge-gui/bridge-gui/SentryUtils.cpp | 36 ++++++++++++++++--- .../bridge-gui/bridge-gui/SentryUtils.h | 1 + .../frontend/bridge-gui/bridge-gui/build.ps1 | 7 ++++ .../frontend/bridge-gui/bridge-gui/build.sh | 2 ++ .../frontend/bridge-gui/bridge-gui/main.cpp | 11 ++---- internal/sentry/reporter.go | 28 ++++++++++----- 11 files changed, 75 insertions(+), 26 deletions(-) diff --git a/Makefile b/Makefile index 0d85f5fc..94a50f9b 100644 --- a/Makefile +++ b/Makefile @@ -23,10 +23,10 @@ REVISION:=$(shell git rev-parse --short=10 HEAD) BUILD_TIME:=$(shell date +%FT%T%z) MACOS_MIN_VERSION_ARM64=11.0 MACOS_MIN_VERSION_AMD64=10.15 +BUILD_ENV?=dev BUILD_FLAGS:=-tags='${BUILD_TAGS}' BUILD_FLAGS_LAUNCHER:=${BUILD_FLAGS} -BUILD_FLAGS_GUI:=-tags='${BUILD_TAGS} build_qt' GO_LDFLAGS:=$(addprefix -X github.com/ProtonMail/proton-bridge/v3/internal/constants., Version=${APP_VERSION} Revision=${REVISION} BuildTime=${BUILD_TIME}) GO_LDFLAGS+=-X "github.com/ProtonMail/proton-bridge/v3/internal/constants.FullAppName=${APP_FULL_NAME}" @@ -34,6 +34,10 @@ ifneq "${DSN_SENTRY}" "" GO_LDFLAGS+=-X github.com/ProtonMail/proton-bridge/v3/internal/constants.DSNSentry=${DSN_SENTRY} endif +ifneq "${BUILD_ENV}" "" + GO_LDFLAGS+=-X github.com/ProtonMail/proton-bridge/v3/internal/constants.BuildEnv=${BUILD_ENV} +endif + GO_LDFLAGS_LAUNCHER:=${GO_LDFLAGS} ifeq "${TARGET_OS}" "windows" #GO_LDFLAGS+=-H=windowsgui # Disabled so we can inspect trace logs from the bridge for debugging. @@ -41,7 +45,6 @@ ifeq "${TARGET_OS}" "windows" endif BUILD_FLAGS+=-ldflags '${GO_LDFLAGS}' -BUILD_FLAGS_GUI+=-ldflags "${GO_LDFLAGS}" BUILD_FLAGS_LAUNCHER+=-ldflags '${GO_LDFLAGS_LAUNCHER}' DEPLOY_DIR:=cmd/${TARGET_CMD}/deploy DIRNAME:=$(shell basename ${CURDIR}) @@ -158,6 +161,7 @@ ${EXE_TARGET}: check-build-essentials ${EXE_NAME} BRIDGE_DSN_SENTRY=${DSN_SENTRY} \ BRIDGE_BUILD_TIME=${BUILD_TIME} \ BRIDGE_GUI_BUILD_CONFIG=Release \ + BRIDGE_BUILD_ENV=BUILD_ENV \ BRIDGE_INSTALL_PATH=${ROOT_DIR}/${DEPLOY_DIR}/${GOOS} \ ./build.sh install mv "${ROOT_DIR}/${BRIDGE_EXE}" "$(ROOT_DIR)/${EXE_TARGET}" diff --git a/cmd/launcher/main.go b/cmd/launcher/main.go index f8b1ec98..32acdf6d 100644 --- a/cmd/launcher/main.go +++ b/cmd/launcher/main.go @@ -59,7 +59,7 @@ func main() { //nolint:funlen logrus.SetLevel(logrus.DebugLevel) l := logrus.WithField("launcher_version", constants.Version) - reporter := sentry.NewReporter(appName, constants.Version, useragent.New()) + reporter := sentry.NewReporter(appName, useragent.New()) crashHandler := crash.NewHandler(reporter.ReportException) defer crashHandler.HandlePanic() diff --git a/internal/app/app.go b/internal/app/app.go index 3a259a26..4a30b0ab 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -170,7 +170,7 @@ func run(c *cli.Context) error { identifier := useragent.New() // Create a new Sentry client that will be used to report crashes etc. - reporter := sentry.NewReporter(constants.FullAppName, constants.Version, identifier) + reporter := sentry.NewReporter(constants.FullAppName, identifier) // Determine the exe that should be used to restart/autostart the app. // By default, this is the launcher, if used. Otherwise, we try to get diff --git a/internal/constants/constants.go b/internal/constants/constants.go index 46df9e78..ac2942df 100644 --- a/internal/constants/constants.go +++ b/internal/constants/constants.go @@ -44,6 +44,9 @@ var ( // DSNSentry client keys to be able to report crashes to Sentry. DSNSentry = "" + + // BuildEnv tags used at build time. + BuildEnv = "" ) const ( diff --git a/internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in b/internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in index afcc58a5..2ebdf00d 100644 --- a/internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in +++ b/internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in @@ -25,5 +25,6 @@ #define PROJECT_REVISION "@BRIDGE_REVISION@" #define PROJECT_BUILD_TIME "@BRIDGE_BUILD_TIME@" #define PROJECT_DSN_SENTRY "@BRIDGE_DSN_SENTRY@" +#define PROJECT_BUILD_ENV "@BRIDGE_BUILD_ENV@" #endif // BRIDGE_GUI_VERSION_H diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index e2470412..0a22ad3d 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -31,13 +31,39 @@ QByteArray getProtectedHostname() { return hostname.toHex(); } +QString getApiOS() { +#if defined(Q_OS_DARWIN) + return "macos"; +#elif defined(Q_OS_WINDOWS) + return "windows"; +#else + return "linux"; +#endif +} + +QString appVersion(const QString& version) { + return QString("%1-bridge@%2").arg(getApiOS()).arg(version); +} + void setSentryReportScope() { sentry_set_tag("OS", bridgepp::goos().toUtf8()); sentry_set_tag("Client", PROJECT_FULL_NAME); - sentry_set_tag("Version", PROJECT_VER); - sentry_set_tag("UserAgent", QString("/ (%1)").arg(bridgepp::goos()).toUtf8()); - sentry_set_tag("HostArch", QSysInfo::currentCpuArchitecture().toUtf8()); - sentry_set_tag("server_name", getProtectedHostname()); + sentry_set_tag("Version", QByteArray(PROJECT_REVISION).toHex()); + sentry_set_tag("HostArch", QSysInfo::currentCpuArchitecture().toUtf8()); + sentry_set_tag("server_name", getProtectedHostname()); +} + +sentry_options_t* newSentryOptions(const char *sentryDNS, const char *cacheDir) { + sentry_options_t *sentryOptions = sentry_options_new(); + sentry_options_set_dsn(sentryOptions, sentryDNS); + sentry_options_set_database_path(sentryOptions, cacheDir); + sentry_options_set_release(sentryOptions, appVersion(PROJECT_VER).toUtf8()); + sentry_options_set_max_breadcrumbs(sentryOptions, 50); + sentry_options_set_environment(sentryOptions, PROJECT_BUILD_ENV); + // Enable this for debugging sentry. + // sentry_options_set_debug(sentryOptions, 1); + + return sentryOptions; } sentry_uuid_t reportSentryEvent(sentry_level_t level, const char *message) { @@ -51,3 +77,5 @@ sentry_uuid_t reportSentryException(sentry_level_t level, const char *message, c sentry_event_add_exception(event, sentry_value_new_exception(exceptionType, exception)); return sentry_capture_event(event); } + + diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h index 14ed3824..7b721066 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h @@ -22,6 +22,7 @@ #include void setSentryReportScope(); +sentry_options_t* newSentryOptions(const char * sentryDNS, const char * cacheDir); sentry_uuid_t reportSentryEvent(sentry_level_t level, const char *message); sentry_uuid_t reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception); diff --git a/internal/frontend/bridge-gui/bridge-gui/build.ps1 b/internal/frontend/bridge-gui/bridge-gui/build.ps1 index b11821c3..004b1a54 100644 --- a/internal/frontend/bridge-gui/bridge-gui/build.ps1 +++ b/internal/frontend/bridge-gui/bridge-gui/build.ps1 @@ -79,6 +79,12 @@ $REVISION_HASH = git rev-parse --short=10 HEAD $bridgeDsnSentry = ($env:BRIDGE_DSN_SENTRY) $bridgeBuidTime = ($env:BRIDGE_BUILD_TIME) +$bridgeBuildEnv = ($env:BRIDGE_BUILD_ENV) +if ($null -eq $bridgeBuildEnv) +{ + $bridgeBuildEnv = "dev" +} + git submodule update --init --recursive $vcpkgRoot . $vcpkgBootstrap -disableMetrics . $vcpkgExe install sentry-native:x64-windows grpc:x64-windows --clean-after-build @@ -90,6 +96,7 @@ git submodule update --init --recursive $vcpkgRoot -DBRIDGE_APP_VERSION="$bridgeVersion" ` -DBRIDGE_BUILD_TIME="$bridgeBuidTime" ` -DBRIDGE_DSN_SENTRY="$bridgeDsnSentry" ` + -DBRIDGE_BUILD_ENV="$bridgeBuildEnv" ` -S . -B $buildDir check_exit "CMake failed" diff --git a/internal/frontend/bridge-gui/bridge-gui/build.sh b/internal/frontend/bridge-gui/bridge-gui/build.sh index 832749e2..ed970d37 100755 --- a/internal/frontend/bridge-gui/bridge-gui/build.sh +++ b/internal/frontend/bridge-gui/bridge-gui/build.sh @@ -58,6 +58,7 @@ VCPKG_ROOT="${BRIDGE_REPO_ROOT}/extern/vcpkg" BRIDGE_REVISION=$(git rev-parse --short=10 HEAD) BRIDGE_DSN_SENTRY=${BRIDGE_DSN_SENTRY} BRIDGE_BUILD_TIME=${BRIDGE_BUILD_TIME} +BRIDGE_BUILD_ENV= ${BRIDGE_BUILD_ENV:-"dev"} git submodule update --init --recursive ${VCPKG_ROOT} check_exit "Failed to initialize vcpkg as a submodule." @@ -98,6 +99,7 @@ cmake \ -DBRIDGE_REVISION="${BRIDGE_REVISION}" \ -DBRIDGE_DSN_SENTRY="${BRIDGE_DSN_SENTRY}" \ -DBRIDGE_BRIDGE_TIME="${BRIDGE_BRIDGE_TIME}" \ + -DBRIDGE_BUILD_ENV="${BRIDGE_BUILD_ENV}" \ -DBRIDGE_APP_VERSION="${BRIDGE_APP_VERSION}" "${BRIDGE_CMAKE_MACOS_OPTS}" \ -G Ninja \ -S . \ diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 9d39f9e3..05ab4b25 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -304,15 +304,8 @@ void closeBridgeApp() { //**************************************************************************************************************************************************** int main(int argc, char *argv[]) { // Init sentry. - sentry_options_t *sentryOptions = sentry_options_new(); - sentry_options_set_dsn(sentryOptions, PROJECT_DSN_SENTRY); - { - const QString sentryCachePath = sentryCacheDir(); - sentry_options_set_database_path(sentryOptions, sentryCachePath.toStdString().c_str()); - } - sentry_options_set_release(sentryOptions, QByteArray(PROJECT_REVISION).toHex()); - // Enable this for debugging sentry. - // sentry_options_set_debug(sentryOptions, 1); + sentry_options_t *sentryOptions = newSentryOptions(PROJECT_DSN_SENTRY, sentryCacheDir().toStdString().c_str()); + if (sentry_init(sentryOptions) != 0) { std::cerr << "Failed to initialize sentry" << std::endl; } diff --git a/internal/sentry/reporter.go b/internal/sentry/reporter.go index 33456d56..4705a3c8 100644 --- a/internal/sentry/reporter.go +++ b/internal/sentry/reporter.go @@ -26,6 +26,7 @@ import ( "runtime" "time" + "github.com/Masterminds/semver/v3" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/pkg/restarter" "github.com/getsentry/sentry-go" @@ -37,14 +38,23 @@ var skippedFunctions = []string{} //nolint:gochecknoglobals func init() { //nolint:gochecknoinits sentrySyncTransport := sentry.NewHTTPSyncTransport() sentrySyncTransport.Timeout = time.Second * 3 + appVersion := constants.Version + version, _ := semver.NewVersion(appVersion) + if version != nil { + appVersion = version.Original() + } - if err := sentry.Init(sentry.ClientOptions{ - Dsn: constants.DSNSentry, - Release: constants.Revision, - BeforeSend: EnhanceSentryEvent, - Transport: sentrySyncTransport, - ServerName: getProtectedHostname(), - }); err != nil { + options := sentry.ClientOptions{ + Dsn: constants.DSNSentry, + Release: constants.AppVersion(appVersion), + BeforeSend: EnhanceSentryEvent, + Transport: sentrySyncTransport, + ServerName: getProtectedHostname(), + Environment: constants.BuildEnv, + MaxBreadcrumbs: 50, + } + + if err := sentry.Init(options); err != nil { logrus.WithError(err).Error("Failed to initialize sentry options") } @@ -79,10 +89,10 @@ func getProtectedHostname() string { } // NewReporter creates new sentry reporter with appName and appVersion to report. -func NewReporter(appName, appVersion string, identifier Identifier) *Reporter { +func NewReporter(appName string, identifier Identifier) *Reporter { return &Reporter{ appName: appName, - appVersion: appVersion, + appVersion: constants.Revision, identifier: identifier, hostArch: getHostArch(), } From 08dab2d115a39f57ecf98dfcaeb432a105501bf0 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Wed, 15 Feb 2023 07:37:09 +0000 Subject: [PATCH 050/130] feat(GODT-1264): constraint on Scheduled mailbox in connector + Integration tests. --- go.mod | 2 +- go.sum | 6 ++- internal/bridge/sync_test.go | 45 ---------------------- internal/user/imap.go | 12 ++++-- tests/features/imap/mailbox/list.feature | 25 +++++++++++- tests/features/imap/message/delete.feature | 10 ++++- tests/features/imap/message/move.feature | 16 +++++++- tests/user_test.go | 24 +++++++----- 8 files changed, 74 insertions(+), 66 deletions(-) diff --git a/go.mod b/go.mod index 28168d93..326c92a8 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/gluon v0.14.2-0.20230207142445-9f98ae47a031 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.4.0 + github.com/ProtonMail/go-proton-api v0.4.1-0.20230214130336-4056d48a12e1 github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.4.10 github.com/PuerkitoBio/goquery v1.8.0 diff --git a/go.sum b/go.sum index bf8875d9..a647398c 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,10 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.4.0 h1:Tw8Ieuc355ljPqpIzh/uttpE+5ia0z8GA/ca5iyl/9w= -github.com/ProtonMail/go-proton-api v0.4.0/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230214112101-944a29edf66a h1:/31/wWgxpBWREaRGRMVH4AVgQGpPtTK9BsLjt1a8uwc= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230214112101-944a29edf66a/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230214130336-4056d48a12e1 h1:AjdiuiUwDz9ADIzEccii+D91YYz0w0doGXZs12j4XcY= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230214130336-4056d48a12e1/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= diff --git a/internal/bridge/sync_test.go b/internal/bridge/sync_test.go index db9854ad..329a42c5 100644 --- a/internal/bridge/sync_test.go +++ b/internal/bridge/sync_test.go @@ -24,7 +24,6 @@ import ( "os" "path/filepath" "runtime" - "strings" "sync/atomic" "testing" "time" @@ -44,8 +43,6 @@ import ( "github.com/stretchr/testify/require" ) -const scheduled = "Scheduled" - func TestBridge_Sync(t *testing.T) { numMsg := 1 << 8 @@ -471,45 +468,3 @@ func countBytesRead(ctl *proton.NetCtl, fn func()) uint64 { return read } - -func TestBridge_ScheduledLabel(t *testing.T) { - withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { - hasScheduledSystemLabel := func(imapClient *client.Client) bool { - return xslices.Any(clientList(imapClient), func(mailboxInfo *imap.MailboxInfo) bool { return mailboxInfo.Name == scheduled }) - } - - _, _, err := s.CreateUser(username, password) - require.NoError(t, err) - - withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(b *bridge.Bridge, _ *bridge.Mocks) { - // Perform initial sync - syncCh, done := chToType[events.Event, events.SyncFinished](b.GetEvents(events.SyncFinished{})) - defer done() - userID, err := b.LoginFull(ctx, username, password, nil, nil) - require.NoError(t, err) - require.Equal(t, userID, (<-syncCh).UserID) - - // connect an IMAP client - info, err := b.GetUserInfo(userID) - require.NoError(t, err) - imapClient, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, b.GetIMAPPort())) - require.NoError(t, err) - require.NoError(t, imapClient.Login(info.Addresses[0], string(info.BridgePass))) - defer func() { _ = imapClient.Logout() }() - - // Scheduled mailbox is empty. It's not listed. - require.False(t, hasScheduledSystemLabel(imapClient)) - - // Add a message to the Schedule mailbox. It's now listed. - require.NoError(t, imapClient.Append(scheduled, []string{}, time.Now(), strings.NewReader("To: no_reply@pm.me"))) - require.True(t, hasScheduledSystemLabel(imapClient)) - - // delete message from Scheduled. The mailbox is now empty and not listed anymore - _, err = imapClient.Select(scheduled, false) - require.NoError(t, err) - require.NoError(t, clientStore(imapClient, 1, 1, true, imap.FormatFlagsOp(imap.AddFlags, true), imap.DeletedFlag)) - require.NoError(t, imapClient.Expunge(nil)) - require.False(t, hasScheduledSystemLabel(imapClient)) - }) - }) -} diff --git a/internal/user/imap.go b/internal/user/imap.go index e144f3da..ff1ffcda 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -380,7 +380,7 @@ func (conn *imapConnector) GetMessageLiteral(ctx context.Context, id imap.Messag func (conn *imapConnector) AddMessagesToMailbox(ctx context.Context, messageIDs []imap.MessageID, mailboxID imap.MailboxID) error { defer conn.goPollAPIEvents(false) - if mailboxID == proton.AllMailLabel { + if isAllMailOrScheduled(mailboxID) { return fmt.Errorf("not allowed") } @@ -391,7 +391,7 @@ func (conn *imapConnector) AddMessagesToMailbox(ctx context.Context, messageIDs func (conn *imapConnector) RemoveMessagesFromMailbox(ctx context.Context, messageIDs []imap.MessageID, mailboxID imap.MailboxID) error { defer conn.goPollAPIEvents(false) - if mailboxID == proton.AllMailLabel { + if isAllMailOrScheduled(mailboxID) { return fmt.Errorf("not allowed") } @@ -440,8 +440,8 @@ func (conn *imapConnector) MoveMessages(ctx context.Context, messageIDs []imap.M if (labelFromID == proton.InboxLabel && labelToID == proton.SentLabel) || (labelFromID == proton.SentLabel && labelToID == proton.InboxLabel) || - labelFromID == proton.AllMailLabel || - labelToID == proton.AllMailLabel { + isAllMailOrScheduled(labelFromID) || + isAllMailOrScheduled(labelToID) { return false, fmt.Errorf("not allowed") } @@ -691,3 +691,7 @@ func toIMAPMailbox(label proton.Label, flags, permFlags, attrs imap.FlagSet) ima Attributes: attrs, } } + +func isAllMailOrScheduled(mailboxID imap.MailboxID) bool { + return (mailboxID == proton.AllMailLabel) || (mailboxID == proton.AllScheduledLabel) +} diff --git a/tests/features/imap/mailbox/list.feature b/tests/features/imap/mailbox/list.feature index f93fc15f..ac939363 100644 --- a/tests/features/imap/mailbox/list.feature +++ b/tests/features/imap/mailbox/list.feature @@ -36,4 +36,27 @@ Feature: IMAP list mailboxes Then IMAP client "1" counts 20 mailboxes under "Folders" And IMAP client "1" counts 60 mailboxes under "Labels" Then IMAP client "2" counts 20 mailboxes under "Folders" - And IMAP client "2" counts 60 mailboxes under "Labels" \ No newline at end of file + And IMAP client "2" counts 60 mailboxes under "Labels" + + Scenario: List with scheduled mail + Given there exists an account with username "[user:user]" and password "password" + And the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Scheduled": + | from | to | subject | unread | + | john.doe@mail.com | [user:user]@[domain] | sch | false | + When bridge starts + And the user logs in with username "[user:user]" and password "password" + And user "[user:user]" finishes syncing + And user "[user:user]" connects and authenticates IMAP client "1" + Then IMAP client "1" eventually sees the following mailbox info: + | name | total | + | INBOX | 0 | + | Drafts | 0 | + | Sent | 0 | + | Starred | 0 | + | Archive | 0 | + | Spam | 0 | + | Trash | 0 | + | All Mail | 1 | + | Folders | 0 | + | Labels | 0 | + | Scheduled | 1 | diff --git a/tests/features/imap/message/delete.feature b/tests/features/imap/message/delete.feature index 32e04229..72fcb288 100644 --- a/tests/features/imap/message/delete.feature +++ b/tests/features/imap/message/delete.feature @@ -6,6 +6,7 @@ Feature: IMAP remove messages from mailbox | mbox | folder | | label | label | And the address "[user:user]@[domain]" of account "[user:user]" has 10 messages in "Folders/mbox" + And the address "[user:user]@[domain]" of account "[user:user]" has 1 messages in "Scheduled" And bridge starts And the user logs in with username "[user:user]" and password "password" And user "[user:user]" finishes syncing @@ -44,4 +45,11 @@ Feature: IMAP remove messages from mailbox And IMAP client "1" marks message 2 as deleted And it succeeds And IMAP client "1" expunges - Then it fails \ No newline at end of file + Then it fails + + Scenario: Not possible to delete from Scheduled and expunge does nothing + When IMAP client "1" selects "Scheduled" + And IMAP client "1" marks message 1 as deleted + Then it succeeds + And IMAP client "1" expunges + Then it fails diff --git a/tests/features/imap/message/move.feature b/tests/features/imap/message/move.feature index 289f258a..4c94c303 100644 --- a/tests/features/imap/message/move.feature +++ b/tests/features/imap/message/move.feature @@ -16,6 +16,9 @@ Feature: IMAP move messages And the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Sent": | from | to | subject | unread | | john.doe@mail.com | [user:user]@[domain] | bax | false | + And the address "[user:user]@[domain]" of account "[user:user]" has the following messages in "Scheduled": + | from | to | subject | unread | + | john.doe@mail.com | [user:user]@[domain] | sch | false | And bridge starts And the user logs in with username "[user:user]" and password "password" And user "[user:user]" finishes syncing @@ -96,8 +99,17 @@ Feature: IMAP move messages | jane.doe@mail.com | name@[domain] | bar | true | | john.doe@mail.com | [user:user]@[domain] | baz | false | | john.doe@mail.com | [user:user]@[domain] | bax | false | + | john.doe@mail.com | [user:user]@[domain] | sch | false | - Scenario: Move message from Inbox to Sent is not possible + Scenario: Move message from Scheduled is not possible + Given test skips reporter checks + When IMAP client "1" moves the message with subject "sch" from "Scheduled" to "Inbox" + Then it fails + And IMAP client "1" eventually sees the following messages in "Scheduled": + | from | to | subject | unread | + | john.doe@mail.com | [user:user]@[domain] | sch | false | + + Scenario: Move message from Inbox to Sent is not possible Given test skips reporter checks When IMAP client "1" moves the message with subject "bar" from "Inbox" to "Sent" Then it fails @@ -105,4 +117,4 @@ Feature: IMAP move messages Scenario: Move message from Sent to Inbox is not possible Given test skips reporter checks When IMAP client "1" moves the message with subject "bax" from "Sent" to "Inbox" - Then it fails \ No newline at end of file + Then it fails diff --git a/tests/user_test.go b/tests/user_test.go index 989a914c..3be34f5f 100644 --- a/tests/user_test.go +++ b/tests/user_test.go @@ -193,14 +193,6 @@ func (s *scenario) theAddressOfAccountHasTheFollowingMessagesInMailbox(address, return err } - var messageFlags proton.MessageFlag - - if !strings.EqualFold(mailbox, "Sent") { - messageFlags = proton.MessageFlagReceived - } else { - messageFlags = proton.MessageFlagSent - } - return s.t.createMessages(ctx, username, addrID, xslices.Map(wantMessages, func(message Message) proton.ImportReq { return proton.ImportReq{ @@ -208,7 +200,7 @@ func (s *scenario) theAddressOfAccountHasTheFollowingMessagesInMailbox(address, AddressID: addrID, LabelIDs: []string{mboxID}, Unread: proton.Bool(message.Unread), - Flags: messageFlags, + Flags: flagsForMailbox(mailbox), }, Message: message.Build(), } @@ -228,7 +220,7 @@ func (s *scenario) theAddressOfAccountHasMessagesInMailbox(address, username str Metadata: proton.ImportMetadata{ AddressID: addrID, LabelIDs: []string{mboxID}, - Flags: proton.MessageFlagReceived, + Flags: flagsForMailbox(mailbox), }, Message: Message{ Subject: fmt.Sprintf("%d", idx), @@ -240,6 +232,18 @@ func (s *scenario) theAddressOfAccountHasMessagesInMailbox(address, username str }))) } +func flagsForMailbox(mailboxName string) proton.MessageFlag { + if strings.EqualFold(mailboxName, "Sent") { + return proton.MessageFlagSent + } + + if strings.EqualFold(mailboxName, "Scheduled") { + return proton.MessageFlagScheduledSend + } + + return proton.MessageFlagReceived +} + // accountDraftChanged changes the draft attributes, where draftIndex is // similar to sequential ID i.e. 1 represents the first message of draft folder // sorted by API creation time. From da82d7a107b6cafe20daeb30556953b81a06a06b Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Wed, 15 Feb 2023 10:13:52 +0100 Subject: [PATCH 051/130] fix(GODT-2365): Use predictable remote ID for placeholder mailboxes --- internal/user/sync.go | 6 +++--- internal/user/user.go | 3 +++ 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/internal/user/sync.go b/internal/user/sync.go index a46c81f4..76f9b61e 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -36,7 +36,6 @@ import ( "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/bradenaw/juniper/parallel" "github.com/bradenaw/juniper/xslices" - "github.com/google/uuid" "github.com/pbnjay/memory" "github.com/sirupsen/logrus" "golang.org/x/exp/maps" @@ -59,6 +58,7 @@ func (user *User) syncSystemLabels(ctx context.Context) error { updates = append(updates, update) } } + if err := waitOnIMAPUpdates(ctx, updates); err != nil { return fmt.Errorf("could not sync system labels: %w", err) } @@ -187,7 +187,7 @@ func (user *User) sync(ctx context.Context) error { func syncLabels(ctx context.Context, apiLabels map[string]proton.Label, updateCh ...*queue.QueuedChannel[imap.Update]) error { var updates []imap.Update - // Create placeholder Folders/Labels mailboxes with a random ID and with the \Noselect attribute. + // Create placeholder Folders/Labels mailboxes with the \Noselect attribute. for _, prefix := range []string{folderPrefix, labelPrefix} { for _, updateCh := range updateCh { update := newPlaceHolderMailboxCreatedUpdate(prefix) @@ -698,7 +698,7 @@ func newSystemMailboxCreatedUpdate(labelID imap.MailboxID, labelName string) *im func newPlaceHolderMailboxCreatedUpdate(labelName string) *imap.MailboxCreated { return imap.NewMailboxCreated(imap.Mailbox{ - ID: imap.MailboxID(uuid.NewString()), + ID: imap.MailboxID(labelName), Name: []string{labelName}, Flags: defaultFlags, PermanentFlags: defaultPermanentFlags, diff --git a/internal/user/user.go b/internal/user/user.go index ae85d7a9..65580dcf 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -191,11 +191,14 @@ func New( user.syncAbort.Do(ctx, func(ctx context.Context) { if user.vault.SyncStatus().IsComplete() { user.log.Info("Sync already complete, only system label will be updated") + if err := user.syncSystemLabels(ctx); err != nil { user.log.WithError(err).Error("Failed to update system labels") return } + user.log.Info("System label update complete, starting API event stream") + return } From 7225fc31dab9e97b49a983b72939673f7801595e Mon Sep 17 00:00:00 2001 From: Romain LE JEUNE Date: Wed, 15 Feb 2023 16:10:58 +0100 Subject: [PATCH 052/130] chore: fix sentry tag for dev and release on GUI side. --- Makefile | 2 +- internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 7f7fd117..5aba432d 100644 --- a/Makefile +++ b/Makefile @@ -161,7 +161,7 @@ ${EXE_TARGET}: check-build-essentials ${EXE_NAME} BRIDGE_DSN_SENTRY=${DSN_SENTRY} \ BRIDGE_BUILD_TIME=${BUILD_TIME} \ BRIDGE_GUI_BUILD_CONFIG=Release \ - BRIDGE_BUILD_ENV=BUILD_ENV \ + BRIDGE_BUILD_ENV=${BUILD_ENV} \ BRIDGE_INSTALL_PATH=${ROOT_DIR}/${DEPLOY_DIR}/${GOOS} \ ./build.sh install mv "${ROOT_DIR}/${BRIDGE_EXE}" "$(ROOT_DIR)/${EXE_TARGET}" diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index 0a22ad3d..f273064a 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -48,7 +48,7 @@ QString appVersion(const QString& version) { void setSentryReportScope() { sentry_set_tag("OS", bridgepp::goos().toUtf8()); sentry_set_tag("Client", PROJECT_FULL_NAME); - sentry_set_tag("Version", QByteArray(PROJECT_REVISION).toHex()); + sentry_set_tag("Version", PROJECT_REVISION); sentry_set_tag("HostArch", QSysInfo::currentCpuArchitecture().toUtf8()); sentry_set_tag("server_name", getProtectedHostname()); } From 21b3a4bca3090b3f410caf620e1576890b748e6f Mon Sep 17 00:00:00 2001 From: Romain Le Jeune Date: Wed, 15 Feb 2023 16:11:04 +0000 Subject: [PATCH 053/130] chore: fill sentry user.id with hostname. --- internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp | 3 +++ internal/sentry/reporter.go | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index f273064a..6eabd72a 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -51,6 +51,9 @@ void setSentryReportScope() { sentry_set_tag("Version", PROJECT_REVISION); sentry_set_tag("HostArch", QSysInfo::currentCpuArchitecture().toUtf8()); sentry_set_tag("server_name", getProtectedHostname()); + sentry_value_t user = sentry_value_new_object(); + sentry_value_set_by_key(user, "id", sentry_value_new_string(getProtectedHostname())); + sentry_set_user(user); } sentry_options_t* newSentryOptions(const char *sentryDNS, const char *cacheDir) { diff --git a/internal/sentry/reporter.go b/internal/sentry/reporter.go index a6e433a7..30589da7 100644 --- a/internal/sentry/reporter.go +++ b/internal/sentry/reporter.go @@ -61,7 +61,7 @@ func init() { //nolint:gochecknoinits sentry.ConfigureScope(func(scope *sentry.Scope) { scope.SetFingerprint([]string{"{{ default }}"}) - scope.SetTag("UserID", "not-defined") + scope.SetUser(sentry.User{ID: getProtectedHostname()}) }) sentry.Logger = log.New( From 98fdf45fa35171ef08662ab038c661f50b0bbea4 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Wed, 15 Feb 2023 15:55:23 +0100 Subject: [PATCH 054/130] feat(GODT-2364): added optional details to C++ exceptions. --- .../bridge-gui/bridge-gui/AppController.cpp | 12 ++++++---- .../bridge-gui/bridge-gui/AppController.h | 2 +- .../bridge-gui/bridge-gui/QMLBackend.cpp | 15 +++++------- .../bridge-gui/bridge-gui/QMLBackend.h | 2 +- .../frontend/bridge-gui/bridge-gui/main.cpp | 11 +++++++-- .../bridgepp/bridgepp/Exception/Exception.cpp | 24 ++++++++++++++----- .../bridgepp/bridgepp/Exception/Exception.h | 8 ++++--- .../bridgepp/bridgepp/GRPC/GRPCClient.cpp | 18 +++++++------- .../bridgepp/bridgepp/GRPC/GRPCClient.h | 2 +- .../bridgepp/bridgepp/GRPC/GRPCConfig.cpp | 16 +++++++------ .../bridgepp/bridgepp/GRPC/GRPCUtils.cpp | 11 ++++++--- .../bridgepp/bridgepp/GRPC/GRPCUtils.h | 2 +- 12 files changed, 75 insertions(+), 48 deletions(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp index c745b784..4152d7d9 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp @@ -73,13 +73,17 @@ ProcessMonitor *AppController::bridgeMonitor() const { //**************************************************************************************************************************************************** /// \param[in] function The function that caught the exception. /// \param[in] message The error message. +/// \param[in] details The details for the error. //**************************************************************************************************************************************************** -void AppController::onFatalError(QString const &function, QString const &message) { - QString const fullMessage = QString("%1(): %2").arg(function, message); - auto uuid = reportSentryException(SENTRY_LEVEL_ERROR, "AppController got notified of a fatal error", "Exception", fullMessage.toLocal8Bit()); +void AppController::onFatalError(QString const &function, QString const &message, QString const& details) { + QString fullMessage = QString("%1(): %2").arg(function, message); + if (!details.isEmpty()) + fullMessage += "\n\nDetails:\n" + details; + sentry_uuid_s const uuid = reportSentryException(SENTRY_LEVEL_ERROR, "AppController got notified of a fatal error", "Exception", + fullMessage.toLocal8Bit()); QMessageBox::critical(nullptr, tr("Error"), message); restart(true); - log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex()).arg(fullMessage)); + log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex(), fullMessage)); qApp->exit(EXIT_FAILURE); } diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.h b/internal/frontend/bridge-gui/bridge-gui/AppController.h index 224857c1..cba3bebd 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.h +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.h @@ -58,7 +58,7 @@ public: // member functions. void setLauncherArgs(const QString& launcher, const QStringList& args); public slots: - void onFatalError(QString const &function, QString const &message); ///< Handle fatal errors. + void onFatalError(QString const &function, QString const &message, QString const& details); ///< Handle fatal errors. private: // member functions AppController(); ///< Default constructor. diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp index d731f5b8..c8b00bcf 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp @@ -25,8 +25,8 @@ #define HANDLE_EXCEPTION(x) try { x } \ - catch (Exception const &e) { emit fatalError(__func__, e.qwhat()); } \ - catch (...) { emit fatalError(__func__, QString("An unknown exception occurred")); } + catch (Exception const &e) { emit fatalError(__func__, e.qwhat(), e.details()); } \ + catch (...) { emit fatalError(__func__, QString("An unknown exception occurred"), QString()); } #define HANDLE_EXCEPTION_RETURN_BOOL(x) HANDLE_EXCEPTION(x) return false; #define HANDLE_EXCEPTION_RETURN_QSTRING(x) HANDLE_EXCEPTION(x) return QString(); #define HANDLE_EXCEPTION_RETURN_ZERO(x) HANDLE_EXCEPTION(x) return 0; @@ -56,12 +56,8 @@ void QMLBackend::init(GRPCConfig const &serviceConfig) { app().grpc().setLog(&log); this->connectGrpcEvents(); - QString error; - if (app().grpc().connectToServer(serviceConfig, app().bridgeMonitor(), error)) { - app().log().info("Connected to backend via gRPC service."); - } else { - throw Exception(QString("Cannot connectToServer to go backend via gRPC: %1").arg(error)); - } + app().grpc().connectToServer(serviceConfig, app().bridgeMonitor()); + app().log().info("Connected to backend via gRPC service."); QString bridgeVer; app().grpc().version(bridgeVer); @@ -598,7 +594,8 @@ void QMLBackend::setDiskCachePath(QUrl const &path) const { void QMLBackend::login(QString const &username, QString const &password) const { HANDLE_EXCEPTION( if (username.compare("coco@bandicoot", Qt::CaseInsensitive) == 0) { - throw Exception("User requested bridge-gui to crash by trying to log as coco@bandicoot"); + throw Exception("User requested bridge-gui to crash by trying to log as coco@bandicoot", + "This error exists for test purposes and should be ignored."); } app().grpc().login(username, password); ) diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h index 46338817..d5ff668b 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h @@ -237,7 +237,7 @@ signals: // Signals received from the Go backend, to be forwarded to QML void imapLoginWhileSignedOut(QString const& username); ///< Signal for the notification of IMAP login attempt on a signed out account. // This signal is emitted when an exception is intercepted is calls triggered by QML. QML engine would intercept the exception otherwise. - void fatalError(QString const &function, QString const &message) const; ///< Signal emitted when an fatal error occurs. + void fatalError(QString const &function, QString const &message, QString const &details) const; ///< Signal emitted when an fatal error occurs. private: // member functions void retrieveUserList(); ///< Retrieve the list of users via gRPC. diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 05ab4b25..4372a3df 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -434,9 +434,16 @@ int main(int argc, char *argv[]) { return result; } catch (Exception const &e) { - auto uuid = reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during main", "Exception", e.what()); + QString fullMessage = e.qwhat(); + bool const hasDetails = !e.details().isEmpty(); + if (hasDetails) + fullMessage += "\n\nDetails:\n" + e.details(); + sentry_uuid_s const uuid = reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during main", "Exception", fullMessage.toLocal8Bit()); QMessageBox::critical(nullptr, "Error", e.qwhat()); - QTextStream(stderr) << "reportID: " << QByteArray(uuid.bytes, 16).toHex() << "Captured exception :" << e.qwhat() << "\n"; + QTextStream errStream(stderr); + errStream << "reportID: " << QByteArray(uuid.bytes, 16).toHex() << " Captured exception :" << e.qwhat() << "\n"; + if (hasDetails) + errStream << "\nDetails:\n" << e.details() << "\n"; return EXIT_FAILURE; } } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp index 42c27355..a9179038 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp @@ -23,11 +23,13 @@ namespace bridgepp { //**************************************************************************************************************************************************** -/// \param[in] what A description of the exception +/// \param[in] what A description of the exception. +/// \param[in] details The optional details for the exception. //**************************************************************************************************************************************************** -Exception::Exception(QString what) noexcept +Exception::Exception(QString what, QString details) noexcept : std::exception() - , what_(std::move(what)) { + , what_(std::move(what)) + , details_(std::move(details)) { } @@ -36,7 +38,8 @@ Exception::Exception(QString what) noexcept //**************************************************************************************************************************************************** Exception::Exception(Exception const &ref) noexcept : std::exception(ref) - , what_(ref.what_) { + , what_(ref.what_) + , details_(ref.details_) { } @@ -45,14 +48,15 @@ Exception::Exception(Exception const &ref) noexcept //**************************************************************************************************************************************************** Exception::Exception(Exception &&ref) noexcept : std::exception(ref) - , what_(ref.what_) { + , what_(ref.what_) + , details_(ref.details_) { } //**************************************************************************************************************************************************** /// \return a string describing the exception //**************************************************************************************************************************************************** -QString const &Exception::qwhat() const noexcept { +QString Exception::qwhat() const noexcept { return what_; } @@ -65,4 +69,12 @@ const char *Exception::what() const noexcept { } +//**************************************************************************************************************************************************** +/// \return The details for the exception. +//**************************************************************************************************************************************************** +QString Exception::details() const noexcept { + return details_; +} + + } // namespace bridgepp diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h index 6f755ea4..9cde3e7d 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h @@ -31,17 +31,19 @@ namespace bridgepp { //**************************************************************************************************************************************************** class Exception : public std::exception { public: // member functions - explicit Exception(QString what = QString()) noexcept; ///< Constructor + explicit Exception(QString what = QString(), QString details = QString()) noexcept; ///< Constructor Exception(Exception const &ref) noexcept; ///< copy constructor Exception(Exception &&ref) noexcept; ///< copy constructor Exception &operator=(Exception const &) = delete; ///< Disabled assignment operator Exception &operator=(Exception &&) = delete; ///< Disabled assignment operator ~Exception() noexcept override = default; ///< Destructor - QString const &qwhat() const noexcept; ///< Return the description of the exception as a QString + QString qwhat() const noexcept; ///< Return the description of the exception as a QString const char *what() const noexcept override; ///< Return the description of the exception as C style string + QString details() const noexcept; ///< Return the details for the exception private: // data members - QString const what_; ///< The description of the exception + QString const what_; ///< The description of the exception. + QString const details_; ///< The optional details for the exception. }; diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp index 85fb3845..b27b9857 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp @@ -88,8 +88,9 @@ GRPCConfig GRPCClient::waitAndRetrieveServiceConfig(qint64 timeoutMs, ProcessMon } GRPCConfig sc; - if (!sc.load(path)) { - throw Exception("The gRPC service configuration file is invalid."); + QString err; + if (!sc.load(path, &err)) { + throw Exception("The gRPC service configuration file is invalid.", err); } return sc; @@ -105,11 +106,10 @@ void GRPCClient::setLog(Log *log) { //**************************************************************************************************************************************************** -/// \param[out] outError If the function returns false, this variable contains a description of the error. /// \param[in] serverProcess An optional server process to monitor. If the process it, no need and retry, as connexion cannot be established. Ignored if null. /// \return true iff the connection was successful. //**************************************************************************************************************************************************** -bool GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serverProcess, QString &outError) { +void GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serverProcess) { try { serverToken_ = config.token.toStdString(); QString address; @@ -158,9 +158,10 @@ bool GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serve this->logInfo("Successfully connected to gRPC server."); QString const clientToken = QUuid::createUuid().toString(); - QString clientConfigPath = createClientConfigFile(clientToken); + QString error; + QString clientConfigPath = createClientConfigFile(clientToken, &error); if (clientConfigPath.isEmpty()) { - throw Exception("gRPC client config could not be saved."); + throw Exception("gRPC client config could not be saved.", error); } this->logInfo(QString("Client config file was saved to '%1'").arg(QDir::toNativeSeparators(clientConfigPath))); @@ -176,12 +177,9 @@ bool GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serve } log_->info("gRPC token was validated"); - - return true; } catch (Exception const &e) { - outError = e.qwhat(); - return false; + throw Exception("Cannot connect to Go backend via gRPC: " + e.qwhat(), e.details()); } } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h index 9d883cef..0791c4cd 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h @@ -59,7 +59,7 @@ public: // member functions. GRPCClient &operator=(GRPCClient const &) = delete; ///< Disabled assignment operator. GRPCClient &operator=(GRPCClient &&) = delete; ///< Disabled move assignment operator. void setLog(Log *log); ///< Set the log for the client. - bool connectToServer(GRPCConfig const &config, class ProcessMonitor *serverProcess, QString &outError); ///< Establish connection to the gRPC server. + void connectToServer(GRPCConfig const &config, class ProcessMonitor *serverProcess); ///< Establish connection to the gRPC server. grpc::Status checkTokens(QString const &clientConfigPath, QString &outReturnedClientToken); ///< Performs a token check. grpc::Status addLogEntry(Log::Level level, QString const &package, QString const &message); ///< Performs the "AddLogEntry" gRPC call. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCConfig.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCConfig.cpp index 1fda5eff..7092d539 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCConfig.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCConfig.cpp @@ -25,8 +25,7 @@ using namespace bridgepp; namespace { -Exception const invalidFileException("The service configuration file is invalid"); // Exception for invalid config. -Exception const couldNotSaveException("The service configuration file could not be saved"); ///< Exception for write errors. +Exception const invalidFileException("The content of the service configuration file is invalid"); // Exception for invalid config. QString const keyPort = "port"; ///< The JSON key for the port. QString const keyCert = "cert"; ///< The JSON key for the TLS certificate. QString const keyToken = "token"; ///< The JSON key for the identification token. @@ -78,8 +77,11 @@ qint32 jsonIntValue(QJsonObject const &object, QString const &key) { bool GRPCConfig::load(QString const &path, QString *outError) { try { QFile file(path); + if (!file.exists()) + throw Exception("The file service configuration file does not exist."); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - throw Exception("Could not open gRPC service config file."); + throw Exception("The file exists but cannot be opened."); } QJsonDocument const doc = QJsonDocument::fromJson(file.readAll()); @@ -93,7 +95,7 @@ bool GRPCConfig::load(QString const &path, QString *outError) { } catch (Exception const &e) { if (outError) { - *outError = e.qwhat(); + *outError = QString("Error loading gRPC service configuration file '%1'.\n%2").arg(QFileInfo(path).absoluteFilePath(), e.qwhat()); } return false; } @@ -115,19 +117,19 @@ bool GRPCConfig::save(QString const &path, QString *outError) { QFile file(path); if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) { - throw couldNotSaveException; + throw Exception("The file could not be opened for writing."); } QByteArray const array = QJsonDocument(object).toJson(); if (array.size() != file.write(array)) { - throw couldNotSaveException; + throw Exception("An error occurred while writing to the file."); } return true; } catch (Exception const &e) { if (outError) { - *outError = e.qwhat(); + *outError = QString("Error saving gRPC service configuration file '%1'.\n%2").arg(QFileInfo(path).absoluteFilePath(), e.qwhat()); } return false; } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.cpp index ebcce011..b651ae54 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.cpp @@ -76,10 +76,12 @@ QString grpcClientConfigBasePath() { //**************************************************************************************************************************************************** /// \param[in] token The token to put in the file. +/// \param[out] outError if the function returns an empty string and this pointer is not null, the pointer variable holds a description of the error +/// on exit. /// \return The path of the created file. -/// \return A null string if the file could not be saved.. +/// \return A null string if the file could not be saved. //**************************************************************************************************************************************************** -QString createClientConfigFile(QString const &token) { +QString createClientConfigFile(QString const &token, QString *outError) { QString const basePath = grpcClientConfigBasePath(); QString path, error; for (qint32 i = 0; i < 1000; ++i) // we try a decent amount of times @@ -88,13 +90,16 @@ QString createClientConfigFile(QString const &token) { if (!QFileInfo(path).exists()) { GRPCConfig config; config.token = token; - if (!config.save(path)) { + + if (!config.save(path, outError)) { return QString(); } return path; } } + if (outError) + *outError = "no usable client configuration file name could be found."; return QString(); } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h index 8cc9dcbc..844ec4c5 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h @@ -36,7 +36,7 @@ typedef std::shared_ptr SPStreamEvent; ///< Type definition f QString grpcServerConfigPath(); ///< Return the path of the gRPC server config file. QString grpcClientConfigBasePath(); ///< Return the path of the gRPC client config file. -QString createClientConfigFile(QString const &token); ///< Create the client config file the server will retrieve and return its path. +QString createClientConfigFile(QString const &token, QString *outError); ///< Create the client config file the server will retrieve and return its path. grpc::LogLevel logLevelToGRPC(Log::Level level); ///< Convert a Log::Level to gRPC enum value. Log::Level logLevelFromGRPC(grpc::LogLevel level); ///< Convert a grpc::LogLevel to a Log::Level. grpc::UserState userStateToGRPC(UserState state); ///< Convert a bridgepp::UserState to a grpc::UserState. From 0207fa04f1630cac520a78b332ca3efc6b8b1edf Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Wed, 15 Feb 2023 17:56:56 +0100 Subject: [PATCH 055/130] feat(GODT-2364): wait and retry once if the gRPC service config file exists but cannot be opened. --- .../bridge-gui/bridgepp/bridgepp/GRPC/GRPCConfig.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCConfig.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCConfig.cpp index 7092d539..17414112 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCConfig.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCConfig.cpp @@ -78,10 +78,13 @@ bool GRPCConfig::load(QString const &path, QString *outError) { try { QFile file(path); if (!file.exists()) - throw Exception("The file service configuration file does not exist."); + throw Exception("The gRPC service configuration file does not exist."); if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { - throw Exception("The file exists but cannot be opened."); + QThread::msleep(500); // we wait a bit and retry once, just in case server is not done writing/moving the config file. + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { + throw Exception("The gRPC service configuration file exists but cannot be opened."); + } } QJsonDocument const doc = QJsonDocument::fromJson(file.readAll()); From 571133f2ff74d802bda13be37c6386285070ed3c Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Wed, 15 Feb 2023 17:28:31 +0100 Subject: [PATCH 056/130] chore: added bridge-gui CMake variable for crashpad_handler path. Ignored in release mode. --- .../bridge-gui/bridge-gui/BuildConfig.h.in | 15 ++++++++------- internal/frontend/bridge-gui/bridge-gui/main.cpp | 2 ++ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in b/internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in index 2ebdf00d..cc05b229 100644 --- a/internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in +++ b/internal/frontend/bridge-gui/bridge-gui/BuildConfig.h.in @@ -19,12 +19,13 @@ #ifndef BRIDGE_GUI_VERSION_H #define BRIDGE_GUI_VERSION_H -#define PROJECT_FULL_NAME "@BRIDGE_APP_FULL_NAME@" -#define PROJECT_VENDOR "@BRIDGE_VENDOR@" -#define PROJECT_VER "@BRIDGE_APP_VERSION@" -#define PROJECT_REVISION "@BRIDGE_REVISION@" -#define PROJECT_BUILD_TIME "@BRIDGE_BUILD_TIME@" -#define PROJECT_DSN_SENTRY "@BRIDGE_DSN_SENTRY@" -#define PROJECT_BUILD_ENV "@BRIDGE_BUILD_ENV@" +#define PROJECT_FULL_NAME "@BRIDGE_APP_FULL_NAME@" +#define PROJECT_VENDOR "@BRIDGE_VENDOR@" +#define PROJECT_VER "@BRIDGE_APP_VERSION@" +#define PROJECT_REVISION "@BRIDGE_REVISION@" +#define PROJECT_BUILD_TIME "@BRIDGE_BUILD_TIME@" +#define PROJECT_DSN_SENTRY "@BRIDGE_DSN_SENTRY@" +#define PROJECT_BUILD_ENV "@BRIDGE_BUILD_ENV@" +#define PROJECT_CRASHPAD_HANDLER_PATH "@BRIDGE_CRASHPAD_HANDLER_PATH@" #endif // BRIDGE_GUI_VERSION_H diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 4372a3df..b0354ff7 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -305,6 +305,8 @@ void closeBridgeApp() { int main(int argc, char *argv[]) { // Init sentry. sentry_options_t *sentryOptions = newSentryOptions(PROJECT_DSN_SENTRY, sentryCacheDir().toStdString().c_str()); + if (!QString(PROJECT_CRASHPAD_HANDLER_PATH).isEmpty()) + sentry_options_set_handler_path(sentryOptions, PROJECT_CRASHPAD_HANDLER_PATH); if (sentry_init(sentryOptions) != 0) { std::cerr << "Failed to initialize sentry" << std::endl; From 4c24c004db8ea3ecc483720522120414e890cf93 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Thu, 16 Feb 2023 16:31:20 +0100 Subject: [PATCH 057/130] fix(GODT-2371): Continue, not return, when handling draft --- internal/bridge/user_event_test.go | 85 ++++++++++++++++++++++++++++++ internal/user/events.go | 2 +- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/internal/bridge/user_event_test.go b/internal/bridge/user_event_test.go index e7a02a28..5b463a7a 100644 --- a/internal/bridge/user_event_test.go +++ b/internal/bridge/user_event_test.go @@ -22,17 +22,20 @@ import ( "fmt" "net" "net/http" + "net/mail" "strings" "sync/atomic" "testing" "time" + "github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/user" + "github.com/bradenaw/juniper/stream" "github.com/bradenaw/juniper/xslices" "github.com/emersion/go-imap" "github.com/emersion/go-imap/client" @@ -349,6 +352,88 @@ func TestBridge_User_DropConn_NoBadEvent(t *testing.T) { }, server.WithListener(dropListener)) } +func TestBridge_User_UpdateDraftAndCreateOtherMessage(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + // Create a bridge user. + _, _, err := s.CreateUser("user", password) + require.NoError(t, err) + + // Initially sync the user. + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + userLoginAndSync(ctx, t, bridge, "user", password) + }) + + withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { + user, err := c.GetUser(ctx) + require.NoError(t, err) + + addrs, err := c.GetAddresses(ctx) + require.NoError(t, err) + + salts, err := c.GetSalts(ctx) + require.NoError(t, err) + + keyPass, err := salts.SaltForKey(password, user.Keys.Primary().ID) + require.NoError(t, err) + + _, addrKRs, err := proton.Unlock(user, addrs, keyPass) + require.NoError(t, err) + + // Create a draft (generating a "create draft message" event). + draft, err := c.CreateDraft(ctx, addrKRs[addrs[0].ID], proton.CreateDraftReq{ + Message: proton.DraftTemplate{ + Subject: "subject", + Sender: &mail.Address{Name: "sender", Address: addrs[0].Email}, + Body: "body", + MIMEType: rfc822.TextPlain, + }, + }) + require.NoError(t, err) + + // Process those events + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + userContinueEventProcess(ctx, t, s, bridge) + }) + + // Update the draft (generating an "update draft message" event). + require.NoError(t, getErr(c.UpdateDraft(ctx, draft.ID, addrKRs[addrs[0].ID], proton.UpdateDraftReq{ + Message: proton.DraftTemplate{ + Subject: "subject 2", + Sender: &mail.Address{Name: "sender", Address: addrs[0].Email}, + Body: "body 2", + MIMEType: rfc822.TextPlain, + }, + }))) + + // Import a message (generating a "create message" event). + str, err := c.ImportMessages(ctx, addrKRs[addrs[0].ID], 1, 1, proton.ImportReq{ + Metadata: proton.ImportMetadata{ + AddressID: addrs[0].ID, + Flags: proton.MessageFlagReceived, + }, + Message: []byte("From: someone@example.com\r\nTo: blabla@example.com\r\n\r\nhello"), + }) + require.NoError(t, err) + + res, err := stream.Collect(ctx, str) + require.NoError(t, err) + + // Process those events. + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + userContinueEventProcess(ctx, t, s, bridge) + }) + + // Update the imported message (generating an "update message" event). + require.NoError(t, c.MarkMessagesUnread(ctx, res[0].MessageID)) + + // Process those events. + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + userContinueEventProcess(ctx, t, s, bridge) + }) + }) + }) +} + // userLoginAndSync logs in user and waits until user is fully synced. func userLoginAndSync( ctx context.Context, diff --git a/internal/user/events.go b/internal/user/events.go index 1c88864e..37e80352 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -456,7 +456,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto return err } - return nil + continue } // GODT-2028 - Use better events here. It should be possible to have 3 separate events that refrain to From cac0cf35f6abf2e0f718d7e9aac69cdfdb14aaba Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Fri, 17 Feb 2023 14:06:15 +0100 Subject: [PATCH 058/130] feat(GODT-2361): Bump GPA to use simple encrypter --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 326c92a8..0b294f22 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.1.1 github.com/ProtonMail/gluon v0.14.2-0.20230207142445-9f98ae47a031 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.4.1-0.20230214130336-4056d48a12e1 + github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.4.10 github.com/PuerkitoBio/goquery v1.8.0 diff --git a/go.sum b/go.sum index b19daeef..d5f3d841 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NB github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230214130336-4056d48a12e1 h1:AjdiuiUwDz9ADIzEccii+D91YYz0w0doGXZs12j4XcY= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230214130336-4056d48a12e1/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 h1:R78tKuV4FnTILa/yCx8+9lvKMl3ZA6gduM10inz7pSc= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= From 54c013012e2222b2e09eaafb003a3eaffcd4171f Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Fri, 17 Feb 2023 14:02:39 +0100 Subject: [PATCH 059/130] feat(GODT-2374): Import TLS certs via shell --- internal/app/vault.go | 4 ++- internal/bridge/bridge.go | 2 +- internal/bridge/tls.go | 6 +++- internal/frontend/cli/frontend.go | 12 ++++--- internal/frontend/cli/system.go | 30 +++++++++++++++++ internal/vault/certs.go | 54 ++++++++++++++++++++++++++++--- internal/vault/certs_test.go | 5 +-- internal/vault/types_certs.go | 4 +++ 8 files changed, 104 insertions(+), 13 deletions(-) diff --git a/internal/app/vault.go b/internal/app/vault.go index d49be879..895e320d 100644 --- a/internal/app/vault.go +++ b/internal/app/vault.go @@ -51,7 +51,9 @@ func WithVault(locations *locations.Locations, fn func(*vault.Vault, bool, bool) if installed := encVault.GetCertsInstalled(); !installed { logrus.Debug("Installing certificates") - if err := certs.NewInstaller().InstallCert(encVault.GetBridgeTLSCert()); err != nil { + certPEM, _ := encVault.GetBridgeTLSCert() + + if err := certs.NewInstaller().InstallCert(certPEM); err != nil { return fmt.Errorf("failed to install certs: %w", err) } diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index e08d4308..27cde2a4 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -556,7 +556,7 @@ func (bridge *Bridge) onStatusDown(ctx context.Context) { } func loadTLSConfig(vault *vault.Vault) (*tls.Config, error) { - cert, err := tls.X509KeyPair(vault.GetBridgeTLSCert(), vault.GetBridgeTLSKey()) + cert, err := tls.X509KeyPair(vault.GetBridgeTLSCert()) if err != nil { return nil, err } diff --git a/internal/bridge/tls.go b/internal/bridge/tls.go index b62e3470..c5e50fce 100644 --- a/internal/bridge/tls.go +++ b/internal/bridge/tls.go @@ -18,5 +18,9 @@ package bridge func (bridge *Bridge) GetBridgeTLSCert() ([]byte, []byte) { - return bridge.vault.GetBridgeTLSCert(), bridge.vault.GetBridgeTLSKey() + return bridge.vault.GetBridgeTLSCert() +} + +func (bridge *Bridge) SetBridgeTLSCertPath(certPath, keyPath string) error { + return bridge.vault.SetBridgeTLSCertPath(certPath, keyPath) } diff --git a/internal/frontend/cli/frontend.go b/internal/frontend/cli/frontend.go index e22856ca..07719c4f 100644 --- a/internal/frontend/cli/frontend.go +++ b/internal/frontend/cli/frontend.go @@ -135,12 +135,16 @@ func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan e fe.AddCmd(configureCmd) // TLS commands. - exportTLSCmd := &ishell.Cmd{ - Name: "export-tls", + fe.AddCmd(&ishell.Cmd{ + Name: "export-tls-cert", Help: "Export the TLS certificate used by the Bridge", Func: fe.exportTLSCerts, - } - fe.AddCmd(exportTLSCmd) + }) + fe.AddCmd(&ishell.Cmd{ + Name: "import-tls-cert", + Help: "Import a TLS certificate to be used by the Bridge", + Func: fe.importTLSCerts, + }) // All mail visibility commands. allMailCmd := &ishell.Cmd{ diff --git a/internal/frontend/cli/system.go b/internal/frontend/cli/system.go index c92df83f..dc1b12ca 100644 --- a/internal/frontend/cli/system.go +++ b/internal/frontend/cli/system.go @@ -226,6 +226,27 @@ func (f *frontendCLI) exportTLSCerts(c *ishell.Context) { } } +func (f *frontendCLI) importTLSCerts(c *ishell.Context) { + certPath := f.readStringInAttempts("Enter the path to the cert.pem file", c.ReadLine, f.isFile) + if certPath == "" { + f.printAndLogError(errors.New("failed to get cert path")) + return + } + + keyPath := f.readStringInAttempts("Enter the path to the key.pem file", c.ReadLine, f.isFile) + if keyPath == "" { + f.printAndLogError(errors.New("failed to get key path")) + return + } + + if err := f.bridge.SetBridgeTLSCertPath(certPath, keyPath); err != nil { + f.printAndLogError(err) + return + } + + f.Println("TLS certificate imported. Restart Bridge to use it.") +} + func (f *frontendCLI) isPortFree(port string) bool { port = strings.ReplaceAll(port, ":", "") if port == "" { @@ -252,3 +273,12 @@ func (f *frontendCLI) isCacheLocationUsable(location string) bool { return stat.IsDir() } + +func (f *frontendCLI) isFile(location string) bool { + stat, err := os.Stat(location) + if err != nil { + return false + } + + return !stat.IsDir() +} diff --git a/internal/vault/certs.go b/internal/vault/certs.go index 77086f9b..75294293 100644 --- a/internal/vault/certs.go +++ b/internal/vault/certs.go @@ -17,12 +17,40 @@ package vault -func (vault *Vault) GetBridgeTLSCert() []byte { - return vault.get().Certs.Bridge.Cert +import ( + "crypto/tls" + "fmt" + "os" + "path/filepath" + + "github.com/sirupsen/logrus" +) + +// GetBridgeTLSCert returns the PEM-encoded certificate for the bridge. +// If CertPEMPath is set, it will attempt to read the certificate from the file. +// Otherwise, or on read/validation failure, it will return the certificate from the vault. +func (vault *Vault) GetBridgeTLSCert() ([]byte, []byte) { + if certPath, keyPath := vault.get().Certs.CustomCertPath, vault.get().Certs.CustomKeyPath; certPath != "" && keyPath != "" { + if certPEM, keyPEM, err := readPEMCert(certPath, keyPath); err == nil { + return certPEM, keyPEM + } + + logrus.Error("Failed to read certificate from file, using default") + } + + return vault.get().Certs.Bridge.Cert, vault.get().Certs.Bridge.Key } -func (vault *Vault) GetBridgeTLSKey() []byte { - return vault.get().Certs.Bridge.Key +// SetBridgeTLSCertPath sets the path to PEM-encoded certificates for the bridge. +func (vault *Vault) SetBridgeTLSCertPath(certPath, keyPath string) error { + if _, _, err := readPEMCert(certPath, keyPath); err != nil { + return fmt.Errorf("invalid certificate: %w", err) + } + + return vault.mod(func(data *Data) { + data.Certs.CustomCertPath = certPath + data.Certs.CustomKeyPath = keyPath + }) } func (vault *Vault) GetCertsInstalled() bool { @@ -34,3 +62,21 @@ func (vault *Vault) SetCertsInstalled(installed bool) error { data.Certs.Installed = installed }) } + +func readPEMCert(certPEMPath, keyPEMPath string) ([]byte, []byte, error) { + certPEM, err := os.ReadFile(filepath.Clean(certPEMPath)) + if err != nil { + return nil, nil, err + } + + keyPEM, err := os.ReadFile(filepath.Clean(keyPEMPath)) + if err != nil { + return nil, nil, err + } + + if _, err := tls.X509KeyPair(certPEM, keyPEM); err != nil { + return nil, nil, err + } + + return certPEM, keyPEM, nil +} diff --git a/internal/vault/certs_test.go b/internal/vault/certs_test.go index 243b575f..0a3d7fde 100644 --- a/internal/vault/certs_test.go +++ b/internal/vault/certs_test.go @@ -28,8 +28,9 @@ func TestVault_TLSCerts(t *testing.T) { s := newVault(t) // Check the default bridge TLS certs. - require.NotEmpty(t, s.GetBridgeTLSCert()) - require.NotEmpty(t, s.GetBridgeTLSKey()) + cert, key := s.GetBridgeTLSCert() + require.NotEmpty(t, cert) + require.NotEmpty(t, key) // Check the certificates are not installed. require.False(t, s.GetCertsInstalled()) diff --git a/internal/vault/types_certs.go b/internal/vault/types_certs.go index b478199d..195a43a1 100644 --- a/internal/vault/types_certs.go +++ b/internal/vault/types_certs.go @@ -22,6 +22,10 @@ import "github.com/ProtonMail/proton-bridge/v3/internal/certs" type Certs struct { Bridge Cert Installed bool + + // If non-empty, the path to the PEM-encoded certificate file. + CustomCertPath string + CustomKeyPath string } type Cert struct { From 6a9f6a173a6e14078af4f19c8bcd055cef7a41ef Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Fri, 17 Feb 2023 14:45:24 +0100 Subject: [PATCH 060/130] feat(GODT-2201): Bump Gluon to use pure Go IMAP parser --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 0b294f22..60a41da3 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230207142445-9f98ae47a031 + github.com/ProtonMail/gluon v0.14.2-0.20230217111735-c6aa35929f2e github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index d5f3d841..8b1b5f23 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230207142445-9f98ae47a031 h1:QxHAyLmGqBtxTybgDwXwqvcA8auTcTGo8ivcEh2IIr8= -github.com/ProtonMail/gluon v0.14.2-0.20230207142445-9f98ae47a031/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230217111735-c6aa35929f2e h1:WWFhucLz1VeNLggqD/Jw14FwQ47TK8rgboSo+Ttu5qk= +github.com/ProtonMail/gluon v0.14.2-0.20230217111735-c6aa35929f2e/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= From cf8284a48929364875b7b15e0d73f40f7f6da074 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Mon, 20 Feb 2023 11:16:50 +0100 Subject: [PATCH 061/130] fix(GODT-2380): Only set external ID in header if non-empty --- pkg/message/build.go | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/pkg/message/build.go b/pkg/message/build.go index a6b893f1..f6bfbc0a 100644 --- a/pkg/message/build.go +++ b/pkg/message/build.go @@ -479,7 +479,9 @@ func getMessageHeader(msg proton.Message, opts JobOptions) message.Header { // Set our external ID if requested. // This was useful during debugging of applemail recovered messages; doesn't help with any behaviour. if opts.AddExternalID { - hdr.Set("X-Pm-External-Id", "<"+msg.ExternalID+">") + if msg.ExternalID != "" { + hdr.Set("X-Pm-External-Id", "<"+msg.ExternalID+">") + } } // Set our server date if requested. From a741ffb59597268aabfd539c0c86a7592aa3e9c9 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Fri, 17 Feb 2023 16:47:35 +0100 Subject: [PATCH 062/130] feat(GODT-2373): introducing bridgelib Go dynamic library in bridge-gui. --- .../bridge-gui/bridge-gui/BridgeLib.cpp | 225 +++++ .../bridge-gui/bridge-gui/BridgeLib.h | 36 + .../bridge-gui/bridge-gui/CMakeLists.txt | 47 +- .../bridge-gui/bridge-gui/DeployDarwin.cmake | 3 + .../bridge-gui/bridge-gui/DeployLinux.cmake | 3 + .../bridge-gui/bridge-gui/DeployWindows.cmake | 3 + .../frontend/bridge-gui/bridge-gui/Log.cpp | 66 ++ internal/frontend/bridge-gui/bridge-gui/Log.h | 29 + .../bridge-gui/bridge-gui/QMLBackend.cpp | 26 +- .../bridge-gui/bridge-gui/QMLBackend.h | 5 +- .../bridge-gui/bridge-gui/SentryUtils.cpp | 77 +- .../bridge-gui/bridge-gui/SentryUtils.h | 1 + .../frontend/bridge-gui/bridge-gui/main.cpp | 85 +- .../bridge-gui/bridge-gui/qml/Bridge.qml | 2 +- .../bridge-gui/bridge-gui/qml/SetupGuide.qml | 4 +- .../bridgepp/bridgepp/BridgeUtils.cpp | 125 --- .../bridgepp/bridgepp/BridgeUtils.h | 5 - .../bridgepp/FocusGRPC/FocusGRPCClient.cpp | 9 +- .../bridgepp/FocusGRPC/FocusGRPCClient.h | 11 +- .../bridgepp/bridgepp/GRPC/GRPCClient.cpp | 33 +- .../bridgepp/bridgepp/GRPC/GRPCClient.h | 6 +- .../bridgepp/bridgepp/GRPC/GRPCUtils.cpp | 13 +- .../bridgepp/bridgepp/GRPC/GRPCUtils.h | 6 +- .../bridgepp/bridgepp/GRPC/bridge.grpc.pb.cc | 204 ++-- .../bridgepp/bridgepp/GRPC/bridge.grpc.pb.h | 901 ++++++++---------- .../bridgepp/bridgepp/GRPC/bridge.pb.cc | 148 ++- internal/frontend/grpc/bridge.pb.go | 538 ++++++----- internal/frontend/grpc/bridge.proto | 1 - internal/frontend/grpc/bridge_grpc.pb.go | 36 - internal/frontend/grpc/service_methods.go | 6 - pkg/bridgelib/bridgelib.go | 108 +++ 31 files changed, 1457 insertions(+), 1305 deletions(-) create mode 100644 internal/frontend/bridge-gui/bridge-gui/BridgeLib.cpp create mode 100644 internal/frontend/bridge-gui/bridge-gui/BridgeLib.h create mode 100644 internal/frontend/bridge-gui/bridge-gui/Log.cpp create mode 100644 internal/frontend/bridge-gui/bridge-gui/Log.h create mode 100644 pkg/bridgelib/bridgelib.go diff --git a/internal/frontend/bridge-gui/bridge-gui/BridgeLib.cpp b/internal/frontend/bridge-gui/bridge-gui/BridgeLib.cpp new file mode 100644 index 00000000..f64c7206 --- /dev/null +++ b/internal/frontend/bridge-gui/bridge-gui/BridgeLib.cpp @@ -0,0 +1,225 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + + +#include "BridgeLib.h" +#include +#include + + +using namespace bridgepp; + +#ifdef __cplusplus +extern "C" { +#endif + + +typedef char *(*FuncReturningCString)(); + + +#ifdef __cplusplus +} +#endif + + +namespace { + + +FuncReturningCString goosFunc = nullptr; ///< A pointer to the dynamically loaded GoOS function. +FuncReturningCString userCacheDirFunc = nullptr; ///< A pointer to the dynamically loaded UserCache function. +FuncReturningCString userConfigDirFunc = nullptr; ///< A pointer to the dynamically loaded UserConfig function. +FuncReturningCString userDataDirFunc = nullptr; ///< A pointer to the dynamically loaded UserData function. +void (*deleteCStringFunc)(char *) = nullptr; ///< A pointer to the deleteCString function. + + +#if defined(Q_OS_WINDOWS) +typedef HINSTANCE LibHandle; +#else +typedef void *LibHandle; +#endif + + +LibHandle loadDynamicLibrary(QString const &path); ///< Load a dynamic library. +void *getFuncPointer(LibHandle lib, QString const &funcName); ///< Retrieve a function pointer from a dynamic library. + + +//**************************************************************************************************************************************************** +/// \return The path to the bridgelib library file. +//**************************************************************************************************************************************************** +QString bridgelibPath() { + QString const path = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("bridgelib."); + switch (os()) { + case OS::Windows: + return path + "dll"; + case OS::MacOS: + return path + "dylib"; + case OS::Linux: + default: + return path + "so"; + } +} + + +#if defined(Q_OS_WINDOWS) + + +//**************************************************************************************************************************************************** +/// \param[in] path The path of the library file. +/// \return A pointer to the library object +//**************************************************************************************************************************************************** +LibHandle loadDynamicLibrary(QString const &path) { + if (!QFileInfo::exists(path)) { + throw Exception(QString("The dynamic library file bridgelib.dylib could not be found at '%1'.").arg(path)); + } + + LibHandle handle = LoadLibrary(reinterpret_cast(path.toStdWString().c_str())); + if (!handle) { + throw Exception(QString("The bridgelib dynamic library file '%1' could not be opened.").arg(path)); + } + + return handle; +} + + +//**************************************************************************************************************************************************** +/// \param[in] lib A handle to the library +/// \param[in] funcName The name of the function. +/// \return A pointer to the function +//**************************************************************************************************************************************************** +void *getFuncPointer(LibHandle lib, QString const &funcName) { + void *pointer = reinterpret_cast(GetProcAddress(lib, funcName.toLocal8Bit())); + if (!pointer) + throw Exception(QString("Could not locate function %1 in bridgelib dynamic library").arg(funcName)); + + return pointer; +} + +#else + + +#include + + +//**************************************************************************************************************************************************** +/// \param[in] path The path of the library file. +/// \return A pointer to the library object +//**************************************************************************************************************************************************** +void *loadDynamicLibrary(QString const &path) { + if (!QFileInfo::exists(path)) { + throw Exception(QString("The dynamic library file bridgelib.dylib could not be found at '%1'.").arg(path)); + } + + void *lib = dlopen(path.toLocal8Bit().data(), RTLD_LAZY); + if (!lib) { + throw Exception(QString("The bridgelib dynamic library file '%1' could not be opened.").arg(path)); + } + + return lib; +} + + +//**************************************************************************************************************************************************** +/// \param[in] lib A handle to the library +/// \param[in] funcName The name of the function. +/// \return A pointer to the function +//**************************************************************************************************************************************************** +void *getFuncPointer(LibHandle lib, QString const &funcName) { + void *pointer = dlsym(lib, funcName.toLocal8Bit()); + if (!pointer) { + throw Exception(QString("Could not locate function %1 in bridgelib dynamic library").arg(funcName)); + } + + return pointer; +} + + +#endif // defined(Q_OS_WINDOWS) + + +} + + +namespace bridgelib { + + +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +void loadLibrary() { + try { + LibHandle lib = loadDynamicLibrary(bridgelibPath()); + goosFunc = reinterpret_cast(getFuncPointer(lib, "GoOS")); + userCacheDirFunc = reinterpret_cast(getFuncPointer(lib, "UserCacheDir")); + userConfigDirFunc = reinterpret_cast(getFuncPointer(lib, "UserConfigDir")); + userDataDirFunc = reinterpret_cast(getFuncPointer(lib, "UserDataDir")); + deleteCStringFunc = reinterpret_cast(getFuncPointer(lib, "DeleteCString")); + + } catch (Exception const &e) { + throw Exception("Error loading the bridgelib dynamic library file.", e.qwhat()); + } +} + + +//**************************************************************************************************************************************************** +/// \brief Converts a C-style string returned by a go library function to a QString, and release the memory allocated for the C-style string. +/// \param[in] cString The C-style string, in UTF-8 format. +/// \return A QString. +//**************************************************************************************************************************************************** +QString goToQString(char *const cString) { + if (!cString) { + return QString(); + } + QString const result = QString::fromUtf8(cString); + deleteCStringFunc(cString); + + return result; +} + + +//**************************************************************************************************************************************************** +/// \return The value of the Go runtime.GOOS constant. +//**************************************************************************************************************************************************** +QString goos() { + return goToQString(goosFunc()); +} + + +//**************************************************************************************************************************************************** +/// \return The path to the user cache folder. +//**************************************************************************************************************************************************** +QString userCacheDir() { + return goToQString(userCacheDirFunc()); +} + + +//**************************************************************************************************************************************************** +/// \return The path to the user cache folder. +//**************************************************************************************************************************************************** +QString userConfigDir() { + return goToQString(userConfigDirFunc()); +} + + +//**************************************************************************************************************************************************** +/// \return The path to the user data folder. +//**************************************************************************************************************************************************** +QString userDataDir() { + return goToQString(userDataDirFunc()); +} + + +} \ No newline at end of file diff --git a/internal/frontend/bridge-gui/bridge-gui/BridgeLib.h b/internal/frontend/bridge-gui/bridge-gui/BridgeLib.h new file mode 100644 index 00000000..2c24b39e --- /dev/null +++ b/internal/frontend/bridge-gui/bridge-gui/BridgeLib.h @@ -0,0 +1,36 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + + +#ifndef BRIDGE_GUI_BRIDGELIB_H +#define BRIDGE_GUI_BRIDGELIB_H + + +namespace bridgelib { + + +void loadLibrary(); +QString goos(); +QString userCacheDir(); +QString userConfigDir(); +QString userDataDir(); + + +} // namespace bridgelib + + +#endif //BRIDGE_GUI_BRIDGELIB_H diff --git a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt index cf40a5e8..edff2992 100644 --- a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt @@ -86,6 +86,48 @@ message(STATUS "Using Qt ${Qt6_VERSION}") find_package(sentry CONFIG REQUIRED) +#***************************************************************************************************************************************************** +# bridgelib +#***************************************************************************************************************************************************** +find_program(GO_BIN "go") +if (NOT GO_BIN) + message(FATAL_ERROR "Could not location go compiler") +endif() +message(STATUS "go compiler is ${GO_BIN}") + +if (APPLE) # set some env variable for go compiler on macOS. Note the CGO_ENABLED=1 is required when cross-compiling. + if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64") + set(GO_BIN "MACOSX_DEPLOYMENT_TARGET=11.0" "GOARCH=arm64" "CGO_CFLAGS=\"-mmacosx-version-min=11.0\"" CGO_ENABLED=1 ${GO_BIN}) + else () + set(GO_BIN "MACOSX_DEPLOYMENT_TARGET=10.15" "GOARCH=amd64" "CGO_CFLAGS=\"-mmacosx-version-min=10.15\"" CGO_ENABLED=1 ${GO_BIN}) + endif() +endif() + +file(REAL_PATH "pkg/bridgelib" BRIDGELIB_DIR BASE_DIRECTORY "${BRIDGE_REPO_ROOT}") +message(STATUS "bridgelib folder is ${BRIDGELIB_DIR}") + +set(BRIDGELIB_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set(BRIDGELIB_BASE_NAME "bridgelib") +if (UNIX AND NOT APPLE) + set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.so") +endif() +if (APPLE) + set(BRIDGELIB_OUTPUT_DIR ${BRIDGELIB_OUTPUT_DIR}/${CMAKE_PROJECT_NAME}.app/Contents/MacOS) + set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.dylib") +endif() +if (WIN32) + set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.dll") +endif() + +set(BRIDGELIB_OUTPUT_PATH "${BRIDGELIB_OUTPUT_DIR}/${BRIDGELIB_LIB_FILE}") + +add_custom_target( + bridgelib + COMMAND ${GO_BIN} build -o ${BRIDGELIB_OUTPUT_PATH} --buildmode c-shared + WORKING_DIRECTORY ${BRIDGELIB_DIR} + COMMENT "Compile bridgelib library" +) + #***************************************************************************************************************************************************** # Source files and output #***************************************************************************************************************************************************** @@ -110,22 +152,23 @@ add_executable(bridge-gui Resources.qrc AppController.cpp AppController.h BridgeApp.cpp BridgeApp.h + BridgeLib.cpp BridgeLib.h CommandLine.cpp CommandLine.h EventStreamWorker.cpp EventStreamWorker.h + Log.cpp Log.h main.cpp Pch.h - BuildConfig.h QMLBackend.cpp QMLBackend.h UserList.cpp UserList.h SentryUtils.cpp SentryUtils.h ${DOCK_ICON_SRC_FILE} MacOS/DockIcon.h ) - if (APPLE) target_sources(bridge-gui PRIVATE MacOS/SecondInstance.mm MacOS/SecondInstance.h) endif(APPLE) +add_dependencies(bridge-gui bridgelib) if (WIN32) # on Windows, we add a (non-Qt) resource file that contains the application icon and version information. string(TIMESTAMP BRIDGE_BUILD_YEAR "%Y") diff --git a/internal/frontend/bridge-gui/bridge-gui/DeployDarwin.cmake b/internal/frontend/bridge-gui/bridge-gui/DeployDarwin.cmake index ce32255b..761105cb 100644 --- a/internal/frontend/bridge-gui/bridge-gui/DeployDarwin.cmake +++ b/internal/frontend/bridge-gui/bridge-gui/DeployDarwin.cmake @@ -46,6 +46,9 @@ install(DIRECTORY "${QT_DIR}/lib/QtQuickDialogs2Utils.framework" # PLUGINS install(FILES "${QT_DIR}/plugins/imageformats/libqsvg.dylib" DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/PlugIns/imageformats") +# BRIDGELIB +install(FILES "${BRIDGELIB_OUTPUT_DIR}/${BRIDGELIB_LIB_FILE}" + DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/MacOS") # crash handler utils ## Build diff --git a/internal/frontend/bridge-gui/bridge-gui/DeployLinux.cmake b/internal/frontend/bridge-gui/bridge-gui/DeployLinux.cmake index 10e1ea16..603c9629 100644 --- a/internal/frontend/bridge-gui/bridge-gui/DeployLinux.cmake +++ b/internal/frontend/bridge-gui/bridge-gui/DeployLinux.cmake @@ -43,6 +43,9 @@ macro( AppendQt6Lib LIB_NAME) AppendLib("${LIB_NAME}" "${QT_DIR}/lib/") endmacro() +# bridgelib +install(FILES ${BRIDGELIB_OUTPUT_PATH} DESTINATION ${CMAKE_INSTALL_PREFIX}) + #Qt6 AppendQt6Lib("libQt6QuickControls2.so.6") AppendQt6Lib("libQt6Quick.so.6") diff --git a/internal/frontend/bridge-gui/bridge-gui/DeployWindows.cmake b/internal/frontend/bridge-gui/bridge-gui/DeployWindows.cmake index 85573307..735f9943 100644 --- a/internal/frontend/bridge-gui/bridge-gui/DeployWindows.cmake +++ b/internal/frontend/bridge-gui/bridge-gui/DeployWindows.cmake @@ -47,6 +47,9 @@ endmacro() # Force plugins to be installed near the exe. install(SCRIPT ${deploy_script}) +# bridgelib +install(FILES ${BRIDGELIB_OUTPUT_PATH} DESTINATION ${CMAKE_INSTALL_PREFIX}) + # Vcpkg DLLs AppendVCPKGLib("abseil_dll.dll") AppendVCPKGLib("cares.dll") diff --git a/internal/frontend/bridge-gui/bridge-gui/Log.cpp b/internal/frontend/bridge-gui/bridge-gui/Log.cpp new file mode 100644 index 00000000..75e81d78 --- /dev/null +++ b/internal/frontend/bridge-gui/bridge-gui/Log.cpp @@ -0,0 +1,66 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + + +#include "Log.h" +#include "BridgeLib.h" +#include "BuildConfig.h" + + +using namespace bridgepp; + + +//**************************************************************************************************************************************************** +/// \return user logs directory used by bridge. +//**************************************************************************************************************************************************** +QString userLogsDir() { + QString const path = QDir(bridgelib::userDataDir()).absoluteFilePath("logs"); + QDir().mkpath(path); + return path; +} + +//**************************************************************************************************************************************************** +/// \return A reference to the log. +//**************************************************************************************************************************************************** +Log &initLog() { + Log &log = app().log(); + log.registerAsQtMessageHandler(); + log.setEchoInConsole(true); + + // remove old gui log files + QDir const logsDir(userLogsDir()); + for (QFileInfo const fileInfo: logsDir.entryInfoList({ "gui_v*.log" }, QDir::Filter::Files)) { // entryInfolist apparently only support wildcards, not regex. + QFile(fileInfo.absoluteFilePath()).remove(); + } + + // create new GUI log file + QString error; + if (!log.startWritingToFile(logsDir.absoluteFilePath(QString("gui_v%1_%2.log").arg(PROJECT_VER).arg(QDateTime::currentSecsSinceEpoch())), &error)) { + log.error(error); + } + + log.info("bridge-gui starting"); + QString const qtCompileTimeVersion = QT_VERSION_STR; + QString const qtRuntimeVersion = qVersion(); + QString msg = QString("Using Qt %1").arg(qtRuntimeVersion); + if (qtRuntimeVersion != qtCompileTimeVersion) { + msg += QString(" (compiled against %1)").arg(qtCompileTimeVersion); + } + log.info(msg); + + return log; +} diff --git a/internal/frontend/bridge-gui/bridge-gui/Log.h b/internal/frontend/bridge-gui/bridge-gui/Log.h new file mode 100644 index 00000000..bd20fd08 --- /dev/null +++ b/internal/frontend/bridge-gui/bridge-gui/Log.h @@ -0,0 +1,29 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + + +#ifndef BRIDGE_GUI_LOG_H +#define BRIDGE_GUI_LOG_H + + +#include + + +bridgepp::Log &initLog(); ///< Initialize the application log. + + +#endif //BRIDGE_GUI_LOG_H diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp index c8b00bcf..d50ac0b2 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp @@ -17,8 +17,9 @@ #include "QMLBackend.h" -#include "EventStreamWorker.h" #include "BuildConfig.h" +#include "BridgeLib.h" +#include "EventStreamWorker.h" #include #include #include @@ -56,7 +57,7 @@ void QMLBackend::init(GRPCConfig const &serviceConfig) { app().grpc().setLog(&log); this->connectGrpcEvents(); - app().grpc().connectToServer(serviceConfig, app().bridgeMonitor()); + app().grpc().connectToServer(bridgelib::userConfigDir(), serviceConfig, app().bridgeMonitor()); app().log().info("Connected to backend via gRPC service."); QString bridgeVer; @@ -73,7 +74,6 @@ void QMLBackend::init(GRPCConfig const &serviceConfig) { }); // Grab from bridge the value that will not change during the execution of this app (or that will only change locally). - app().grpc().goos(goos_); app().grpc().logsPath(logsPath_); app().grpc().licensePath(licensePath_); bool sslForIMAP = false, sslForSMTP = false; @@ -151,6 +151,16 @@ bool QMLBackend::areSameFileOrFolder(QUrl const &lhs, QUrl const &rhs) const { } +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +QString QMLBackend::goOS() { + HANDLE_EXCEPTION_RETURN_QSTRING( + return bridgelib::goos(); + ) +} + + //**************************************************************************************************************************************************** /// \return The value for the 'showOnStartup' property. //**************************************************************************************************************************************************** @@ -186,16 +196,6 @@ bool QMLBackend::showSplashScreen() const { } -//**************************************************************************************************************************************************** -/// \return The value for the 'GOOS' property. -//**************************************************************************************************************************************************** -QString QMLBackend::goos() const { - HANDLE_EXCEPTION_RETURN_QSTRING( - return goos_; - ) -} - - //**************************************************************************************************************************************************** /// \return The value for the 'logsPath' property. //**************************************************************************************************************************************************** diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h index d5ff668b..db3c5adb 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h @@ -50,11 +50,11 @@ public: // member functions. Q_INVOKABLE bool isPortFree(int port) const; ///< Check if a given network port is available. Q_INVOKABLE QString nativePath(QUrl const &url) const; ///< Retrieve the native path of a local URL. Q_INVOKABLE bool areSameFileOrFolder(QUrl const &lhs, QUrl const &rhs) const; ///< Check if two local URL point to the same file. + Q_INVOKABLE QString goOS(); ///< Return the OS string from golang's runtime.GOOS. public: // Qt/QML properties. Note that the NOTIFY-er signal is required even for read-only properties (QML warning otherwise) Q_PROPERTY(bool showOnStartup READ showOnStartup NOTIFY showOnStartupChanged) Q_PROPERTY(bool showSplashScreen READ showSplashScreen WRITE setShowSplashScreen NOTIFY showSplashScreenChanged) - Q_PROPERTY(QString goos READ goos NOTIFY goosChanged) Q_PROPERTY(QUrl logsPath READ logsPath NOTIFY logsPathChanged) Q_PROPERTY(QUrl licensePath READ licensePath NOTIFY licensePathChanged) Q_PROPERTY(QUrl releaseNotesLink READ releaseNotesLink NOTIFY releaseNotesLinkChanged) @@ -86,7 +86,6 @@ public: // Qt/QML properties. Note that the NOTIFY-er signal is required even fo bool showOnStartup() const; ///< Getter for the 'showOnStartup' property. void setShowSplashScreen(bool show); ///< Setter for the 'showSplashScreen' property. bool showSplashScreen() const; ///< Getter for the 'showSplashScreen' property. - QString goos() const; ///< Getter for the 'GOOS' property. QUrl logsPath() const; ///< Getter for the 'logsPath' property. QUrl licensePath() const; ///< Getter for the 'licensePath' property. QUrl releaseNotesLink() const;///< Getter for the 'releaseNotesLink' property. @@ -120,7 +119,6 @@ public: // Qt/QML properties. Note that the NOTIFY-er signal is required even fo signals: // Signal used by the Qt property system. Many of them are unused but required to avoid warning from the QML engine. void showSplashScreenChanged(bool value); /// eventStreamOverseer_; ///< The event stream overseer. bool showSplashScreen_ { false }; ///< The cached version of show splash screen. Retrieved on startup from bridge, and potentially modified locally. - QString goos_; ///< The cached version of the GOOS variable. QUrl logsPath_; ///< The logs path. Retrieved from bridge on startup. QUrl licensePath_; ///< The license path. Retrieved from bridge on startup. int imapPort_ { 0 }; ///< The cached value for the IMAP port. diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index 6eabd72a..3e091514 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -17,36 +17,82 @@ #include "SentryUtils.h" #include "BuildConfig.h" +#include "BridgeLib.h" #include - #include #include #include #include + +using namespace bridgepp; + + static constexpr const char *LoggerName = "bridge-gui"; + +//**************************************************************************************************************************************************** +/// \brief Get the path of the sentry cache folder. +/// +/// \return sentry cache directory used by bridge. +//**************************************************************************************************************************************************** +QString sentryCacheDir() { + QString const path = QDir(bridgelib::userDataDir()).absoluteFilePath("sentry_cache"); + QDir().mkpath(path); + return path; +} + + +//**************************************************************************************************************************************************** +/// \brief Get a hash of the computer's host name +//**************************************************************************************************************************************************** QByteArray getProtectedHostname() { QByteArray hostname = QCryptographicHash::hash(QSysInfo::machineHostName().toUtf8(), QCryptographicHash::Sha256); return hostname.toHex(); } +//**************************************************************************************************************************************************** +/// \return The OS String used by sentry +//**************************************************************************************************************************************************** QString getApiOS() { -#if defined(Q_OS_DARWIN) - return "macos"; -#elif defined(Q_OS_WINDOWS) - return "windows"; -#else - return "linux"; -#endif + switch (os()) { + case OS::MacOS: + return "macos"; + case OS::Windows: + return "windows"; + case OS::Linux: + default: + return "linux"; + } } +//**************************************************************************************************************************************************** +/// \return The application version number. +//**************************************************************************************************************************************************** QString appVersion(const QString& version) { - return QString("%1-bridge@%2").arg(getApiOS()).arg(version); + return QString("%1-bridge@%2").arg(getApiOS(), version); } + +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +void initSentry() { + sentry_options_t *sentryOptions = newSentryOptions(PROJECT_DSN_SENTRY, sentryCacheDir().toStdString().c_str()); + if (!QString(PROJECT_CRASHPAD_HANDLER_PATH).isEmpty()) + sentry_options_set_handler_path(sentryOptions, PROJECT_CRASHPAD_HANDLER_PATH); + + if (sentry_init(sentryOptions) != 0) { + QTextStream(stderr) << "Failed to initialize sentry\n"; + } + setSentryReportScope(); +} + +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** void setSentryReportScope() { - sentry_set_tag("OS", bridgepp::goos().toUtf8()); + sentry_set_tag("OS", bridgelib::goos().toUtf8()); sentry_set_tag("Client", PROJECT_FULL_NAME); sentry_set_tag("Version", PROJECT_REVISION); sentry_set_tag("HostArch", QSysInfo::currentCpuArchitecture().toUtf8()); @@ -56,6 +102,10 @@ void setSentryReportScope() { sentry_set_user(user); } + +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** sentry_options_t* newSentryOptions(const char *sentryDNS, const char *cacheDir) { sentry_options_t *sentryOptions = sentry_options_new(); sentry_options_set_dsn(sentryOptions, sentryDNS); @@ -69,12 +119,19 @@ sentry_options_t* newSentryOptions(const char *sentryDNS, const char *cacheDir) return sentryOptions; } + +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** sentry_uuid_t reportSentryEvent(sentry_level_t level, const char *message) { auto event = sentry_value_new_message_event(level, LoggerName, message); return sentry_capture_event(event); } +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** sentry_uuid_t reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception) { auto event = sentry_value_new_message_event(level, LoggerName, message); sentry_event_add_exception(event, sentry_value_new_exception(exceptionType, exception)); diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h index 7b721066..28e6aeb1 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h @@ -21,6 +21,7 @@ #include +void initSentry(); void setSentryReportScope(); sentry_options_t* newSentryOptions(const char * sentryDNS, const char * cacheDir); sentry_uuid_t reportSentryEvent(sentry_level_t level, const char *message); diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index b0354ff7..9aa55d7e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -18,7 +18,9 @@ #include "Pch.h" #include "BridgeApp.h" +#include "BridgeLib.h" #include "CommandLine.h" +#include "Log.h" #include "QMLBackend.h" #include "SentryUtils.h" #include "BuildConfig.h" @@ -27,8 +29,6 @@ #include #include #include -#include -#include #ifdef Q_OS_MACOS @@ -98,38 +98,6 @@ void initQtApplication() { } -//**************************************************************************************************************************************************** -/// \return A reference to the log. -//**************************************************************************************************************************************************** -Log &initLog() { - Log &log = app().log(); - log.registerAsQtMessageHandler(); - log.setEchoInConsole(true); - - // remove old gui log files - QDir const logsDir(userLogsDir()); - for (QFileInfo const fileInfo: logsDir.entryInfoList({ "gui_v*.log" }, QDir::Filter::Files)) { // entryInfolist apparently only support wildcards, not regex. - QFile(fileInfo.absoluteFilePath()).remove(); - } - - // create new GUI log file - QString error; - if (!log.startWritingToFile(logsDir.absoluteFilePath(QString("gui_v%1_%2.log").arg(PROJECT_VER).arg(QDateTime::currentSecsSinceEpoch())), &error)) { - log.error(error); - } - - log.info("bridge-gui starting"); - QString const qtCompileTimeVersion = QT_VERSION_STR; - QString const qtRuntimeVersion = qVersion(); - QString msg = QString("Using Qt %1").arg(qtRuntimeVersion); - if (qtRuntimeVersion != qtCompileTimeVersion) { - msg += QString(" (compiled against %1)").arg(qtCompileTimeVersion); - } - log.info(msg); - - return log; -} - //**************************************************************************************************************************************************** /// \param[in] engine The QML component. @@ -189,7 +157,7 @@ QUrl getApiUrl() { url.setPort(1042); // override with what can be found in the prefs.json file. - QFile prefFile(QString("%1/%2").arg(bridgepp::userConfigDir(), "prefs.json")); + QFile prefFile(QString("%1/%2").arg(bridgelib::userConfigDir(), "prefs.json")); if (prefFile.exists()) { prefFile.open(QIODevice::ReadOnly | QIODevice::Text); QByteArray data = prefFile.readAll(); @@ -217,7 +185,7 @@ QUrl getApiUrl() { /// \return true if an instance of bridge is already running. //**************************************************************************************************************************************************** bool isBridgeRunning() { - QLockFile lockFile(QDir(userCacheDir()).absoluteFilePath(bridgeLock)); + QLockFile lockFile(QDir(bridgelib::userCacheDir()).absoluteFilePath(bridgeLock)); return (!lockFile.tryLock()) && (lockFile.error() == QLockFile::LockFailedError); } @@ -229,7 +197,7 @@ void focusOtherInstance() { try { FocusGRPCClient client; GRPCConfig sc; - QString const path = FocusGRPCClient::grpcFocusServerConfigPath(); + QString const path = FocusGRPCClient::grpcFocusServerConfigPath(bridgelib::userConfigDir()); QFile file(path); if (file.exists()) { if (!sc.load(path)) { @@ -252,7 +220,7 @@ void focusOtherInstance() { catch (Exception const &e) { app().log().error(e.qwhat()); auto uuid = reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during focusOtherInstance()", "Exception", e.what()); - app().log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex()).arg(e.qwhat())); + app().log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex(), e.qwhat())); } } @@ -303,31 +271,29 @@ void closeBridgeApp() { /// \return The exit code for the application. //**************************************************************************************************************************************************** int main(int argc, char *argv[]) { - // Init sentry. - sentry_options_t *sentryOptions = newSentryOptions(PROJECT_DSN_SENTRY, sentryCacheDir().toStdString().c_str()); - if (!QString(PROJECT_CRASHPAD_HANDLER_PATH).isEmpty()) - sentry_options_set_handler_path(sentryOptions, PROJECT_CRASHPAD_HANDLER_PATH); - - if (sentry_init(sentryOptions) != 0) { - std::cerr << "Failed to initialize sentry" << std::endl; - } - setSentryReportScope(); - auto sentryClose = qScopeGuard([] { sentry_close(); }); - // The application instance is needed to display system message boxes. As we may have to do it in the exception handler, // application instance is create outside the try/catch clause. if (QSysInfo::productType() != "windows") { - QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL); + QCoreApplication::setAttribute(Qt::AA_UseSoftwareOpenGL); // must be called before instantiating the BridgeApp } BridgeApp guiApp(argc, argv); try { + bridgelib::loadLibrary(); + QString const& configDir = bridgelib::userConfigDir(); + + // Init sentry. + initSentry(); + + auto sentryClose = qScopeGuard([] { sentry_close(); }); + + initQtApplication(); Log &log = initLog(); - QLockFile lock(bridgepp::userCacheDir() + "/" + bridgeGUILock); + QLockFile lock(bridgelib::userCacheDir() + "/" + bridgeGUILock); if (!checkSingleInstance(lock)) { focusOtherInstance(); return EXIT_FAILURE; @@ -351,15 +317,16 @@ int main(int argc, char *argv[]) { } // before launching bridge, we remove any trailing service config file, because we need to make sure we get a newly generated one. - FocusGRPCClient::removeServiceConfigFile(); - GRPCClient::removeServiceConfigFile(); + FocusGRPCClient::removeServiceConfigFile(configDir); + GRPCClient::removeServiceConfigFile(configDir); launchBridge(cliOptions.bridgeArgs); } - log.info(QString("Retrieving gRPC service configuration from '%1'").arg(QDir::toNativeSeparators(grpcServerConfigPath()))); - app().backend().init(GRPCClient::waitAndRetrieveServiceConfig(cliOptions.attach ? 0 : grpcServiceConfigWaitDelayMs, app().bridgeMonitor())); + log.info(QString("Retrieving gRPC service configuration from '%1'").arg(QDir::toNativeSeparators(grpcServerConfigPath(configDir)))); + app().backend().init(GRPCClient::waitAndRetrieveServiceConfig(configDir, cliOptions.attach ? 0 : grpcServiceConfigWaitDelayMs, + app().bridgeMonitor())); if (!cliOptions.attach) { - GRPCClient::removeServiceConfigFile(); + GRPCClient::removeServiceConfigFile(configDir); } // gRPC communication is established. From now on, log events will be sent to bridge via gRPC. bridge will write these to file, @@ -409,11 +376,11 @@ int main(int argc, char *argv[]) { int result = 0; if (!startError) { // we succeeded in launching bridge, so we can be set as mainExecutable. - QString mainexec = QString::fromLocal8Bit(argv[0]); - app().grpc().setMainExecutable(mainexec); + QString mainExe = QString::fromLocal8Bit(argv[0]); + app().grpc().setMainExecutable(mainExe); QStringList args = cliOptions.bridgeGuiArgs; args.append(waitFlag); - args.append(mainexec); + args.append(mainExe); app().setLauncherArgs(cliOptions.launcher, args); result = QGuiApplication::exec(); } diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/Bridge.qml b/internal/frontend/bridge-gui/bridge-gui/qml/Bridge.qml index 8d116b3a..1c990a00 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/Bridge.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/Bridge.qml @@ -231,7 +231,7 @@ QtObject { } function getTrayIconPath() { - var color = Backend.goos == "darwin" ? "mono" : "color" + var color = Backend.goOS() == "darwin" ? "mono" : "color" var level = "norm" if (_systrayfilter.topmost) { diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/SetupGuide.qml b/internal/frontend/bridge-gui/bridge-gui/qml/SetupGuide.qml index f0d4e6b5..33ade9e6 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/SetupGuide.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/SetupGuide.qml @@ -45,7 +45,7 @@ Item { property string link: "https://proton.me/support/protonmail-bridge-clients-apple-mail" Component.onCompleted : { - if (Backend.goos == "darwin") { + if (Backend.goOS() == "darwin") { append({ "name" : "Apple Mail", "iconSource" : "/qml/icons/ic-apple-mail.svg", @@ -59,7 +59,7 @@ Item { "link" : "https://proton.me/support/protonmail-bridge-clients-macos-outlook-2019" }) } - if (Backend.goos == "windows") { + if (Backend.goOS() == "windows") { append({ "name" : "Microsoft Outlook", "iconSource" : "/qml/icons/ic-microsoft-outlook.svg", diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp index 6f5aae07..a2f323bf 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp @@ -65,131 +65,6 @@ std::mt19937_64 &rng() { } // anonymous namespace -//**************************************************************************************************************************************************** -/// \return user configuration directory used by bridge (based on Golang OS/File's UserConfigDir). -//**************************************************************************************************************************************************** -QString userConfigDir() { - QString dir; -#ifdef Q_OS_WIN - dir = qgetenv ("AppData"); - if (dir.isEmpty()) - throw Exception("%AppData% is not defined."); -#elif defined(Q_OS_IOS) || defined(Q_OS_DARWIN) - dir = qgetenv("HOME"); - if (dir.isEmpty()) { - throw Exception("$HOME is not defined."); - } - dir += "/Library/Application Support"; -#else - dir = qgetenv ("XDG_CONFIG_HOME"); - if (dir.isEmpty()) - { - dir = qgetenv ("HOME"); - if (dir.isEmpty()) - throw Exception("neither $XDG_CONFIG_HOME nor $HOME are defined"); - dir += "/.config"; - } -#endif - QString const folder = QDir(dir).absoluteFilePath(configFolder); - QDir().mkpath(folder); - - return folder; -} - - -//**************************************************************************************************************************************************** -/// \return user cache directory used by bridge (based on Golang OS/File's UserCacheDir). -//**************************************************************************************************************************************************** -QString userCacheDir() { - QString dir; - -#ifdef Q_OS_WIN - dir = qgetenv ("LocalAppData"); - if (dir.isEmpty()) - throw Exception("%LocalAppData% is not defined."); -#elif defined(Q_OS_IOS) || defined(Q_OS_DARWIN) - dir = qgetenv("HOME"); - if (dir.isEmpty()) { - throw Exception("$HOME is not defined."); - } - dir += "/Library/Caches"; -#else - dir = qgetenv ("XDG_CACHE_HOME"); - if (dir.isEmpty()) - { - dir = qgetenv ("HOME"); - if (dir.isEmpty()) - throw Exception("neither $XDG_CACHE_HOME nor $HOME are defined"); - dir += "/.cache"; - } -#endif - - QString const folder = QDir(dir).absoluteFilePath(configFolder); - QDir().mkpath(folder); - - return folder; -} - - -//**************************************************************************************************************************************************** -/// \return user data directory used by bridge (based on Golang OS/File's UserDataDir). -//**************************************************************************************************************************************************** -QString userDataDir() { - QString folder; - -#ifdef Q_OS_LINUX - QString dir = qgetenv ("XDG_DATA_HOME"); - if (dir.isEmpty()) - { - dir = qgetenv ("HOME"); - if (dir.isEmpty()) - throw Exception("neither $XDG_DATA_HOME nor $HOME are defined"); - dir += "/.local/share"; - } - folder = QDir(dir).absoluteFilePath(configFolder); - QDir().mkpath(folder); -#else - folder = userConfigDir(); -#endif - - return folder; -} - - -//**************************************************************************************************************************************************** -/// \return user logs directory used by bridge. -//**************************************************************************************************************************************************** -QString userLogsDir() { - QString const path = QDir(userDataDir()).absoluteFilePath("logs"); - QDir().mkpath(path); - return path; -} - - -//**************************************************************************************************************************************************** -/// \return sentry cache directory used by bridge. -//**************************************************************************************************************************************************** -QString sentryCacheDir() { - QString const path = QDir(userDataDir()).absoluteFilePath("sentry_cache"); - QDir().mkpath(path); - return path; -} - - -//**************************************************************************************************************************************************** -/// \return The value GOOS would return for the current platform. -//**************************************************************************************************************************************************** -QString goos() { -#if defined(Q_OS_DARWIN) - return "darwin"; -#elif defined(Q_OS_WINDOWS) - return "windows"; -#else - return "linux"; -#endif -} - - //**************************************************************************************************************************************************** /// Slow, but not biased. Not for use in crypto functions though, as the RNG use std::random_device as a seed. /// diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h index 47d5e894..ba19fe12 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h @@ -36,11 +36,6 @@ enum class OS { }; -QString userConfigDir(); ///< Get the path of the user configuration folder. -QString userCacheDir(); ///< Get the path of the user cache folder. -QString userLogsDir(); ///< Get the path of the user logs folder. -QString sentryCacheDir(); ///< Get the path of the sentry cache folder. -QString goos(); ///< return the value of Go's GOOS for the current platform ("darwin", "linux" and "windows" are supported). qint64 randN(qint64 n); ///< return a random integer in the half open range [0,n) QString randomFirstName(); ///< Get a random first name from a pre-determined list. QString randomLastName(); ///< Get a random first name from a pre-determined list. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.cpp index 3f9be02f..7c33b801 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.cpp @@ -17,7 +17,6 @@ #include "FocusGRPCClient.h" -#include "../BridgeUtils.h" #include "../Exception/Exception.h" @@ -50,16 +49,16 @@ QString grpcFocusServerConfigFilename() { //**************************************************************************************************************************************************** /// \return The absolute path of the focus service config path. //**************************************************************************************************************************************************** -QString FocusGRPCClient::grpcFocusServerConfigPath() { - return QDir(userConfigDir()).absoluteFilePath(grpcFocusServerConfigFilename()); +QString FocusGRPCClient::grpcFocusServerConfigPath(QString const &configDir) { + return QDir(configDir).absoluteFilePath(grpcFocusServerConfigFilename()); } //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** -void FocusGRPCClient::removeServiceConfigFile() { - QString const path = grpcFocusServerConfigPath(); +void FocusGRPCClient::removeServiceConfigFile(QString const &configDir) { + QString const path = grpcFocusServerConfigPath(configDir); if (!QFile(path).exists()) { return; } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.h index 2c597fac..01c3ed43 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/FocusGRPC/FocusGRPCClient.h @@ -27,13 +27,14 @@ namespace bridgepp { -//********************************************************************************************************************** +//**************************************************************************************************************************************************** /// \brief Focus GRPC client class -//********************************************************************************************************************** +//**************************************************************************************************************************************************** class FocusGRPCClient { public: // static member functions - static void removeServiceConfigFile(); ///< Delete the service config file. - static QString grpcFocusServerConfigPath(); ///< Return the path of the gRPC Focus server config file. + static void removeServiceConfigFile(QString const &configDir); ///< Delete the service config file. + static QString grpcFocusServerConfigPath(QString const &configDir); ///< Return the path of the gRPC Focus server config file. + public: // member functions. FocusGRPCClient() = default; ///< Default constructor. FocusGRPCClient(FocusGRPCClient const &) = delete; ///< Disabled copy-constructor. @@ -41,8 +42,8 @@ public: // member functions. ~FocusGRPCClient() = default; ///< Destructor. FocusGRPCClient &operator=(FocusGRPCClient const &) = delete; ///< Disabled assignment operator. FocusGRPCClient &operator=(FocusGRPCClient &&) = delete; ///< Disabled move assignment operator. - bool connectToServer(qint64 timeoutMs, quint16 port, QString *outError = nullptr); ///< Connect to the focus server + bool connectToServer(qint64 timeoutMs, quint16 port, QString *outError = nullptr); ///< Connect to the focus server grpc::Status raise(); ///< Performs the 'raise' call. grpc::Status version(QString &outVersion); ///< Performs the 'version' call. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp index b27b9857..a3c1b9c9 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp @@ -45,8 +45,8 @@ qint64 const grpcConnectionRetryDelayMs = 10000; ///< Retry delay for the gRPC c //**************************************************************************************************************************************************** // //**************************************************************************************************************************************************** -void GRPCClient::removeServiceConfigFile() { - QString const path = grpcServerConfigPath(); +void GRPCClient::removeServiceConfigFile(QString const &configDir) { + QString const path = grpcServerConfigPath(configDir); if (!QFile(path).exists()) { return; } @@ -61,8 +61,8 @@ void GRPCClient::removeServiceConfigFile() { /// \param[in] serverProcess An optional server process to monitor. If the process it, no need and retry, as connexion cannot be established. Ignored if null. /// \return The service config. //**************************************************************************************************************************************************** -GRPCConfig GRPCClient::waitAndRetrieveServiceConfig(qint64 timeoutMs, ProcessMonitor *serverProcess) { - QString const path = grpcServerConfigPath(); +GRPCConfig GRPCClient::waitAndRetrieveServiceConfig(QString const &configDir, qint64 timeoutMs, ProcessMonitor *serverProcess) { + QString const path = grpcServerConfigPath(configDir); QFile file(path); QElapsedTimer timer; @@ -109,7 +109,7 @@ void GRPCClient::setLog(Log *log) { /// \param[in] serverProcess An optional server process to monitor. If the process it, no need and retry, as connexion cannot be established. Ignored if null. /// \return true iff the connection was successful. //**************************************************************************************************************************************************** -void GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serverProcess) { +void GRPCClient::connectToServer(QString const &configDir, GRPCConfig const &config, ProcessMonitor *serverProcess) { try { serverToken_ = config.token.toStdString(); QString address; @@ -147,8 +147,9 @@ void GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serve break; } // connection established. - if (QDateTime::currentDateTime() > giveUpTime) + if (QDateTime::currentDateTime() > giveUpTime) { throw Exception("Connection to the RPC server failed."); + } } if (channel_->GetState(true) != GRPC_CHANNEL_READY) { @@ -159,7 +160,7 @@ void GRPCClient::connectToServer(GRPCConfig const &config, ProcessMonitor *serve QString const clientToken = QUuid::createUuid().toString(); QString error; - QString clientConfigPath = createClientConfigFile(clientToken, &error); + QString clientConfigPath = createClientConfigFile(configDir, clientToken, &error); if (clientConfigPath.isEmpty()) { throw Exception("gRPC client config could not be saved.", error); } @@ -223,8 +224,9 @@ grpc::Status GRPCClient::addLogEntry(Log::Level level, QString const &package, Q grpc::Status GRPCClient::guiReady(bool &outShowSplashScreen) { GuiReadyResponse response; Status status = this->logGRPCCallStatus(stub_->GuiReady(this->clientContext().get(), empty, &response), __FUNCTION__); - if (status.ok()) + if (status.ok()) { outShowSplashScreen = response.showsplashscreen(); + } return status; } @@ -458,15 +460,6 @@ grpc::Status GRPCClient::showOnStartup(bool &outValue) { } -//**************************************************************************************************************************************************** -/// \param[out] outGoos The value for the property. -/// \return The status for the gRPC call. -//**************************************************************************************************************************************************** -grpc::Status GRPCClient::goos(QString &outGoos) { - return this->logGRPCCallStatus(this->getString(&Bridge::Stub::GoOs, outGoos), __FUNCTION__); -} - - //**************************************************************************************************************************************************** /// \param[out] outPath The value for the property. /// \return The status for the gRPC call. @@ -1365,7 +1358,7 @@ void GRPCClient::processUserEvent(UserEvent const &event) { break; } case UserEvent::kUserBadEvent: { - UserBadEvent const& e = event.userbadevent(); + UserBadEvent const &e = event.userbadevent(); QString const userID = QString::fromStdString(e.userid()); QString const errorMessage = QString::fromStdString(e.errormessage()); this->logTrace(QString("User event received: UserBadEvent (userID = %1, errorMessage = %2).").arg(userID, errorMessage)); @@ -1373,7 +1366,7 @@ void GRPCClient::processUserEvent(UserEvent const &event) { break; } case UserEvent::kUsedBytesChangedEvent: { - UsedBytesChangedEvent const& e = event.usedbyteschangedevent(); + UsedBytesChangedEvent const &e = event.usedbyteschangedevent(); QString const userID = QString::fromStdString(e.userid()); qint64 const usedBytes = e.usedbytes(); this->logTrace(QString("User event received: UsedBytesChangedEvent (userID = %1, usedBytes = %2).").arg(userID).arg(usedBytes)); @@ -1381,7 +1374,7 @@ void GRPCClient::processUserEvent(UserEvent const &event) { break; } case UserEvent::kImapLoginFailedEvent: { - ImapLoginFailedEvent const& e = event.imaploginfailedevent(); + ImapLoginFailedEvent const &e = event.imaploginfailedevent(); QString const username = QString::fromStdString(e.username()); this->logTrace(QString("User event received: IMAPLoginFailed (username = %1).:").arg(username)); emit imapLoginFailed(username); diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h index 0791c4cd..3bc16973 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h @@ -48,8 +48,8 @@ typedef std::unique_ptr UPClientContext; class GRPCClient : public QObject { Q_OBJECT public: // static member functions - static void removeServiceConfigFile(); ///< Delete the service config file. - static GRPCConfig waitAndRetrieveServiceConfig(qint64 timeoutMs, class ProcessMonitor *serverProcess); ///< Wait and retrieve the service configuration. + static void removeServiceConfigFile(QString const &configDir); ///< Delete the service config file. + static GRPCConfig waitAndRetrieveServiceConfig(QString const &configDir, qint64 timeoutMs, class ProcessMonitor *serverProcess); ///< Wait and retrieve the service configuration. public: // member functions. GRPCClient() = default; ///< Default constructor. @@ -59,7 +59,7 @@ public: // member functions. GRPCClient &operator=(GRPCClient const &) = delete; ///< Disabled assignment operator. GRPCClient &operator=(GRPCClient &&) = delete; ///< Disabled move assignment operator. void setLog(Log *log); ///< Set the log for the client. - void connectToServer(GRPCConfig const &config, class ProcessMonitor *serverProcess); ///< Establish connection to the gRPC server. + void connectToServer(QString const &configDir, GRPCConfig const &config, class ProcessMonitor *serverProcess); ///< Establish connection to the gRPC server. grpc::Status checkTokens(QString const &clientConfigPath, QString &outReturnedClientToken); ///< Performs a token check. grpc::Status addLogEntry(Log::Level level, QString const &package, QString const &message); ///< Performs the "AddLogEntry" gRPC call. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.cpp index b651ae54..8552eee4 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.cpp @@ -59,18 +59,19 @@ bool useFileSocketForGRPC() { //**************************************************************************************************************************************************** +/// \param[in] configDir The folder containing the configuration files. /// \return The absolute path of the service config path. //**************************************************************************************************************************************************** -QString grpcServerConfigPath() { - return QDir(userConfigDir()).absoluteFilePath(grpcServerConfigFilename()); +QString grpcServerConfigPath(QString const &configDir) { + return QDir(configDir).absoluteFilePath(grpcServerConfigFilename()); } //**************************************************************************************************************************************************** /// \return The absolute path of the service config path. //**************************************************************************************************************************************************** -QString grpcClientConfigBasePath() { - return QDir(userConfigDir()).absoluteFilePath(grpcClientConfigBaseFilename()); +QString grpcClientConfigBasePath(QString const &configDir) { + return QDir(configDir).absoluteFilePath(grpcClientConfigBaseFilename()); } @@ -81,8 +82,8 @@ QString grpcClientConfigBasePath() { /// \return The path of the created file. /// \return A null string if the file could not be saved. //**************************************************************************************************************************************************** -QString createClientConfigFile(QString const &token, QString *outError) { - QString const basePath = grpcClientConfigBasePath(); +QString createClientConfigFile(QString const &configDir, QString const &token, QString *outError) { + QString const basePath = grpcClientConfigBasePath(configDir); QString path, error; for (qint32 i = 0; i < 1000; ++i) // we try a decent amount of times { diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h index 844ec4c5..e749df3b 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCUtils.h @@ -34,9 +34,9 @@ extern std::string const grpcMetadataServerTokenKey; ///< The key for the server typedef std::shared_ptr SPStreamEvent; ///< Type definition for shared pointer to grpc::StreamEvent. -QString grpcServerConfigPath(); ///< Return the path of the gRPC server config file. -QString grpcClientConfigBasePath(); ///< Return the path of the gRPC client config file. -QString createClientConfigFile(QString const &token, QString *outError); ///< Create the client config file the server will retrieve and return its path. +QString grpcServerConfigPath(QString const &configDir); ///< Return the path of the gRPC server config file. +QString grpcClientConfigBasePath(QString const &configDir); ///< Return the path of the gRPC client config file. +QString createClientConfigFile(QString const &configDir, QString const &token, QString *outError); ///< Create the client config file the server will retrieve and return its path. grpc::LogLevel logLevelToGRPC(Log::Level level); ///< Convert a Log::Level to gRPC enum value. Log::Level logLevelFromGRPC(grpc::LogLevel level); ///< Convert a grpc::LogLevel to a Log::Level. grpc::UserState userStateToGRPC(UserState state); ///< Convert a bridgepp::UserState to a grpc::UserState. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.cc b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.cc index 51b4968b..a6dad038 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.cc +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.cc @@ -34,7 +34,6 @@ static const char* Bridge_method_names[] = { "/grpc.Bridge/IsBetaEnabled", "/grpc.Bridge/SetIsAllMailVisible", "/grpc.Bridge/IsAllMailVisible", - "/grpc.Bridge/GoOs", "/grpc.Bridge/TriggerReset", "/grpc.Bridge/Version", "/grpc.Bridge/LogsPath", @@ -97,48 +96,47 @@ Bridge::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, co , rpcmethod_IsBetaEnabled_(Bridge_method_names[9], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) , rpcmethod_SetIsAllMailVisible_(Bridge_method_names[10], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) , rpcmethod_IsAllMailVisible_(Bridge_method_names[11], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_GoOs_(Bridge_method_names[12], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_TriggerReset_(Bridge_method_names[13], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_Version_(Bridge_method_names[14], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_LogsPath_(Bridge_method_names[15], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_LicensePath_(Bridge_method_names[16], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ReleaseNotesPageLink_(Bridge_method_names[17], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_DependencyLicensesLink_(Bridge_method_names[18], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_LandingPageLink_(Bridge_method_names[19], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetColorSchemeName_(Bridge_method_names[20], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ColorSchemeName_(Bridge_method_names[21], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_CurrentEmailClient_(Bridge_method_names[22], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ReportBug_(Bridge_method_names[23], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ExportTLSCertificates_(Bridge_method_names[24], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ForceLauncher_(Bridge_method_names[25], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetMainExecutable_(Bridge_method_names[26], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_Login_(Bridge_method_names[27], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_Login2FA_(Bridge_method_names[28], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_Login2Passwords_(Bridge_method_names[29], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_LoginAbort_(Bridge_method_names[30], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_CheckUpdate_(Bridge_method_names[31], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_InstallUpdate_(Bridge_method_names[32], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetIsAutomaticUpdateOn_(Bridge_method_names[33], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_IsAutomaticUpdateOn_(Bridge_method_names[34], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_DiskCachePath_(Bridge_method_names[35], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetDiskCachePath_(Bridge_method_names[36], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetIsDoHEnabled_(Bridge_method_names[37], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_IsDoHEnabled_(Bridge_method_names[38], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_MailServerSettings_(Bridge_method_names[39], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetMailServerSettings_(Bridge_method_names[40], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_Hostname_(Bridge_method_names[41], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_IsPortFree_(Bridge_method_names[42], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_AvailableKeychains_(Bridge_method_names[43], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetCurrentKeychain_(Bridge_method_names[44], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_CurrentKeychain_(Bridge_method_names[45], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_GetUserList_(Bridge_method_names[46], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_GetUser_(Bridge_method_names[47], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetUserSplitMode_(Bridge_method_names[48], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_LogoutUser_(Bridge_method_names[49], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_RemoveUser_(Bridge_method_names[50], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ConfigureUserAppleMail_(Bridge_method_names[51], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_RunEventStream_(Bridge_method_names[52], options.suffix_for_stats(),::grpc::internal::RpcMethod::SERVER_STREAMING, channel) - , rpcmethod_StopEventStream_(Bridge_method_names[53], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_TriggerReset_(Bridge_method_names[12], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Version_(Bridge_method_names[13], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_LogsPath_(Bridge_method_names[14], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_LicensePath_(Bridge_method_names[15], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ReleaseNotesPageLink_(Bridge_method_names[16], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_DependencyLicensesLink_(Bridge_method_names[17], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_LandingPageLink_(Bridge_method_names[18], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetColorSchemeName_(Bridge_method_names[19], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ColorSchemeName_(Bridge_method_names[20], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_CurrentEmailClient_(Bridge_method_names[21], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ReportBug_(Bridge_method_names[22], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ExportTLSCertificates_(Bridge_method_names[23], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ForceLauncher_(Bridge_method_names[24], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetMainExecutable_(Bridge_method_names[25], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Login_(Bridge_method_names[26], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Login2FA_(Bridge_method_names[27], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Login2Passwords_(Bridge_method_names[28], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_LoginAbort_(Bridge_method_names[29], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_CheckUpdate_(Bridge_method_names[30], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_InstallUpdate_(Bridge_method_names[31], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetIsAutomaticUpdateOn_(Bridge_method_names[32], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_IsAutomaticUpdateOn_(Bridge_method_names[33], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_DiskCachePath_(Bridge_method_names[34], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetDiskCachePath_(Bridge_method_names[35], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetIsDoHEnabled_(Bridge_method_names[36], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_IsDoHEnabled_(Bridge_method_names[37], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_MailServerSettings_(Bridge_method_names[38], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetMailServerSettings_(Bridge_method_names[39], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Hostname_(Bridge_method_names[40], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_IsPortFree_(Bridge_method_names[41], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_AvailableKeychains_(Bridge_method_names[42], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetCurrentKeychain_(Bridge_method_names[43], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_CurrentKeychain_(Bridge_method_names[44], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_GetUserList_(Bridge_method_names[45], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_GetUser_(Bridge_method_names[46], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetUserSplitMode_(Bridge_method_names[47], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_LogoutUser_(Bridge_method_names[48], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_RemoveUser_(Bridge_method_names[49], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ConfigureUserAppleMail_(Bridge_method_names[50], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_RunEventStream_(Bridge_method_names[51], options.suffix_for_stats(),::grpc::internal::RpcMethod::SERVER_STREAMING, channel) + , rpcmethod_StopEventStream_(Bridge_method_names[52], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) {} ::grpc::Status Bridge::Stub::CheckTokens(::grpc::ClientContext* context, const ::google::protobuf::StringValue& request, ::google::protobuf::StringValue* response) { @@ -417,29 +415,6 @@ void Bridge::Stub::async::IsAllMailVisible(::grpc::ClientContext* context, const return result; } -::grpc::Status Bridge::Stub::GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::StringValue* response) { - return ::grpc::internal::BlockingUnaryCall< ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_GoOs_, context, request, response); -} - -void Bridge::Stub::async::GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, std::function f) { - ::grpc::internal::CallbackUnaryCall< ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GoOs_, context, request, response, std::move(f)); -} - -void Bridge::Stub::async::GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, ::grpc::ClientUnaryReactor* reactor) { - ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GoOs_, context, request, response, reactor); -} - -::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>* Bridge::Stub::PrepareAsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { - return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_GoOs_, context, request); -} - -::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>* Bridge::Stub::AsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { - auto* result = - this->PrepareAsyncGoOsRaw(context, request, cq); - result->StartCall(); - return result; -} - ::grpc::Status Bridge::Stub::TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::Empty* response) { return ::grpc::internal::BlockingUnaryCall< ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_TriggerReset_, context, request, response); } @@ -1500,16 +1475,6 @@ Bridge::Service::Service() { AddMethod(new ::grpc::internal::RpcServiceMethod( Bridge_method_names[12], ::grpc::internal::RpcMethod::NORMAL_RPC, - new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( - [](Bridge::Service* service, - ::grpc::ServerContext* ctx, - const ::google::protobuf::Empty* req, - ::google::protobuf::StringValue* resp) { - return service->GoOs(ctx, req, resp); - }, this))); - AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[13], - ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, ::grpc::ServerContext* ctx, @@ -1518,7 +1483,7 @@ Bridge::Service::Service() { return service->TriggerReset(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[14], + Bridge_method_names[13], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1528,7 +1493,7 @@ Bridge::Service::Service() { return service->Version(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[15], + Bridge_method_names[14], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1538,7 +1503,7 @@ Bridge::Service::Service() { return service->LogsPath(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[16], + Bridge_method_names[15], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1548,7 +1513,7 @@ Bridge::Service::Service() { return service->LicensePath(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[17], + Bridge_method_names[16], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1558,7 +1523,7 @@ Bridge::Service::Service() { return service->ReleaseNotesPageLink(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[18], + Bridge_method_names[17], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1568,7 +1533,7 @@ Bridge::Service::Service() { return service->DependencyLicensesLink(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[19], + Bridge_method_names[18], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1578,7 +1543,7 @@ Bridge::Service::Service() { return service->LandingPageLink(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[20], + Bridge_method_names[19], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1588,7 +1553,7 @@ Bridge::Service::Service() { return service->SetColorSchemeName(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[21], + Bridge_method_names[20], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1598,7 +1563,7 @@ Bridge::Service::Service() { return service->ColorSchemeName(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[22], + Bridge_method_names[21], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1608,7 +1573,7 @@ Bridge::Service::Service() { return service->CurrentEmailClient(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[23], + Bridge_method_names[22], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::ReportBugRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1618,7 +1583,7 @@ Bridge::Service::Service() { return service->ReportBug(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[24], + Bridge_method_names[23], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1628,7 +1593,7 @@ Bridge::Service::Service() { return service->ExportTLSCertificates(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[25], + Bridge_method_names[24], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1638,7 +1603,7 @@ Bridge::Service::Service() { return service->ForceLauncher(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[26], + Bridge_method_names[25], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1648,7 +1613,7 @@ Bridge::Service::Service() { return service->SetMainExecutable(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[27], + Bridge_method_names[26], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::LoginRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1658,7 +1623,7 @@ Bridge::Service::Service() { return service->Login(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[28], + Bridge_method_names[27], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::LoginRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1668,7 +1633,7 @@ Bridge::Service::Service() { return service->Login2FA(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[29], + Bridge_method_names[28], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::LoginRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1678,7 +1643,7 @@ Bridge::Service::Service() { return service->Login2Passwords(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[30], + Bridge_method_names[29], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::LoginAbortRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1688,7 +1653,7 @@ Bridge::Service::Service() { return service->LoginAbort(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[31], + Bridge_method_names[30], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1698,7 +1663,7 @@ Bridge::Service::Service() { return service->CheckUpdate(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[32], + Bridge_method_names[31], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1708,7 +1673,7 @@ Bridge::Service::Service() { return service->InstallUpdate(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[33], + Bridge_method_names[32], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::BoolValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1718,7 +1683,7 @@ Bridge::Service::Service() { return service->SetIsAutomaticUpdateOn(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[34], + Bridge_method_names[33], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::BoolValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1728,7 +1693,7 @@ Bridge::Service::Service() { return service->IsAutomaticUpdateOn(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[35], + Bridge_method_names[34], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1738,7 +1703,7 @@ Bridge::Service::Service() { return service->DiskCachePath(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[36], + Bridge_method_names[35], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1748,7 +1713,7 @@ Bridge::Service::Service() { return service->SetDiskCachePath(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[37], + Bridge_method_names[36], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::BoolValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1758,7 +1723,7 @@ Bridge::Service::Service() { return service->SetIsDoHEnabled(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[38], + Bridge_method_names[37], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::BoolValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1768,7 +1733,7 @@ Bridge::Service::Service() { return service->IsDoHEnabled(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[39], + Bridge_method_names[38], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::grpc::ImapSmtpSettings, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1778,7 +1743,7 @@ Bridge::Service::Service() { return service->MailServerSettings(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[40], + Bridge_method_names[39], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::ImapSmtpSettings, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1788,7 +1753,7 @@ Bridge::Service::Service() { return service->SetMailServerSettings(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[41], + Bridge_method_names[40], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1798,7 +1763,7 @@ Bridge::Service::Service() { return service->Hostname(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[42], + Bridge_method_names[41], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Int32Value, ::google::protobuf::BoolValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1808,7 +1773,7 @@ Bridge::Service::Service() { return service->IsPortFree(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[43], + Bridge_method_names[42], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::grpc::AvailableKeychainsResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1818,7 +1783,7 @@ Bridge::Service::Service() { return service->AvailableKeychains(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[44], + Bridge_method_names[43], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1828,7 +1793,7 @@ Bridge::Service::Service() { return service->SetCurrentKeychain(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[45], + Bridge_method_names[44], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1838,7 +1803,7 @@ Bridge::Service::Service() { return service->CurrentKeychain(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[46], + Bridge_method_names[45], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::grpc::UserListResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1848,7 +1813,7 @@ Bridge::Service::Service() { return service->GetUserList(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[47], + Bridge_method_names[46], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::grpc::User, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1858,7 +1823,7 @@ Bridge::Service::Service() { return service->GetUser(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[48], + Bridge_method_names[47], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::UserSplitModeRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1868,7 +1833,7 @@ Bridge::Service::Service() { return service->SetUserSplitMode(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[49], + Bridge_method_names[48], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1878,7 +1843,7 @@ Bridge::Service::Service() { return service->LogoutUser(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[50], + Bridge_method_names[49], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1888,7 +1853,7 @@ Bridge::Service::Service() { return service->RemoveUser(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[51], + Bridge_method_names[50], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::ConfigureAppleMailRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1898,7 +1863,7 @@ Bridge::Service::Service() { return service->ConfigureUserAppleMail(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[52], + Bridge_method_names[51], ::grpc::internal::RpcMethod::SERVER_STREAMING, new ::grpc::internal::ServerStreamingHandler< Bridge::Service, ::grpc::EventStreamRequest, ::grpc::StreamEvent>( [](Bridge::Service* service, @@ -1908,7 +1873,7 @@ Bridge::Service::Service() { return service->RunEventStream(ctx, req, writer); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[53], + Bridge_method_names[52], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -2006,13 +1971,6 @@ Bridge::Service::~Service() { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } -::grpc::Status Bridge::Service::GoOs(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { - (void) context; - (void) request; - (void) response; - return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); -} - ::grpc::Status Bridge::Service::TriggerReset(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response) { (void) context; (void) request; diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.h index 6bd65044..ce0dce4c 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.h @@ -141,13 +141,6 @@ class Bridge final { std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::BoolValue>> PrepareAsyncIsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::BoolValue>>(PrepareAsyncIsAllMailVisibleRaw(context, request, cq)); } - virtual ::grpc::Status GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::StringValue* response) = 0; - std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>> AsyncGoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { - return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>>(AsyncGoOsRaw(context, request, cq)); - } - std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>> PrepareAsyncGoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { - return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>>(PrepareAsyncGoOsRaw(context, request, cq)); - } virtual ::grpc::Status TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::Empty* response) = 0; std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::Empty>> AsyncTriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::Empty>>(AsyncTriggerResetRaw(context, request, cq)); @@ -474,8 +467,6 @@ class Bridge final { virtual void SetIsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::BoolValue* request, ::google::protobuf::Empty* response, ::grpc::ClientUnaryReactor* reactor) = 0; virtual void IsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response, std::function) = 0; virtual void IsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response, ::grpc::ClientUnaryReactor* reactor) = 0; - virtual void GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, std::function) = 0; - virtual void GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, ::grpc::ClientUnaryReactor* reactor) = 0; virtual void TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, std::function) = 0; virtual void TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, ::grpc::ClientUnaryReactor* reactor) = 0; virtual void Version(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, std::function) = 0; @@ -595,8 +586,6 @@ class Bridge final { virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::Empty>* PrepareAsyncSetIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::BoolValue& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::BoolValue>* AsyncIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::BoolValue>* PrepareAsyncIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; - virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>* AsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; - virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>* PrepareAsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::Empty>* AsyncTriggerResetRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::Empty>* PrepareAsyncTriggerResetRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>* AsyncVersionRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; @@ -768,13 +757,6 @@ class Bridge final { std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::BoolValue>> PrepareAsyncIsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::BoolValue>>(PrepareAsyncIsAllMailVisibleRaw(context, request, cq)); } - ::grpc::Status GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::StringValue* response) override; - std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>> AsyncGoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { - return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>>(AsyncGoOsRaw(context, request, cq)); - } - std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>> PrepareAsyncGoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { - return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>>(PrepareAsyncGoOsRaw(context, request, cq)); - } ::grpc::Status TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::Empty* response) override; std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>> AsyncTriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>>(AsyncTriggerResetRaw(context, request, cq)); @@ -1091,8 +1073,6 @@ class Bridge final { void SetIsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::BoolValue* request, ::google::protobuf::Empty* response, ::grpc::ClientUnaryReactor* reactor) override; void IsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response, std::function) override; void IsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response, ::grpc::ClientUnaryReactor* reactor) override; - void GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, std::function) override; - void GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, ::grpc::ClientUnaryReactor* reactor) override; void TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, std::function) override; void TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, ::grpc::ClientUnaryReactor* reactor) override; void Version(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, std::function) override; @@ -1209,8 +1189,6 @@ class Bridge final { ::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>* PrepareAsyncSetIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::BoolValue& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::google::protobuf::BoolValue>* AsyncIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::google::protobuf::BoolValue>* PrepareAsyncIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; - ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>* AsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; - ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>* PrepareAsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>* AsyncTriggerResetRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>* PrepareAsyncTriggerResetRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>* AsyncVersionRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; @@ -1306,7 +1284,6 @@ class Bridge final { const ::grpc::internal::RpcMethod rpcmethod_IsBetaEnabled_; const ::grpc::internal::RpcMethod rpcmethod_SetIsAllMailVisible_; const ::grpc::internal::RpcMethod rpcmethod_IsAllMailVisible_; - const ::grpc::internal::RpcMethod rpcmethod_GoOs_; const ::grpc::internal::RpcMethod rpcmethod_TriggerReset_; const ::grpc::internal::RpcMethod rpcmethod_Version_; const ::grpc::internal::RpcMethod rpcmethod_LogsPath_; @@ -1368,7 +1345,6 @@ class Bridge final { virtual ::grpc::Status IsBetaEnabled(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response); virtual ::grpc::Status SetIsAllMailVisible(::grpc::ServerContext* context, const ::google::protobuf::BoolValue* request, ::google::protobuf::Empty* response); virtual ::grpc::Status IsAllMailVisible(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response); - virtual ::grpc::Status GoOs(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response); virtual ::grpc::Status TriggerReset(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response); virtual ::grpc::Status Version(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response); virtual ::grpc::Status LogsPath(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response); @@ -1661,32 +1637,12 @@ class Bridge final { } }; template - class WithAsyncMethod_GoOs : public BaseClass { - private: - void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} - public: - WithAsyncMethod_GoOs() { - ::grpc::Service::MarkMethodAsync(12); - } - ~WithAsyncMethod_GoOs() override { - BaseClassMustBeDerivedFromService(this); - } - // disable synchronous version of this method - ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { - abort(); - return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); - } - void RequestGoOs(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(12, context, request, response, new_call_cq, notification_cq, tag); - } - }; - template class WithAsyncMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_TriggerReset() { - ::grpc::Service::MarkMethodAsync(13); + ::grpc::Service::MarkMethodAsync(12); } ~WithAsyncMethod_TriggerReset() override { BaseClassMustBeDerivedFromService(this); @@ -1697,7 +1653,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestTriggerReset(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(13, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(12, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1706,7 +1662,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_Version() { - ::grpc::Service::MarkMethodAsync(14); + ::grpc::Service::MarkMethodAsync(13); } ~WithAsyncMethod_Version() override { BaseClassMustBeDerivedFromService(this); @@ -1717,7 +1673,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestVersion(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(14, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(13, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1726,7 +1682,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_LogsPath() { - ::grpc::Service::MarkMethodAsync(15); + ::grpc::Service::MarkMethodAsync(14); } ~WithAsyncMethod_LogsPath() override { BaseClassMustBeDerivedFromService(this); @@ -1737,7 +1693,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogsPath(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(15, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(14, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1746,7 +1702,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_LicensePath() { - ::grpc::Service::MarkMethodAsync(16); + ::grpc::Service::MarkMethodAsync(15); } ~WithAsyncMethod_LicensePath() override { BaseClassMustBeDerivedFromService(this); @@ -1757,7 +1713,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLicensePath(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(16, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(15, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1766,7 +1722,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodAsync(17); + ::grpc::Service::MarkMethodAsync(16); } ~WithAsyncMethod_ReleaseNotesPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -1777,7 +1733,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestReleaseNotesPageLink(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(17, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(16, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1786,7 +1742,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodAsync(18); + ::grpc::Service::MarkMethodAsync(17); } ~WithAsyncMethod_DependencyLicensesLink() override { BaseClassMustBeDerivedFromService(this); @@ -1797,7 +1753,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestDependencyLicensesLink(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(18, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(17, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1806,7 +1762,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_LandingPageLink() { - ::grpc::Service::MarkMethodAsync(19); + ::grpc::Service::MarkMethodAsync(18); } ~WithAsyncMethod_LandingPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -1817,7 +1773,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLandingPageLink(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(19, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(18, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1826,7 +1782,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodAsync(20); + ::grpc::Service::MarkMethodAsync(19); } ~WithAsyncMethod_SetColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -1837,7 +1793,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetColorSchemeName(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(20, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(19, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1846,7 +1802,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodAsync(21); + ::grpc::Service::MarkMethodAsync(20); } ~WithAsyncMethod_ColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -1857,7 +1813,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestColorSchemeName(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(21, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(20, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1866,7 +1822,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodAsync(22); + ::grpc::Service::MarkMethodAsync(21); } ~WithAsyncMethod_CurrentEmailClient() override { BaseClassMustBeDerivedFromService(this); @@ -1877,7 +1833,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCurrentEmailClient(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(22, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(21, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1886,7 +1842,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ReportBug() { - ::grpc::Service::MarkMethodAsync(23); + ::grpc::Service::MarkMethodAsync(22); } ~WithAsyncMethod_ReportBug() override { BaseClassMustBeDerivedFromService(this); @@ -1897,7 +1853,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestReportBug(::grpc::ServerContext* context, ::grpc::ReportBugRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(23, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(22, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1906,7 +1862,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodAsync(24); + ::grpc::Service::MarkMethodAsync(23); } ~WithAsyncMethod_ExportTLSCertificates() override { BaseClassMustBeDerivedFromService(this); @@ -1917,7 +1873,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestExportTLSCertificates(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(24, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(23, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1926,7 +1882,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ForceLauncher() { - ::grpc::Service::MarkMethodAsync(25); + ::grpc::Service::MarkMethodAsync(24); } ~WithAsyncMethod_ForceLauncher() override { BaseClassMustBeDerivedFromService(this); @@ -1937,7 +1893,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestForceLauncher(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(25, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(24, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1946,7 +1902,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodAsync(26); + ::grpc::Service::MarkMethodAsync(25); } ~WithAsyncMethod_SetMainExecutable() override { BaseClassMustBeDerivedFromService(this); @@ -1957,7 +1913,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetMainExecutable(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(26, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(25, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1966,7 +1922,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_Login() { - ::grpc::Service::MarkMethodAsync(27); + ::grpc::Service::MarkMethodAsync(26); } ~WithAsyncMethod_Login() override { BaseClassMustBeDerivedFromService(this); @@ -1977,7 +1933,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin(::grpc::ServerContext* context, ::grpc::LoginRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(27, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(26, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1986,7 +1942,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_Login2FA() { - ::grpc::Service::MarkMethodAsync(28); + ::grpc::Service::MarkMethodAsync(27); } ~WithAsyncMethod_Login2FA() override { BaseClassMustBeDerivedFromService(this); @@ -1997,7 +1953,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin2FA(::grpc::ServerContext* context, ::grpc::LoginRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(28, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(27, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2006,7 +1962,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_Login2Passwords() { - ::grpc::Service::MarkMethodAsync(29); + ::grpc::Service::MarkMethodAsync(28); } ~WithAsyncMethod_Login2Passwords() override { BaseClassMustBeDerivedFromService(this); @@ -2017,7 +1973,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin2Passwords(::grpc::ServerContext* context, ::grpc::LoginRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(29, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(28, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2026,7 +1982,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_LoginAbort() { - ::grpc::Service::MarkMethodAsync(30); + ::grpc::Service::MarkMethodAsync(29); } ~WithAsyncMethod_LoginAbort() override { BaseClassMustBeDerivedFromService(this); @@ -2037,7 +1993,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLoginAbort(::grpc::ServerContext* context, ::grpc::LoginAbortRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(30, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(29, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2046,7 +2002,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_CheckUpdate() { - ::grpc::Service::MarkMethodAsync(31); + ::grpc::Service::MarkMethodAsync(30); } ~WithAsyncMethod_CheckUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -2057,7 +2013,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCheckUpdate(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(31, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(30, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2066,7 +2022,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_InstallUpdate() { - ::grpc::Service::MarkMethodAsync(32); + ::grpc::Service::MarkMethodAsync(31); } ~WithAsyncMethod_InstallUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -2077,7 +2033,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestInstallUpdate(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(32, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(31, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2086,7 +2042,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodAsync(33); + ::grpc::Service::MarkMethodAsync(32); } ~WithAsyncMethod_SetIsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -2097,7 +2053,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetIsAutomaticUpdateOn(::grpc::ServerContext* context, ::google::protobuf::BoolValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(33, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(32, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2106,7 +2062,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodAsync(34); + ::grpc::Service::MarkMethodAsync(33); } ~WithAsyncMethod_IsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -2117,7 +2073,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsAutomaticUpdateOn(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::BoolValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(34, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(33, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2126,7 +2082,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_DiskCachePath() { - ::grpc::Service::MarkMethodAsync(35); + ::grpc::Service::MarkMethodAsync(34); } ~WithAsyncMethod_DiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -2137,7 +2093,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestDiskCachePath(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(35, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(34, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2146,7 +2102,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodAsync(36); + ::grpc::Service::MarkMethodAsync(35); } ~WithAsyncMethod_SetDiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -2157,7 +2113,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetDiskCachePath(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(36, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(35, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2166,7 +2122,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodAsync(37); + ::grpc::Service::MarkMethodAsync(36); } ~WithAsyncMethod_SetIsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -2177,7 +2133,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetIsDoHEnabled(::grpc::ServerContext* context, ::google::protobuf::BoolValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(37, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(36, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2186,7 +2142,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodAsync(38); + ::grpc::Service::MarkMethodAsync(37); } ~WithAsyncMethod_IsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -2197,7 +2153,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsDoHEnabled(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::BoolValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(38, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(37, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2206,7 +2162,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_MailServerSettings() { - ::grpc::Service::MarkMethodAsync(39); + ::grpc::Service::MarkMethodAsync(38); } ~WithAsyncMethod_MailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -2217,7 +2173,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestMailServerSettings(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ImapSmtpSettings>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(39, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(38, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2226,7 +2182,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodAsync(40); + ::grpc::Service::MarkMethodAsync(39); } ~WithAsyncMethod_SetMailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -2237,7 +2193,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetMailServerSettings(::grpc::ServerContext* context, ::grpc::ImapSmtpSettings* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(40, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(39, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2246,7 +2202,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_Hostname() { - ::grpc::Service::MarkMethodAsync(41); + ::grpc::Service::MarkMethodAsync(40); } ~WithAsyncMethod_Hostname() override { BaseClassMustBeDerivedFromService(this); @@ -2257,7 +2213,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestHostname(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(41, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(40, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2266,7 +2222,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_IsPortFree() { - ::grpc::Service::MarkMethodAsync(42); + ::grpc::Service::MarkMethodAsync(41); } ~WithAsyncMethod_IsPortFree() override { BaseClassMustBeDerivedFromService(this); @@ -2277,7 +2233,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsPortFree(::grpc::ServerContext* context, ::google::protobuf::Int32Value* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::BoolValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(42, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(41, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2286,7 +2242,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodAsync(43); + ::grpc::Service::MarkMethodAsync(42); } ~WithAsyncMethod_AvailableKeychains() override { BaseClassMustBeDerivedFromService(this); @@ -2297,7 +2253,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestAvailableKeychains(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::grpc::AvailableKeychainsResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(43, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(42, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2306,7 +2262,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodAsync(44); + ::grpc::Service::MarkMethodAsync(43); } ~WithAsyncMethod_SetCurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -2317,7 +2273,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetCurrentKeychain(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(44, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(43, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2326,7 +2282,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodAsync(45); + ::grpc::Service::MarkMethodAsync(44); } ~WithAsyncMethod_CurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -2337,7 +2293,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCurrentKeychain(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(45, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(44, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2346,7 +2302,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_GetUserList() { - ::grpc::Service::MarkMethodAsync(46); + ::grpc::Service::MarkMethodAsync(45); } ~WithAsyncMethod_GetUserList() override { BaseClassMustBeDerivedFromService(this); @@ -2357,7 +2313,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestGetUserList(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::grpc::UserListResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(46, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(45, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2366,7 +2322,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_GetUser() { - ::grpc::Service::MarkMethodAsync(47); + ::grpc::Service::MarkMethodAsync(46); } ~WithAsyncMethod_GetUser() override { BaseClassMustBeDerivedFromService(this); @@ -2377,7 +2333,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestGetUser(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::grpc::User>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(47, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(46, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2386,7 +2342,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodAsync(48); + ::grpc::Service::MarkMethodAsync(47); } ~WithAsyncMethod_SetUserSplitMode() override { BaseClassMustBeDerivedFromService(this); @@ -2397,7 +2353,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetUserSplitMode(::grpc::ServerContext* context, ::grpc::UserSplitModeRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(48, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(47, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2406,7 +2362,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_LogoutUser() { - ::grpc::Service::MarkMethodAsync(49); + ::grpc::Service::MarkMethodAsync(48); } ~WithAsyncMethod_LogoutUser() override { BaseClassMustBeDerivedFromService(this); @@ -2417,7 +2373,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogoutUser(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(49, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(48, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2426,7 +2382,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_RemoveUser() { - ::grpc::Service::MarkMethodAsync(50); + ::grpc::Service::MarkMethodAsync(49); } ~WithAsyncMethod_RemoveUser() override { BaseClassMustBeDerivedFromService(this); @@ -2437,7 +2393,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestRemoveUser(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(50, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(49, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2446,7 +2402,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodAsync(51); + ::grpc::Service::MarkMethodAsync(50); } ~WithAsyncMethod_ConfigureUserAppleMail() override { BaseClassMustBeDerivedFromService(this); @@ -2457,7 +2413,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestConfigureUserAppleMail(::grpc::ServerContext* context, ::grpc::ConfigureAppleMailRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(51, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(50, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2466,7 +2422,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_RunEventStream() { - ::grpc::Service::MarkMethodAsync(52); + ::grpc::Service::MarkMethodAsync(51); } ~WithAsyncMethod_RunEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -2477,7 +2433,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestRunEventStream(::grpc::ServerContext* context, ::grpc::EventStreamRequest* request, ::grpc::ServerAsyncWriter< ::grpc::StreamEvent>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncServerStreaming(52, context, request, writer, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncServerStreaming(51, context, request, writer, new_call_cq, notification_cq, tag); } }; template @@ -2486,7 +2442,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_StopEventStream() { - ::grpc::Service::MarkMethodAsync(53); + ::grpc::Service::MarkMethodAsync(52); } ~WithAsyncMethod_StopEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -2497,10 +2453,10 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestStopEventStream(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(53, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(52, context, request, response, new_call_cq, notification_cq, tag); } }; - typedef WithAsyncMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > AsyncService; + typedef WithAsyncMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > AsyncService; template class WithCallbackMethod_CheckTokens : public BaseClass { private: @@ -2826,45 +2782,18 @@ class Bridge final { ::grpc::CallbackServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::BoolValue* /*response*/) { return nullptr; } }; template - class WithCallbackMethod_GoOs : public BaseClass { - private: - void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} - public: - WithCallbackMethod_GoOs() { - ::grpc::Service::MarkMethodCallback(12, - new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( - [this]( - ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->GoOs(context, request, response); }));} - void SetMessageAllocatorFor_GoOs( - ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(12); - static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) - ->SetMessageAllocator(allocator); - } - ~WithCallbackMethod_GoOs() override { - BaseClassMustBeDerivedFromService(this); - } - // disable synchronous version of this method - ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { - abort(); - return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); - } - virtual ::grpc::ServerUnaryReactor* GoOs( - ::grpc::CallbackServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) { return nullptr; } - }; - template class WithCallbackMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_TriggerReset() { - ::grpc::Service::MarkMethodCallback(13, + ::grpc::Service::MarkMethodCallback(12, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response) { return this->TriggerReset(context, request, response); }));} void SetMessageAllocatorFor_TriggerReset( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(13); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(12); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -2885,13 +2814,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_Version() { - ::grpc::Service::MarkMethodCallback(14, + ::grpc::Service::MarkMethodCallback(13, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->Version(context, request, response); }));} void SetMessageAllocatorFor_Version( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(14); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(13); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -2912,13 +2841,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_LogsPath() { - ::grpc::Service::MarkMethodCallback(15, + ::grpc::Service::MarkMethodCallback(14, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->LogsPath(context, request, response); }));} void SetMessageAllocatorFor_LogsPath( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(15); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(14); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -2939,13 +2868,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_LicensePath() { - ::grpc::Service::MarkMethodCallback(16, + ::grpc::Service::MarkMethodCallback(15, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->LicensePath(context, request, response); }));} void SetMessageAllocatorFor_LicensePath( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(16); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(15); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -2966,13 +2895,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodCallback(17, + ::grpc::Service::MarkMethodCallback(16, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->ReleaseNotesPageLink(context, request, response); }));} void SetMessageAllocatorFor_ReleaseNotesPageLink( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(17); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(16); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -2993,13 +2922,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodCallback(18, + ::grpc::Service::MarkMethodCallback(17, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->DependencyLicensesLink(context, request, response); }));} void SetMessageAllocatorFor_DependencyLicensesLink( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(18); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(17); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3020,13 +2949,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_LandingPageLink() { - ::grpc::Service::MarkMethodCallback(19, + ::grpc::Service::MarkMethodCallback(18, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->LandingPageLink(context, request, response); }));} void SetMessageAllocatorFor_LandingPageLink( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(19); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(18); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3047,13 +2976,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodCallback(20, + ::grpc::Service::MarkMethodCallback(19, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->SetColorSchemeName(context, request, response); }));} void SetMessageAllocatorFor_SetColorSchemeName( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(20); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(19); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3074,13 +3003,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodCallback(21, + ::grpc::Service::MarkMethodCallback(20, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->ColorSchemeName(context, request, response); }));} void SetMessageAllocatorFor_ColorSchemeName( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(21); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(20); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3101,13 +3030,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodCallback(22, + ::grpc::Service::MarkMethodCallback(21, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->CurrentEmailClient(context, request, response); }));} void SetMessageAllocatorFor_CurrentEmailClient( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(22); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(21); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3128,13 +3057,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ReportBug() { - ::grpc::Service::MarkMethodCallback(23, + ::grpc::Service::MarkMethodCallback(22, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ReportBugRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ReportBugRequest* request, ::google::protobuf::Empty* response) { return this->ReportBug(context, request, response); }));} void SetMessageAllocatorFor_ReportBug( ::grpc::MessageAllocator< ::grpc::ReportBugRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(23); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(22); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::ReportBugRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3155,13 +3084,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodCallback(24, + ::grpc::Service::MarkMethodCallback(23, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->ExportTLSCertificates(context, request, response); }));} void SetMessageAllocatorFor_ExportTLSCertificates( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(24); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(23); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3182,13 +3111,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ForceLauncher() { - ::grpc::Service::MarkMethodCallback(25, + ::grpc::Service::MarkMethodCallback(24, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->ForceLauncher(context, request, response); }));} void SetMessageAllocatorFor_ForceLauncher( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(25); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(24); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3209,13 +3138,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodCallback(26, + ::grpc::Service::MarkMethodCallback(25, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->SetMainExecutable(context, request, response); }));} void SetMessageAllocatorFor_SetMainExecutable( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(26); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(25); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3236,13 +3165,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_Login() { - ::grpc::Service::MarkMethodCallback(27, + ::grpc::Service::MarkMethodCallback(26, new ::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::LoginRequest* request, ::google::protobuf::Empty* response) { return this->Login(context, request, response); }));} void SetMessageAllocatorFor_Login( ::grpc::MessageAllocator< ::grpc::LoginRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(27); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(26); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3263,13 +3192,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_Login2FA() { - ::grpc::Service::MarkMethodCallback(28, + ::grpc::Service::MarkMethodCallback(27, new ::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::LoginRequest* request, ::google::protobuf::Empty* response) { return this->Login2FA(context, request, response); }));} void SetMessageAllocatorFor_Login2FA( ::grpc::MessageAllocator< ::grpc::LoginRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(28); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(27); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3290,13 +3219,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_Login2Passwords() { - ::grpc::Service::MarkMethodCallback(29, + ::grpc::Service::MarkMethodCallback(28, new ::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::LoginRequest* request, ::google::protobuf::Empty* response) { return this->Login2Passwords(context, request, response); }));} void SetMessageAllocatorFor_Login2Passwords( ::grpc::MessageAllocator< ::grpc::LoginRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(29); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(28); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3317,13 +3246,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_LoginAbort() { - ::grpc::Service::MarkMethodCallback(30, + ::grpc::Service::MarkMethodCallback(29, new ::grpc::internal::CallbackUnaryHandler< ::grpc::LoginAbortRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::LoginAbortRequest* request, ::google::protobuf::Empty* response) { return this->LoginAbort(context, request, response); }));} void SetMessageAllocatorFor_LoginAbort( ::grpc::MessageAllocator< ::grpc::LoginAbortRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(30); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(29); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::LoginAbortRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3344,13 +3273,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_CheckUpdate() { - ::grpc::Service::MarkMethodCallback(31, + ::grpc::Service::MarkMethodCallback(30, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response) { return this->CheckUpdate(context, request, response); }));} void SetMessageAllocatorFor_CheckUpdate( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(31); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(30); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3371,13 +3300,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_InstallUpdate() { - ::grpc::Service::MarkMethodCallback(32, + ::grpc::Service::MarkMethodCallback(31, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response) { return this->InstallUpdate(context, request, response); }));} void SetMessageAllocatorFor_InstallUpdate( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(32); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(31); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3398,13 +3327,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodCallback(33, + ::grpc::Service::MarkMethodCallback(32, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::BoolValue* request, ::google::protobuf::Empty* response) { return this->SetIsAutomaticUpdateOn(context, request, response); }));} void SetMessageAllocatorFor_SetIsAutomaticUpdateOn( ::grpc::MessageAllocator< ::google::protobuf::BoolValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(33); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(32); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3425,13 +3354,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodCallback(34, + ::grpc::Service::MarkMethodCallback(33, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response) { return this->IsAutomaticUpdateOn(context, request, response); }));} void SetMessageAllocatorFor_IsAutomaticUpdateOn( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::BoolValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(34); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(33); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3452,13 +3381,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_DiskCachePath() { - ::grpc::Service::MarkMethodCallback(35, + ::grpc::Service::MarkMethodCallback(34, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->DiskCachePath(context, request, response); }));} void SetMessageAllocatorFor_DiskCachePath( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(35); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(34); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3479,13 +3408,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodCallback(36, + ::grpc::Service::MarkMethodCallback(35, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->SetDiskCachePath(context, request, response); }));} void SetMessageAllocatorFor_SetDiskCachePath( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(36); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(35); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3506,13 +3435,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodCallback(37, + ::grpc::Service::MarkMethodCallback(36, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::BoolValue* request, ::google::protobuf::Empty* response) { return this->SetIsDoHEnabled(context, request, response); }));} void SetMessageAllocatorFor_SetIsDoHEnabled( ::grpc::MessageAllocator< ::google::protobuf::BoolValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(37); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(36); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3533,13 +3462,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodCallback(38, + ::grpc::Service::MarkMethodCallback(37, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response) { return this->IsDoHEnabled(context, request, response); }));} void SetMessageAllocatorFor_IsDoHEnabled( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::BoolValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(38); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(37); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3560,13 +3489,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_MailServerSettings() { - ::grpc::Service::MarkMethodCallback(39, + ::grpc::Service::MarkMethodCallback(38, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::ImapSmtpSettings>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::grpc::ImapSmtpSettings* response) { return this->MailServerSettings(context, request, response); }));} void SetMessageAllocatorFor_MailServerSettings( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::grpc::ImapSmtpSettings>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(39); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(38); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::ImapSmtpSettings>*>(handler) ->SetMessageAllocator(allocator); } @@ -3587,13 +3516,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodCallback(40, + ::grpc::Service::MarkMethodCallback(39, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ImapSmtpSettings, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ImapSmtpSettings* request, ::google::protobuf::Empty* response) { return this->SetMailServerSettings(context, request, response); }));} void SetMessageAllocatorFor_SetMailServerSettings( ::grpc::MessageAllocator< ::grpc::ImapSmtpSettings, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(40); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(39); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::ImapSmtpSettings, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3614,13 +3543,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_Hostname() { - ::grpc::Service::MarkMethodCallback(41, + ::grpc::Service::MarkMethodCallback(40, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->Hostname(context, request, response); }));} void SetMessageAllocatorFor_Hostname( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(41); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(40); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3641,13 +3570,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_IsPortFree() { - ::grpc::Service::MarkMethodCallback(42, + ::grpc::Service::MarkMethodCallback(41, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Int32Value, ::google::protobuf::BoolValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Int32Value* request, ::google::protobuf::BoolValue* response) { return this->IsPortFree(context, request, response); }));} void SetMessageAllocatorFor_IsPortFree( ::grpc::MessageAllocator< ::google::protobuf::Int32Value, ::google::protobuf::BoolValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(42); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(41); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Int32Value, ::google::protobuf::BoolValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3668,13 +3597,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodCallback(43, + ::grpc::Service::MarkMethodCallback(42, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::AvailableKeychainsResponse>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::grpc::AvailableKeychainsResponse* response) { return this->AvailableKeychains(context, request, response); }));} void SetMessageAllocatorFor_AvailableKeychains( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::grpc::AvailableKeychainsResponse>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(43); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(42); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::AvailableKeychainsResponse>*>(handler) ->SetMessageAllocator(allocator); } @@ -3695,13 +3624,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodCallback(44, + ::grpc::Service::MarkMethodCallback(43, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->SetCurrentKeychain(context, request, response); }));} void SetMessageAllocatorFor_SetCurrentKeychain( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(44); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(43); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3722,13 +3651,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodCallback(45, + ::grpc::Service::MarkMethodCallback(44, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->CurrentKeychain(context, request, response); }));} void SetMessageAllocatorFor_CurrentKeychain( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(45); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(44); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3749,13 +3678,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_GetUserList() { - ::grpc::Service::MarkMethodCallback(46, + ::grpc::Service::MarkMethodCallback(45, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::UserListResponse>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::grpc::UserListResponse* response) { return this->GetUserList(context, request, response); }));} void SetMessageAllocatorFor_GetUserList( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::grpc::UserListResponse>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(46); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(45); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::UserListResponse>*>(handler) ->SetMessageAllocator(allocator); } @@ -3776,13 +3705,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_GetUser() { - ::grpc::Service::MarkMethodCallback(47, + ::grpc::Service::MarkMethodCallback(46, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::grpc::User>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::grpc::User* response) { return this->GetUser(context, request, response); }));} void SetMessageAllocatorFor_GetUser( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::grpc::User>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(47); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(46); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::grpc::User>*>(handler) ->SetMessageAllocator(allocator); } @@ -3803,13 +3732,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodCallback(48, + ::grpc::Service::MarkMethodCallback(47, new ::grpc::internal::CallbackUnaryHandler< ::grpc::UserSplitModeRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::UserSplitModeRequest* request, ::google::protobuf::Empty* response) { return this->SetUserSplitMode(context, request, response); }));} void SetMessageAllocatorFor_SetUserSplitMode( ::grpc::MessageAllocator< ::grpc::UserSplitModeRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(48); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(47); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::UserSplitModeRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3830,13 +3759,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_LogoutUser() { - ::grpc::Service::MarkMethodCallback(49, + ::grpc::Service::MarkMethodCallback(48, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->LogoutUser(context, request, response); }));} void SetMessageAllocatorFor_LogoutUser( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(49); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(48); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3857,13 +3786,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_RemoveUser() { - ::grpc::Service::MarkMethodCallback(50, + ::grpc::Service::MarkMethodCallback(49, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->RemoveUser(context, request, response); }));} void SetMessageAllocatorFor_RemoveUser( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(50); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(49); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3884,13 +3813,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodCallback(51, + ::grpc::Service::MarkMethodCallback(50, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ConfigureAppleMailRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ConfigureAppleMailRequest* request, ::google::protobuf::Empty* response) { return this->ConfigureUserAppleMail(context, request, response); }));} void SetMessageAllocatorFor_ConfigureUserAppleMail( ::grpc::MessageAllocator< ::grpc::ConfigureAppleMailRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(51); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(50); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::ConfigureAppleMailRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3911,7 +3840,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_RunEventStream() { - ::grpc::Service::MarkMethodCallback(52, + ::grpc::Service::MarkMethodCallback(51, new ::grpc::internal::CallbackServerStreamingHandler< ::grpc::EventStreamRequest, ::grpc::StreamEvent>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::EventStreamRequest* request) { return this->RunEventStream(context, request); })); @@ -3933,13 +3862,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_StopEventStream() { - ::grpc::Service::MarkMethodCallback(53, + ::grpc::Service::MarkMethodCallback(52, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response) { return this->StopEventStream(context, request, response); }));} void SetMessageAllocatorFor_StopEventStream( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(53); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(52); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3954,7 +3883,7 @@ class Bridge final { virtual ::grpc::ServerUnaryReactor* StopEventStream( ::grpc::CallbackServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::Empty* /*response*/) { return nullptr; } }; - typedef WithCallbackMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > CallbackService; + typedef WithCallbackMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > CallbackService; typedef CallbackService ExperimentalCallbackService; template class WithGenericMethod_CheckTokens : public BaseClass { @@ -4161,29 +4090,12 @@ class Bridge final { } }; template - class WithGenericMethod_GoOs : public BaseClass { - private: - void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} - public: - WithGenericMethod_GoOs() { - ::grpc::Service::MarkMethodGeneric(12); - } - ~WithGenericMethod_GoOs() override { - BaseClassMustBeDerivedFromService(this); - } - // disable synchronous version of this method - ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { - abort(); - return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); - } - }; - template class WithGenericMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_TriggerReset() { - ::grpc::Service::MarkMethodGeneric(13); + ::grpc::Service::MarkMethodGeneric(12); } ~WithGenericMethod_TriggerReset() override { BaseClassMustBeDerivedFromService(this); @@ -4200,7 +4112,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_Version() { - ::grpc::Service::MarkMethodGeneric(14); + ::grpc::Service::MarkMethodGeneric(13); } ~WithGenericMethod_Version() override { BaseClassMustBeDerivedFromService(this); @@ -4217,7 +4129,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_LogsPath() { - ::grpc::Service::MarkMethodGeneric(15); + ::grpc::Service::MarkMethodGeneric(14); } ~WithGenericMethod_LogsPath() override { BaseClassMustBeDerivedFromService(this); @@ -4234,7 +4146,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_LicensePath() { - ::grpc::Service::MarkMethodGeneric(16); + ::grpc::Service::MarkMethodGeneric(15); } ~WithGenericMethod_LicensePath() override { BaseClassMustBeDerivedFromService(this); @@ -4251,7 +4163,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodGeneric(17); + ::grpc::Service::MarkMethodGeneric(16); } ~WithGenericMethod_ReleaseNotesPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -4268,7 +4180,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodGeneric(18); + ::grpc::Service::MarkMethodGeneric(17); } ~WithGenericMethod_DependencyLicensesLink() override { BaseClassMustBeDerivedFromService(this); @@ -4285,7 +4197,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_LandingPageLink() { - ::grpc::Service::MarkMethodGeneric(19); + ::grpc::Service::MarkMethodGeneric(18); } ~WithGenericMethod_LandingPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -4302,7 +4214,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodGeneric(20); + ::grpc::Service::MarkMethodGeneric(19); } ~WithGenericMethod_SetColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -4319,7 +4231,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodGeneric(21); + ::grpc::Service::MarkMethodGeneric(20); } ~WithGenericMethod_ColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -4336,7 +4248,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodGeneric(22); + ::grpc::Service::MarkMethodGeneric(21); } ~WithGenericMethod_CurrentEmailClient() override { BaseClassMustBeDerivedFromService(this); @@ -4353,7 +4265,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ReportBug() { - ::grpc::Service::MarkMethodGeneric(23); + ::grpc::Service::MarkMethodGeneric(22); } ~WithGenericMethod_ReportBug() override { BaseClassMustBeDerivedFromService(this); @@ -4370,7 +4282,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodGeneric(24); + ::grpc::Service::MarkMethodGeneric(23); } ~WithGenericMethod_ExportTLSCertificates() override { BaseClassMustBeDerivedFromService(this); @@ -4387,7 +4299,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ForceLauncher() { - ::grpc::Service::MarkMethodGeneric(25); + ::grpc::Service::MarkMethodGeneric(24); } ~WithGenericMethod_ForceLauncher() override { BaseClassMustBeDerivedFromService(this); @@ -4404,7 +4316,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodGeneric(26); + ::grpc::Service::MarkMethodGeneric(25); } ~WithGenericMethod_SetMainExecutable() override { BaseClassMustBeDerivedFromService(this); @@ -4421,7 +4333,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_Login() { - ::grpc::Service::MarkMethodGeneric(27); + ::grpc::Service::MarkMethodGeneric(26); } ~WithGenericMethod_Login() override { BaseClassMustBeDerivedFromService(this); @@ -4438,7 +4350,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_Login2FA() { - ::grpc::Service::MarkMethodGeneric(28); + ::grpc::Service::MarkMethodGeneric(27); } ~WithGenericMethod_Login2FA() override { BaseClassMustBeDerivedFromService(this); @@ -4455,7 +4367,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_Login2Passwords() { - ::grpc::Service::MarkMethodGeneric(29); + ::grpc::Service::MarkMethodGeneric(28); } ~WithGenericMethod_Login2Passwords() override { BaseClassMustBeDerivedFromService(this); @@ -4472,7 +4384,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_LoginAbort() { - ::grpc::Service::MarkMethodGeneric(30); + ::grpc::Service::MarkMethodGeneric(29); } ~WithGenericMethod_LoginAbort() override { BaseClassMustBeDerivedFromService(this); @@ -4489,7 +4401,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_CheckUpdate() { - ::grpc::Service::MarkMethodGeneric(31); + ::grpc::Service::MarkMethodGeneric(30); } ~WithGenericMethod_CheckUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -4506,7 +4418,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_InstallUpdate() { - ::grpc::Service::MarkMethodGeneric(32); + ::grpc::Service::MarkMethodGeneric(31); } ~WithGenericMethod_InstallUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -4523,7 +4435,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodGeneric(33); + ::grpc::Service::MarkMethodGeneric(32); } ~WithGenericMethod_SetIsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -4540,7 +4452,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodGeneric(34); + ::grpc::Service::MarkMethodGeneric(33); } ~WithGenericMethod_IsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -4557,7 +4469,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_DiskCachePath() { - ::grpc::Service::MarkMethodGeneric(35); + ::grpc::Service::MarkMethodGeneric(34); } ~WithGenericMethod_DiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -4574,7 +4486,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodGeneric(36); + ::grpc::Service::MarkMethodGeneric(35); } ~WithGenericMethod_SetDiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -4591,7 +4503,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodGeneric(37); + ::grpc::Service::MarkMethodGeneric(36); } ~WithGenericMethod_SetIsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -4608,7 +4520,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodGeneric(38); + ::grpc::Service::MarkMethodGeneric(37); } ~WithGenericMethod_IsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -4625,7 +4537,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_MailServerSettings() { - ::grpc::Service::MarkMethodGeneric(39); + ::grpc::Service::MarkMethodGeneric(38); } ~WithGenericMethod_MailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -4642,7 +4554,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodGeneric(40); + ::grpc::Service::MarkMethodGeneric(39); } ~WithGenericMethod_SetMailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -4659,7 +4571,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_Hostname() { - ::grpc::Service::MarkMethodGeneric(41); + ::grpc::Service::MarkMethodGeneric(40); } ~WithGenericMethod_Hostname() override { BaseClassMustBeDerivedFromService(this); @@ -4676,7 +4588,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_IsPortFree() { - ::grpc::Service::MarkMethodGeneric(42); + ::grpc::Service::MarkMethodGeneric(41); } ~WithGenericMethod_IsPortFree() override { BaseClassMustBeDerivedFromService(this); @@ -4693,7 +4605,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodGeneric(43); + ::grpc::Service::MarkMethodGeneric(42); } ~WithGenericMethod_AvailableKeychains() override { BaseClassMustBeDerivedFromService(this); @@ -4710,7 +4622,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodGeneric(44); + ::grpc::Service::MarkMethodGeneric(43); } ~WithGenericMethod_SetCurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -4727,7 +4639,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodGeneric(45); + ::grpc::Service::MarkMethodGeneric(44); } ~WithGenericMethod_CurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -4744,7 +4656,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_GetUserList() { - ::grpc::Service::MarkMethodGeneric(46); + ::grpc::Service::MarkMethodGeneric(45); } ~WithGenericMethod_GetUserList() override { BaseClassMustBeDerivedFromService(this); @@ -4761,7 +4673,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_GetUser() { - ::grpc::Service::MarkMethodGeneric(47); + ::grpc::Service::MarkMethodGeneric(46); } ~WithGenericMethod_GetUser() override { BaseClassMustBeDerivedFromService(this); @@ -4778,7 +4690,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodGeneric(48); + ::grpc::Service::MarkMethodGeneric(47); } ~WithGenericMethod_SetUserSplitMode() override { BaseClassMustBeDerivedFromService(this); @@ -4795,7 +4707,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_LogoutUser() { - ::grpc::Service::MarkMethodGeneric(49); + ::grpc::Service::MarkMethodGeneric(48); } ~WithGenericMethod_LogoutUser() override { BaseClassMustBeDerivedFromService(this); @@ -4812,7 +4724,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_RemoveUser() { - ::grpc::Service::MarkMethodGeneric(50); + ::grpc::Service::MarkMethodGeneric(49); } ~WithGenericMethod_RemoveUser() override { BaseClassMustBeDerivedFromService(this); @@ -4829,7 +4741,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodGeneric(51); + ::grpc::Service::MarkMethodGeneric(50); } ~WithGenericMethod_ConfigureUserAppleMail() override { BaseClassMustBeDerivedFromService(this); @@ -4846,7 +4758,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_RunEventStream() { - ::grpc::Service::MarkMethodGeneric(52); + ::grpc::Service::MarkMethodGeneric(51); } ~WithGenericMethod_RunEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -4863,7 +4775,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_StopEventStream() { - ::grpc::Service::MarkMethodGeneric(53); + ::grpc::Service::MarkMethodGeneric(52); } ~WithGenericMethod_StopEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -5115,32 +5027,12 @@ class Bridge final { } }; template - class WithRawMethod_GoOs : public BaseClass { - private: - void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} - public: - WithRawMethod_GoOs() { - ::grpc::Service::MarkMethodRaw(12); - } - ~WithRawMethod_GoOs() override { - BaseClassMustBeDerivedFromService(this); - } - // disable synchronous version of this method - ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { - abort(); - return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); - } - void RequestGoOs(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(12, context, request, response, new_call_cq, notification_cq, tag); - } - }; - template class WithRawMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_TriggerReset() { - ::grpc::Service::MarkMethodRaw(13); + ::grpc::Service::MarkMethodRaw(12); } ~WithRawMethod_TriggerReset() override { BaseClassMustBeDerivedFromService(this); @@ -5151,7 +5043,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestTriggerReset(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(13, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(12, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5160,7 +5052,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_Version() { - ::grpc::Service::MarkMethodRaw(14); + ::grpc::Service::MarkMethodRaw(13); } ~WithRawMethod_Version() override { BaseClassMustBeDerivedFromService(this); @@ -5171,7 +5063,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestVersion(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(14, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(13, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5180,7 +5072,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_LogsPath() { - ::grpc::Service::MarkMethodRaw(15); + ::grpc::Service::MarkMethodRaw(14); } ~WithRawMethod_LogsPath() override { BaseClassMustBeDerivedFromService(this); @@ -5191,7 +5083,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogsPath(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(15, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(14, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5200,7 +5092,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_LicensePath() { - ::grpc::Service::MarkMethodRaw(16); + ::grpc::Service::MarkMethodRaw(15); } ~WithRawMethod_LicensePath() override { BaseClassMustBeDerivedFromService(this); @@ -5211,7 +5103,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLicensePath(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(16, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(15, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5220,7 +5112,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodRaw(17); + ::grpc::Service::MarkMethodRaw(16); } ~WithRawMethod_ReleaseNotesPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -5231,7 +5123,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestReleaseNotesPageLink(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(17, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(16, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5240,7 +5132,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodRaw(18); + ::grpc::Service::MarkMethodRaw(17); } ~WithRawMethod_DependencyLicensesLink() override { BaseClassMustBeDerivedFromService(this); @@ -5251,7 +5143,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestDependencyLicensesLink(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(18, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(17, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5260,7 +5152,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_LandingPageLink() { - ::grpc::Service::MarkMethodRaw(19); + ::grpc::Service::MarkMethodRaw(18); } ~WithRawMethod_LandingPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -5271,7 +5163,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLandingPageLink(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(19, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(18, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5280,7 +5172,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodRaw(20); + ::grpc::Service::MarkMethodRaw(19); } ~WithRawMethod_SetColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -5291,7 +5183,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetColorSchemeName(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(20, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(19, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5300,7 +5192,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodRaw(21); + ::grpc::Service::MarkMethodRaw(20); } ~WithRawMethod_ColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -5311,7 +5203,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestColorSchemeName(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(21, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(20, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5320,7 +5212,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodRaw(22); + ::grpc::Service::MarkMethodRaw(21); } ~WithRawMethod_CurrentEmailClient() override { BaseClassMustBeDerivedFromService(this); @@ -5331,7 +5223,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCurrentEmailClient(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(22, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(21, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5340,7 +5232,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ReportBug() { - ::grpc::Service::MarkMethodRaw(23); + ::grpc::Service::MarkMethodRaw(22); } ~WithRawMethod_ReportBug() override { BaseClassMustBeDerivedFromService(this); @@ -5351,7 +5243,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestReportBug(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(23, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(22, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5360,7 +5252,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodRaw(24); + ::grpc::Service::MarkMethodRaw(23); } ~WithRawMethod_ExportTLSCertificates() override { BaseClassMustBeDerivedFromService(this); @@ -5371,7 +5263,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestExportTLSCertificates(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(24, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(23, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5380,7 +5272,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ForceLauncher() { - ::grpc::Service::MarkMethodRaw(25); + ::grpc::Service::MarkMethodRaw(24); } ~WithRawMethod_ForceLauncher() override { BaseClassMustBeDerivedFromService(this); @@ -5391,7 +5283,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestForceLauncher(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(25, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(24, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5400,7 +5292,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodRaw(26); + ::grpc::Service::MarkMethodRaw(25); } ~WithRawMethod_SetMainExecutable() override { BaseClassMustBeDerivedFromService(this); @@ -5411,7 +5303,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetMainExecutable(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(26, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(25, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5420,7 +5312,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_Login() { - ::grpc::Service::MarkMethodRaw(27); + ::grpc::Service::MarkMethodRaw(26); } ~WithRawMethod_Login() override { BaseClassMustBeDerivedFromService(this); @@ -5431,7 +5323,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(27, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(26, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5440,7 +5332,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_Login2FA() { - ::grpc::Service::MarkMethodRaw(28); + ::grpc::Service::MarkMethodRaw(27); } ~WithRawMethod_Login2FA() override { BaseClassMustBeDerivedFromService(this); @@ -5451,7 +5343,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin2FA(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(28, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(27, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5460,7 +5352,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_Login2Passwords() { - ::grpc::Service::MarkMethodRaw(29); + ::grpc::Service::MarkMethodRaw(28); } ~WithRawMethod_Login2Passwords() override { BaseClassMustBeDerivedFromService(this); @@ -5471,7 +5363,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin2Passwords(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(29, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(28, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5480,7 +5372,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_LoginAbort() { - ::grpc::Service::MarkMethodRaw(30); + ::grpc::Service::MarkMethodRaw(29); } ~WithRawMethod_LoginAbort() override { BaseClassMustBeDerivedFromService(this); @@ -5491,7 +5383,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLoginAbort(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(30, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(29, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5500,7 +5392,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_CheckUpdate() { - ::grpc::Service::MarkMethodRaw(31); + ::grpc::Service::MarkMethodRaw(30); } ~WithRawMethod_CheckUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -5511,7 +5403,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCheckUpdate(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(31, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(30, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5520,7 +5412,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_InstallUpdate() { - ::grpc::Service::MarkMethodRaw(32); + ::grpc::Service::MarkMethodRaw(31); } ~WithRawMethod_InstallUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -5531,7 +5423,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestInstallUpdate(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(32, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(31, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5540,7 +5432,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodRaw(33); + ::grpc::Service::MarkMethodRaw(32); } ~WithRawMethod_SetIsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -5551,7 +5443,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetIsAutomaticUpdateOn(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(33, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(32, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5560,7 +5452,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodRaw(34); + ::grpc::Service::MarkMethodRaw(33); } ~WithRawMethod_IsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -5571,7 +5463,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsAutomaticUpdateOn(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(34, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(33, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5580,7 +5472,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_DiskCachePath() { - ::grpc::Service::MarkMethodRaw(35); + ::grpc::Service::MarkMethodRaw(34); } ~WithRawMethod_DiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -5591,7 +5483,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestDiskCachePath(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(35, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(34, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5600,7 +5492,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodRaw(36); + ::grpc::Service::MarkMethodRaw(35); } ~WithRawMethod_SetDiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -5611,7 +5503,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetDiskCachePath(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(36, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(35, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5620,7 +5512,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodRaw(37); + ::grpc::Service::MarkMethodRaw(36); } ~WithRawMethod_SetIsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -5631,7 +5523,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetIsDoHEnabled(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(37, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(36, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5640,7 +5532,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodRaw(38); + ::grpc::Service::MarkMethodRaw(37); } ~WithRawMethod_IsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -5651,7 +5543,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsDoHEnabled(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(38, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(37, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5660,7 +5552,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_MailServerSettings() { - ::grpc::Service::MarkMethodRaw(39); + ::grpc::Service::MarkMethodRaw(38); } ~WithRawMethod_MailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -5671,7 +5563,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestMailServerSettings(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(39, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(38, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5680,7 +5572,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodRaw(40); + ::grpc::Service::MarkMethodRaw(39); } ~WithRawMethod_SetMailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -5691,7 +5583,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetMailServerSettings(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(40, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(39, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5700,7 +5592,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_Hostname() { - ::grpc::Service::MarkMethodRaw(41); + ::grpc::Service::MarkMethodRaw(40); } ~WithRawMethod_Hostname() override { BaseClassMustBeDerivedFromService(this); @@ -5711,7 +5603,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestHostname(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(41, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(40, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5720,7 +5612,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_IsPortFree() { - ::grpc::Service::MarkMethodRaw(42); + ::grpc::Service::MarkMethodRaw(41); } ~WithRawMethod_IsPortFree() override { BaseClassMustBeDerivedFromService(this); @@ -5731,7 +5623,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsPortFree(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(42, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(41, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5740,7 +5632,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodRaw(43); + ::grpc::Service::MarkMethodRaw(42); } ~WithRawMethod_AvailableKeychains() override { BaseClassMustBeDerivedFromService(this); @@ -5751,7 +5643,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestAvailableKeychains(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(43, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(42, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5760,7 +5652,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodRaw(44); + ::grpc::Service::MarkMethodRaw(43); } ~WithRawMethod_SetCurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -5771,7 +5663,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetCurrentKeychain(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(44, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(43, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5780,7 +5672,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodRaw(45); + ::grpc::Service::MarkMethodRaw(44); } ~WithRawMethod_CurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -5791,7 +5683,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCurrentKeychain(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(45, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(44, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5800,7 +5692,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_GetUserList() { - ::grpc::Service::MarkMethodRaw(46); + ::grpc::Service::MarkMethodRaw(45); } ~WithRawMethod_GetUserList() override { BaseClassMustBeDerivedFromService(this); @@ -5811,7 +5703,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestGetUserList(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(46, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(45, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5820,7 +5712,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_GetUser() { - ::grpc::Service::MarkMethodRaw(47); + ::grpc::Service::MarkMethodRaw(46); } ~WithRawMethod_GetUser() override { BaseClassMustBeDerivedFromService(this); @@ -5831,7 +5723,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestGetUser(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(47, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(46, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5840,7 +5732,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodRaw(48); + ::grpc::Service::MarkMethodRaw(47); } ~WithRawMethod_SetUserSplitMode() override { BaseClassMustBeDerivedFromService(this); @@ -5851,7 +5743,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetUserSplitMode(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(48, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(47, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5860,7 +5752,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_LogoutUser() { - ::grpc::Service::MarkMethodRaw(49); + ::grpc::Service::MarkMethodRaw(48); } ~WithRawMethod_LogoutUser() override { BaseClassMustBeDerivedFromService(this); @@ -5871,7 +5763,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogoutUser(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(49, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(48, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5880,7 +5772,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_RemoveUser() { - ::grpc::Service::MarkMethodRaw(50); + ::grpc::Service::MarkMethodRaw(49); } ~WithRawMethod_RemoveUser() override { BaseClassMustBeDerivedFromService(this); @@ -5891,7 +5783,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestRemoveUser(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(50, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(49, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5900,7 +5792,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodRaw(51); + ::grpc::Service::MarkMethodRaw(50); } ~WithRawMethod_ConfigureUserAppleMail() override { BaseClassMustBeDerivedFromService(this); @@ -5911,7 +5803,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestConfigureUserAppleMail(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(51, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(50, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5920,7 +5812,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_RunEventStream() { - ::grpc::Service::MarkMethodRaw(52); + ::grpc::Service::MarkMethodRaw(51); } ~WithRawMethod_RunEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -5931,7 +5823,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestRunEventStream(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncWriter< ::grpc::ByteBuffer>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncServerStreaming(52, context, request, writer, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncServerStreaming(51, context, request, writer, new_call_cq, notification_cq, tag); } }; template @@ -5940,7 +5832,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_StopEventStream() { - ::grpc::Service::MarkMethodRaw(53); + ::grpc::Service::MarkMethodRaw(52); } ~WithRawMethod_StopEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -5951,7 +5843,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestStopEventStream(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(53, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(52, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -6219,34 +6111,12 @@ class Bridge final { ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } }; template - class WithRawCallbackMethod_GoOs : public BaseClass { - private: - void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} - public: - WithRawCallbackMethod_GoOs() { - ::grpc::Service::MarkMethodRawCallback(12, - new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( - [this]( - ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->GoOs(context, request, response); })); - } - ~WithRawCallbackMethod_GoOs() override { - BaseClassMustBeDerivedFromService(this); - } - // disable synchronous version of this method - ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { - abort(); - return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); - } - virtual ::grpc::ServerUnaryReactor* GoOs( - ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } - }; - template class WithRawCallbackMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_TriggerReset() { - ::grpc::Service::MarkMethodRawCallback(13, + ::grpc::Service::MarkMethodRawCallback(12, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->TriggerReset(context, request, response); })); @@ -6268,7 +6138,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_Version() { - ::grpc::Service::MarkMethodRawCallback(14, + ::grpc::Service::MarkMethodRawCallback(13, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Version(context, request, response); })); @@ -6290,7 +6160,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_LogsPath() { - ::grpc::Service::MarkMethodRawCallback(15, + ::grpc::Service::MarkMethodRawCallback(14, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->LogsPath(context, request, response); })); @@ -6312,7 +6182,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_LicensePath() { - ::grpc::Service::MarkMethodRawCallback(16, + ::grpc::Service::MarkMethodRawCallback(15, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->LicensePath(context, request, response); })); @@ -6334,7 +6204,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodRawCallback(17, + ::grpc::Service::MarkMethodRawCallback(16, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ReleaseNotesPageLink(context, request, response); })); @@ -6356,7 +6226,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodRawCallback(18, + ::grpc::Service::MarkMethodRawCallback(17, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->DependencyLicensesLink(context, request, response); })); @@ -6378,7 +6248,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_LandingPageLink() { - ::grpc::Service::MarkMethodRawCallback(19, + ::grpc::Service::MarkMethodRawCallback(18, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->LandingPageLink(context, request, response); })); @@ -6400,7 +6270,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodRawCallback(20, + ::grpc::Service::MarkMethodRawCallback(19, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetColorSchemeName(context, request, response); })); @@ -6422,7 +6292,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodRawCallback(21, + ::grpc::Service::MarkMethodRawCallback(20, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ColorSchemeName(context, request, response); })); @@ -6444,7 +6314,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodRawCallback(22, + ::grpc::Service::MarkMethodRawCallback(21, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->CurrentEmailClient(context, request, response); })); @@ -6466,7 +6336,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ReportBug() { - ::grpc::Service::MarkMethodRawCallback(23, + ::grpc::Service::MarkMethodRawCallback(22, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ReportBug(context, request, response); })); @@ -6488,7 +6358,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodRawCallback(24, + ::grpc::Service::MarkMethodRawCallback(23, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ExportTLSCertificates(context, request, response); })); @@ -6510,7 +6380,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ForceLauncher() { - ::grpc::Service::MarkMethodRawCallback(25, + ::grpc::Service::MarkMethodRawCallback(24, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ForceLauncher(context, request, response); })); @@ -6532,7 +6402,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodRawCallback(26, + ::grpc::Service::MarkMethodRawCallback(25, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetMainExecutable(context, request, response); })); @@ -6554,7 +6424,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_Login() { - ::grpc::Service::MarkMethodRawCallback(27, + ::grpc::Service::MarkMethodRawCallback(26, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Login(context, request, response); })); @@ -6576,7 +6446,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_Login2FA() { - ::grpc::Service::MarkMethodRawCallback(28, + ::grpc::Service::MarkMethodRawCallback(27, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Login2FA(context, request, response); })); @@ -6598,7 +6468,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_Login2Passwords() { - ::grpc::Service::MarkMethodRawCallback(29, + ::grpc::Service::MarkMethodRawCallback(28, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Login2Passwords(context, request, response); })); @@ -6620,7 +6490,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_LoginAbort() { - ::grpc::Service::MarkMethodRawCallback(30, + ::grpc::Service::MarkMethodRawCallback(29, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->LoginAbort(context, request, response); })); @@ -6642,7 +6512,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_CheckUpdate() { - ::grpc::Service::MarkMethodRawCallback(31, + ::grpc::Service::MarkMethodRawCallback(30, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->CheckUpdate(context, request, response); })); @@ -6664,7 +6534,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_InstallUpdate() { - ::grpc::Service::MarkMethodRawCallback(32, + ::grpc::Service::MarkMethodRawCallback(31, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->InstallUpdate(context, request, response); })); @@ -6686,7 +6556,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodRawCallback(33, + ::grpc::Service::MarkMethodRawCallback(32, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetIsAutomaticUpdateOn(context, request, response); })); @@ -6708,7 +6578,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodRawCallback(34, + ::grpc::Service::MarkMethodRawCallback(33, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->IsAutomaticUpdateOn(context, request, response); })); @@ -6730,7 +6600,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_DiskCachePath() { - ::grpc::Service::MarkMethodRawCallback(35, + ::grpc::Service::MarkMethodRawCallback(34, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->DiskCachePath(context, request, response); })); @@ -6752,7 +6622,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodRawCallback(36, + ::grpc::Service::MarkMethodRawCallback(35, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetDiskCachePath(context, request, response); })); @@ -6774,7 +6644,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodRawCallback(37, + ::grpc::Service::MarkMethodRawCallback(36, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetIsDoHEnabled(context, request, response); })); @@ -6796,7 +6666,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodRawCallback(38, + ::grpc::Service::MarkMethodRawCallback(37, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->IsDoHEnabled(context, request, response); })); @@ -6818,7 +6688,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_MailServerSettings() { - ::grpc::Service::MarkMethodRawCallback(39, + ::grpc::Service::MarkMethodRawCallback(38, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->MailServerSettings(context, request, response); })); @@ -6840,7 +6710,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodRawCallback(40, + ::grpc::Service::MarkMethodRawCallback(39, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetMailServerSettings(context, request, response); })); @@ -6862,7 +6732,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_Hostname() { - ::grpc::Service::MarkMethodRawCallback(41, + ::grpc::Service::MarkMethodRawCallback(40, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Hostname(context, request, response); })); @@ -6884,7 +6754,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_IsPortFree() { - ::grpc::Service::MarkMethodRawCallback(42, + ::grpc::Service::MarkMethodRawCallback(41, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->IsPortFree(context, request, response); })); @@ -6906,7 +6776,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodRawCallback(43, + ::grpc::Service::MarkMethodRawCallback(42, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->AvailableKeychains(context, request, response); })); @@ -6928,7 +6798,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodRawCallback(44, + ::grpc::Service::MarkMethodRawCallback(43, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetCurrentKeychain(context, request, response); })); @@ -6950,7 +6820,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodRawCallback(45, + ::grpc::Service::MarkMethodRawCallback(44, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->CurrentKeychain(context, request, response); })); @@ -6972,7 +6842,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_GetUserList() { - ::grpc::Service::MarkMethodRawCallback(46, + ::grpc::Service::MarkMethodRawCallback(45, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->GetUserList(context, request, response); })); @@ -6994,7 +6864,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_GetUser() { - ::grpc::Service::MarkMethodRawCallback(47, + ::grpc::Service::MarkMethodRawCallback(46, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->GetUser(context, request, response); })); @@ -7016,7 +6886,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodRawCallback(48, + ::grpc::Service::MarkMethodRawCallback(47, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetUserSplitMode(context, request, response); })); @@ -7038,7 +6908,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_LogoutUser() { - ::grpc::Service::MarkMethodRawCallback(49, + ::grpc::Service::MarkMethodRawCallback(48, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->LogoutUser(context, request, response); })); @@ -7060,7 +6930,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_RemoveUser() { - ::grpc::Service::MarkMethodRawCallback(50, + ::grpc::Service::MarkMethodRawCallback(49, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->RemoveUser(context, request, response); })); @@ -7082,7 +6952,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodRawCallback(51, + ::grpc::Service::MarkMethodRawCallback(50, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ConfigureUserAppleMail(context, request, response); })); @@ -7104,7 +6974,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_RunEventStream() { - ::grpc::Service::MarkMethodRawCallback(52, + ::grpc::Service::MarkMethodRawCallback(51, new ::grpc::internal::CallbackServerStreamingHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const::grpc::ByteBuffer* request) { return this->RunEventStream(context, request); })); @@ -7126,7 +6996,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_StopEventStream() { - ::grpc::Service::MarkMethodRawCallback(53, + ::grpc::Service::MarkMethodRawCallback(52, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->StopEventStream(context, request, response); })); @@ -7467,39 +7337,12 @@ class Bridge final { virtual ::grpc::Status StreamedIsAllMailVisible(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::google::protobuf::Empty,::google::protobuf::BoolValue>* server_unary_streamer) = 0; }; template - class WithStreamedUnaryMethod_GoOs : public BaseClass { - private: - void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} - public: - WithStreamedUnaryMethod_GoOs() { - ::grpc::Service::MarkMethodStreamed(12, - new ::grpc::internal::StreamedUnaryHandler< - ::google::protobuf::Empty, ::google::protobuf::StringValue>( - [this](::grpc::ServerContext* context, - ::grpc::ServerUnaryStreamer< - ::google::protobuf::Empty, ::google::protobuf::StringValue>* streamer) { - return this->StreamedGoOs(context, - streamer); - })); - } - ~WithStreamedUnaryMethod_GoOs() override { - BaseClassMustBeDerivedFromService(this); - } - // disable regular version of this method - ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { - abort(); - return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); - } - // replace default version of method with streamed unary - virtual ::grpc::Status StreamedGoOs(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::google::protobuf::Empty,::google::protobuf::StringValue>* server_unary_streamer) = 0; - }; - template class WithStreamedUnaryMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_TriggerReset() { - ::grpc::Service::MarkMethodStreamed(13, + ::grpc::Service::MarkMethodStreamed(12, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7526,7 +7369,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_Version() { - ::grpc::Service::MarkMethodStreamed(14, + ::grpc::Service::MarkMethodStreamed(13, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7553,7 +7396,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_LogsPath() { - ::grpc::Service::MarkMethodStreamed(15, + ::grpc::Service::MarkMethodStreamed(14, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7580,7 +7423,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_LicensePath() { - ::grpc::Service::MarkMethodStreamed(16, + ::grpc::Service::MarkMethodStreamed(15, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7607,7 +7450,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodStreamed(17, + ::grpc::Service::MarkMethodStreamed(16, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7634,7 +7477,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodStreamed(18, + ::grpc::Service::MarkMethodStreamed(17, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7661,7 +7504,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_LandingPageLink() { - ::grpc::Service::MarkMethodStreamed(19, + ::grpc::Service::MarkMethodStreamed(18, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7688,7 +7531,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodStreamed(20, + ::grpc::Service::MarkMethodStreamed(19, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7715,7 +7558,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodStreamed(21, + ::grpc::Service::MarkMethodStreamed(20, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7742,7 +7585,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodStreamed(22, + ::grpc::Service::MarkMethodStreamed(21, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7769,7 +7612,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ReportBug() { - ::grpc::Service::MarkMethodStreamed(23, + ::grpc::Service::MarkMethodStreamed(22, new ::grpc::internal::StreamedUnaryHandler< ::grpc::ReportBugRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7796,7 +7639,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodStreamed(24, + ::grpc::Service::MarkMethodStreamed(23, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7823,7 +7666,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ForceLauncher() { - ::grpc::Service::MarkMethodStreamed(25, + ::grpc::Service::MarkMethodStreamed(24, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7850,7 +7693,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodStreamed(26, + ::grpc::Service::MarkMethodStreamed(25, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7877,7 +7720,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_Login() { - ::grpc::Service::MarkMethodStreamed(27, + ::grpc::Service::MarkMethodStreamed(26, new ::grpc::internal::StreamedUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7904,7 +7747,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_Login2FA() { - ::grpc::Service::MarkMethodStreamed(28, + ::grpc::Service::MarkMethodStreamed(27, new ::grpc::internal::StreamedUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7931,7 +7774,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_Login2Passwords() { - ::grpc::Service::MarkMethodStreamed(29, + ::grpc::Service::MarkMethodStreamed(28, new ::grpc::internal::StreamedUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7958,7 +7801,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_LoginAbort() { - ::grpc::Service::MarkMethodStreamed(30, + ::grpc::Service::MarkMethodStreamed(29, new ::grpc::internal::StreamedUnaryHandler< ::grpc::LoginAbortRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7985,7 +7828,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_CheckUpdate() { - ::grpc::Service::MarkMethodStreamed(31, + ::grpc::Service::MarkMethodStreamed(30, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8012,7 +7855,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_InstallUpdate() { - ::grpc::Service::MarkMethodStreamed(32, + ::grpc::Service::MarkMethodStreamed(31, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8039,7 +7882,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodStreamed(33, + ::grpc::Service::MarkMethodStreamed(32, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8066,7 +7909,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodStreamed(34, + ::grpc::Service::MarkMethodStreamed(33, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>( [this](::grpc::ServerContext* context, @@ -8093,7 +7936,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_DiskCachePath() { - ::grpc::Service::MarkMethodStreamed(35, + ::grpc::Service::MarkMethodStreamed(34, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -8120,7 +7963,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodStreamed(36, + ::grpc::Service::MarkMethodStreamed(35, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8147,7 +7990,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodStreamed(37, + ::grpc::Service::MarkMethodStreamed(36, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8174,7 +8017,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodStreamed(38, + ::grpc::Service::MarkMethodStreamed(37, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>( [this](::grpc::ServerContext* context, @@ -8201,7 +8044,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_MailServerSettings() { - ::grpc::Service::MarkMethodStreamed(39, + ::grpc::Service::MarkMethodStreamed(38, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::grpc::ImapSmtpSettings>( [this](::grpc::ServerContext* context, @@ -8228,7 +8071,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodStreamed(40, + ::grpc::Service::MarkMethodStreamed(39, new ::grpc::internal::StreamedUnaryHandler< ::grpc::ImapSmtpSettings, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8255,7 +8098,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_Hostname() { - ::grpc::Service::MarkMethodStreamed(41, + ::grpc::Service::MarkMethodStreamed(40, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -8282,7 +8125,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_IsPortFree() { - ::grpc::Service::MarkMethodStreamed(42, + ::grpc::Service::MarkMethodStreamed(41, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Int32Value, ::google::protobuf::BoolValue>( [this](::grpc::ServerContext* context, @@ -8309,7 +8152,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodStreamed(43, + ::grpc::Service::MarkMethodStreamed(42, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::grpc::AvailableKeychainsResponse>( [this](::grpc::ServerContext* context, @@ -8336,7 +8179,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodStreamed(44, + ::grpc::Service::MarkMethodStreamed(43, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8363,7 +8206,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodStreamed(45, + ::grpc::Service::MarkMethodStreamed(44, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -8390,7 +8233,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_GetUserList() { - ::grpc::Service::MarkMethodStreamed(46, + ::grpc::Service::MarkMethodStreamed(45, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::grpc::UserListResponse>( [this](::grpc::ServerContext* context, @@ -8417,7 +8260,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_GetUser() { - ::grpc::Service::MarkMethodStreamed(47, + ::grpc::Service::MarkMethodStreamed(46, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::grpc::User>( [this](::grpc::ServerContext* context, @@ -8444,7 +8287,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodStreamed(48, + ::grpc::Service::MarkMethodStreamed(47, new ::grpc::internal::StreamedUnaryHandler< ::grpc::UserSplitModeRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8471,7 +8314,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_LogoutUser() { - ::grpc::Service::MarkMethodStreamed(49, + ::grpc::Service::MarkMethodStreamed(48, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8498,7 +8341,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_RemoveUser() { - ::grpc::Service::MarkMethodStreamed(50, + ::grpc::Service::MarkMethodStreamed(49, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8525,7 +8368,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodStreamed(51, + ::grpc::Service::MarkMethodStreamed(50, new ::grpc::internal::StreamedUnaryHandler< ::grpc::ConfigureAppleMailRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8552,7 +8395,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_StopEventStream() { - ::grpc::Service::MarkMethodStreamed(53, + ::grpc::Service::MarkMethodStreamed(52, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8573,14 +8416,14 @@ class Bridge final { // replace default version of method with streamed unary virtual ::grpc::Status StreamedStopEventStream(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::google::protobuf::Empty,::google::protobuf::Empty>* server_unary_streamer) = 0; }; - typedef WithStreamedUnaryMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > StreamedUnaryService; + typedef WithStreamedUnaryMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > StreamedUnaryService; template class WithSplitStreamingMethod_RunEventStream : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithSplitStreamingMethod_RunEventStream() { - ::grpc::Service::MarkMethodStreamed(52, + ::grpc::Service::MarkMethodStreamed(51, new ::grpc::internal::SplitServerStreamingHandler< ::grpc::EventStreamRequest, ::grpc::StreamEvent>( [this](::grpc::ServerContext* context, @@ -8602,7 +8445,7 @@ class Bridge final { virtual ::grpc::Status StreamedRunEventStream(::grpc::ServerContext* context, ::grpc::ServerSplitStreamer< ::grpc::EventStreamRequest,::grpc::StreamEvent>* server_split_streamer) = 0; }; typedef WithSplitStreamingMethod_RunEventStream SplitStreamedService; - typedef WithStreamedUnaryMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > StreamedService; + typedef WithStreamedUnaryMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > StreamedService; }; } // namespace grpc diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc index 40954ecb..65a5edf0 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc @@ -1564,7 +1564,7 @@ const char descriptor_table_protodef_bridge_2eproto[] PROTOBUF_SECTION_VARIABLE( "OR\020\004\022%\n!SMTP_CONNECTION_MODE_CHANGE_ERRO" "R\020\005*S\n\tErrorCode\022\021\n\rUNKNOWN_ERROR\020\000\022\031\n\025T" "LS_CERT_EXPORT_ERROR\020\001\022\030\n\024TLS_KEY_EXPORT" - "_ERROR\020\0022\231\035\n\006Bridge\022I\n\013CheckTokens\022\034.goo" + "_ERROR\020\0022\333\034\n\006Bridge\022I\n\013CheckTokens\022\034.goo" "gle.protobuf.StringValue\032\034.google.protob" "uf.StringValue\022\?\n\013AddLogEntry\022\030.grpc.Add" "LogEntryRequest\032\026.google.protobuf.Empty\022" @@ -1584,82 +1584,80 @@ const char descriptor_table_protodef_bridge_2eproto[] PROTOBUF_SECTION_VARIABLE( "Value\022I\n\023SetIsAllMailVisible\022\032.google.pr" "otobuf.BoolValue\032\026.google.protobuf.Empty" "\022F\n\020IsAllMailVisible\022\026.google.protobuf.E" - "mpty\032\032.google.protobuf.BoolValue\022<\n\004GoOs" + "mpty\032\032.google.protobuf.BoolValue\022>\n\014Trig" + "gerReset\022\026.google.protobuf.Empty\032\026.googl" + "e.protobuf.Empty\022\?\n\007Version\022\026.google.pro" + "tobuf.Empty\032\034.google.protobuf.StringValu" + "e\022@\n\010LogsPath\022\026.google.protobuf.Empty\032\034." + "google.protobuf.StringValue\022C\n\013LicensePa" + "th\022\026.google.protobuf.Empty\032\034.google.prot" + "obuf.StringValue\022L\n\024ReleaseNotesPageLink" "\022\026.google.protobuf.Empty\032\034.google.protob" - "uf.StringValue\022>\n\014TriggerReset\022\026.google." - "protobuf.Empty\032\026.google.protobuf.Empty\022\?" - "\n\007Version\022\026.google.protobuf.Empty\032\034.goog" - "le.protobuf.StringValue\022@\n\010LogsPath\022\026.go" - "ogle.protobuf.Empty\032\034.google.protobuf.St" - "ringValue\022C\n\013LicensePath\022\026.google.protob" - "uf.Empty\032\034.google.protobuf.StringValue\022L" - "\n\024ReleaseNotesPageLink\022\026.google.protobuf" - ".Empty\032\034.google.protobuf.StringValue\022N\n\026" - "DependencyLicensesLink\022\026.google.protobuf" - ".Empty\032\034.google.protobuf.StringValue\022G\n\017" - "LandingPageLink\022\026.google.protobuf.Empty\032" - "\034.google.protobuf.StringValue\022J\n\022SetColo" - "rSchemeName\022\034.google.protobuf.StringValu" - "e\032\026.google.protobuf.Empty\022G\n\017ColorScheme" - "Name\022\026.google.protobuf.Empty\032\034.google.pr" - "otobuf.StringValue\022J\n\022CurrentEmailClient" + "uf.StringValue\022N\n\026DependencyLicensesLink" "\022\026.google.protobuf.Empty\032\034.google.protob" - "uf.StringValue\022;\n\tReportBug\022\026.grpc.Repor" - "tBugRequest\032\026.google.protobuf.Empty\022M\n\025E" - "xportTLSCertificates\022\034.google.protobuf.S" - "tringValue\032\026.google.protobuf.Empty\022E\n\rFo" - "rceLauncher\022\034.google.protobuf.StringValu" - "e\032\026.google.protobuf.Empty\022I\n\021SetMainExec" - "utable\022\034.google.protobuf.StringValue\032\026.g" - "oogle.protobuf.Empty\0223\n\005Login\022\022.grpc.Log" - "inRequest\032\026.google.protobuf.Empty\0226\n\010Log" - "in2FA\022\022.grpc.LoginRequest\032\026.google.proto" - "buf.Empty\022=\n\017Login2Passwords\022\022.grpc.Logi" - "nRequest\032\026.google.protobuf.Empty\022=\n\nLogi" - "nAbort\022\027.grpc.LoginAbortRequest\032\026.google" - ".protobuf.Empty\022=\n\013CheckUpdate\022\026.google." - "protobuf.Empty\032\026.google.protobuf.Empty\022\?" - "\n\rInstallUpdate\022\026.google.protobuf.Empty\032" - "\026.google.protobuf.Empty\022L\n\026SetIsAutomati" - "cUpdateOn\022\032.google.protobuf.BoolValue\032\026." - "google.protobuf.Empty\022I\n\023IsAutomaticUpda" - "teOn\022\026.google.protobuf.Empty\032\032.google.pr" - "otobuf.BoolValue\022E\n\rDiskCachePath\022\026.goog" + "uf.StringValue\022G\n\017LandingPageLink\022\026.goog" "le.protobuf.Empty\032\034.google.protobuf.Stri" - "ngValue\022H\n\020SetDiskCachePath\022\034.google.pro" - "tobuf.StringValue\032\026.google.protobuf.Empt" - "y\022E\n\017SetIsDoHEnabled\022\032.google.protobuf.B" - "oolValue\032\026.google.protobuf.Empty\022B\n\014IsDo" - "HEnabled\022\026.google.protobuf.Empty\032\032.googl" - "e.protobuf.BoolValue\022D\n\022MailServerSettin" - "gs\022\026.google.protobuf.Empty\032\026.grpc.ImapSm" - "tpSettings\022G\n\025SetMailServerSettings\022\026.gr" - "pc.ImapSmtpSettings\032\026.google.protobuf.Em" - "pty\022@\n\010Hostname\022\026.google.protobuf.Empty\032" - "\034.google.protobuf.StringValue\022E\n\nIsPortF" - "ree\022\033.google.protobuf.Int32Value\032\032.googl" - "e.protobuf.BoolValue\022N\n\022AvailableKeychai" - "ns\022\026.google.protobuf.Empty\032 .grpc.Availa" - "bleKeychainsResponse\022J\n\022SetCurrentKeycha" - "in\022\034.google.protobuf.StringValue\032\026.googl" - "e.protobuf.Empty\022G\n\017CurrentKeychain\022\026.go" - "ogle.protobuf.Empty\032\034.google.protobuf.St" - "ringValue\022=\n\013GetUserList\022\026.google.protob" - "uf.Empty\032\026.grpc.UserListResponse\0223\n\007GetU" - "ser\022\034.google.protobuf.StringValue\032\n.grpc" - ".User\022F\n\020SetUserSplitMode\022\032.grpc.UserSpl" - "itModeRequest\032\026.google.protobuf.Empty\022B\n" - "\nLogoutUser\022\034.google.protobuf.StringValu" - "e\032\026.google.protobuf.Empty\022B\n\nRemoveUser\022" - "\034.google.protobuf.StringValue\032\026.google.p" - "rotobuf.Empty\022Q\n\026ConfigureUserAppleMail\022" - "\037.grpc.ConfigureAppleMailRequest\032\026.googl" - "e.protobuf.Empty\022\?\n\016RunEventStream\022\030.grp" - "c.EventStreamRequest\032\021.grpc.StreamEvent0" - "\001\022A\n\017StopEventStream\022\026.google.protobuf.E" - "mpty\032\026.google.protobuf.EmptyB6Z4github.c" - "om/ProtonMail/proton-bridge/v3/internal/" - "grpcb\006proto3" + "ngValue\022J\n\022SetColorSchemeName\022\034.google.p" + "rotobuf.StringValue\032\026.google.protobuf.Em" + "pty\022G\n\017ColorSchemeName\022\026.google.protobuf" + ".Empty\032\034.google.protobuf.StringValue\022J\n\022" + "CurrentEmailClient\022\026.google.protobuf.Emp" + "ty\032\034.google.protobuf.StringValue\022;\n\tRepo" + "rtBug\022\026.grpc.ReportBugRequest\032\026.google.p" + "rotobuf.Empty\022M\n\025ExportTLSCertificates\022\034" + ".google.protobuf.StringValue\032\026.google.pr" + "otobuf.Empty\022E\n\rForceLauncher\022\034.google.p" + "rotobuf.StringValue\032\026.google.protobuf.Em" + "pty\022I\n\021SetMainExecutable\022\034.google.protob" + "uf.StringValue\032\026.google.protobuf.Empty\0223" + "\n\005Login\022\022.grpc.LoginRequest\032\026.google.pro" + "tobuf.Empty\0226\n\010Login2FA\022\022.grpc.LoginRequ" + "est\032\026.google.protobuf.Empty\022=\n\017Login2Pas" + "swords\022\022.grpc.LoginRequest\032\026.google.prot" + "obuf.Empty\022=\n\nLoginAbort\022\027.grpc.LoginAbo" + "rtRequest\032\026.google.protobuf.Empty\022=\n\013Che" + "ckUpdate\022\026.google.protobuf.Empty\032\026.googl" + "e.protobuf.Empty\022\?\n\rInstallUpdate\022\026.goog" + "le.protobuf.Empty\032\026.google.protobuf.Empt" + "y\022L\n\026SetIsAutomaticUpdateOn\022\032.google.pro" + "tobuf.BoolValue\032\026.google.protobuf.Empty\022" + "I\n\023IsAutomaticUpdateOn\022\026.google.protobuf" + ".Empty\032\032.google.protobuf.BoolValue\022E\n\rDi" + "skCachePath\022\026.google.protobuf.Empty\032\034.go" + "ogle.protobuf.StringValue\022H\n\020SetDiskCach" + "ePath\022\034.google.protobuf.StringValue\032\026.go" + "ogle.protobuf.Empty\022E\n\017SetIsDoHEnabled\022\032" + ".google.protobuf.BoolValue\032\026.google.prot" + "obuf.Empty\022B\n\014IsDoHEnabled\022\026.google.prot" + "obuf.Empty\032\032.google.protobuf.BoolValue\022D" + "\n\022MailServerSettings\022\026.google.protobuf.E" + "mpty\032\026.grpc.ImapSmtpSettings\022G\n\025SetMailS" + "erverSettings\022\026.grpc.ImapSmtpSettings\032\026." + "google.protobuf.Empty\022@\n\010Hostname\022\026.goog" + "le.protobuf.Empty\032\034.google.protobuf.Stri" + "ngValue\022E\n\nIsPortFree\022\033.google.protobuf." + "Int32Value\032\032.google.protobuf.BoolValue\022N" + "\n\022AvailableKeychains\022\026.google.protobuf.E" + "mpty\032 .grpc.AvailableKeychainsResponse\022J" + "\n\022SetCurrentKeychain\022\034.google.protobuf.S" + "tringValue\032\026.google.protobuf.Empty\022G\n\017Cu" + "rrentKeychain\022\026.google.protobuf.Empty\032\034." + "google.protobuf.StringValue\022=\n\013GetUserLi" + "st\022\026.google.protobuf.Empty\032\026.grpc.UserLi" + "stResponse\0223\n\007GetUser\022\034.google.protobuf." + "StringValue\032\n.grpc.User\022F\n\020SetUserSplitM" + "ode\022\032.grpc.UserSplitModeRequest\032\026.google" + ".protobuf.Empty\022B\n\nLogoutUser\022\034.google.p" + "rotobuf.StringValue\032\026.google.protobuf.Em" + "pty\022B\n\nRemoveUser\022\034.google.protobuf.Stri" + "ngValue\032\026.google.protobuf.Empty\022Q\n\026Confi" + "gureUserAppleMail\022\037.grpc.ConfigureAppleM" + "ailRequest\032\026.google.protobuf.Empty\022\?\n\016Ru" + "nEventStream\022\030.grpc.EventStreamRequest\032\021" + ".grpc.StreamEvent0\001\022A\n\017StopEventStream\022\026" + ".google.protobuf.Empty\032\026.google.protobuf" + ".EmptyB6Z4github.com/ProtonMail/proton-b" + "ridge/v3/internal/grpcb\006proto3" ; static const ::_pbi::DescriptorTable* const descriptor_table_bridge_2eproto_deps[2] = { &::descriptor_table_google_2fprotobuf_2fempty_2eproto, @@ -1667,7 +1665,7 @@ static const ::_pbi::DescriptorTable* const descriptor_table_bridge_2eproto_deps }; static ::_pbi::once_flag descriptor_table_bridge_2eproto_once; const ::_pbi::DescriptorTable descriptor_table_bridge_2eproto = { - false, false, 10052, descriptor_table_protodef_bridge_2eproto, + false, false, 9990, descriptor_table_protodef_bridge_2eproto, "bridge.proto", &descriptor_table_bridge_2eproto_once, descriptor_table_bridge_2eproto_deps, 2, 60, schemas, file_default_instances, TableStruct_bridge_2eproto::offsets, diff --git a/internal/frontend/grpc/bridge.pb.go b/internal/frontend/grpc/bridge.pb.go index 4a291990..a9998433 100644 --- a/internal/frontend/grpc/bridge.pb.go +++ b/internal/frontend/grpc/bridge.pb.go @@ -4509,7 +4509,7 @@ var file_bridge_proto_rawDesc = []byte{ 0x4c, 0x53, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x4c, 0x53, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, - 0x32, 0x99, 0x1d, 0x0a, 0x06, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x43, + 0x32, 0xdb, 0x1c, 0x0a, 0x06, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, @@ -4560,193 +4560,189 @@ var file_bridge_proto_rawDesc = []byte{ 0x69, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, - 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x47, 0x6f, 0x4f, 0x73, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, - 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x73, 0x50, - 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x54, 0x72, 0x69, 0x67, + 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, + 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x63, - 0x65, 0x6e, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x4c, 0x6f, 0x67, + 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x0b, 0x4c, + 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x4c, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, + 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4c, - 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x50, 0x61, - 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x16, - 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, - 0x65, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x47, 0x0a, 0x0f, - 0x4c, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, - 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, - 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x43, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3b, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, - 0x42, 0x75, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x42, 0x75, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, + 0x0a, 0x16, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x63, 0x65, + 0x6e, 0x73, 0x65, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x47, + 0x0a, 0x0f, 0x4c, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, + 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x6f, + 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x4d, 0x0a, 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x4c, 0x53, - 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0d, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x75, 0x6e, 0x63, - 0x68, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x11, 0x53, 0x65, 0x74, - 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1c, + 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, + 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3b, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x6f, + 0x72, 0x74, 0x42, 0x75, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x70, + 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4d, 0x0a, 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x54, + 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x12, 0x2e, - 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x4c, 0x6f, 0x67, - 0x69, 0x6e, 0x32, 0x46, 0x41, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, - 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x3d, 0x0a, 0x0f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x50, 0x61, 0x73, 0x73, 0x77, - 0x6f, 0x72, 0x64, 0x73, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x3d, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x17, - 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x3d, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, + 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0d, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x75, + 0x6e, 0x63, 0x68, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x11, 0x53, + 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, + 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, - 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x4c, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, - 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, - 0x13, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, - 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, - 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x6b, - 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, - 0x48, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, - 0x61, 0x74, 0x68, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0f, 0x53, 0x65, 0x74, - 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, - 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x42, 0x0a, 0x0c, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, 0x0a, 0x12, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, - 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, - 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x15, 0x53, 0x65, - 0x74, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, - 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, - 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, + 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x46, 0x41, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x49, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x46, - 0x72, 0x65, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x12, - 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, - 0x6e, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, - 0x53, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, - 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x50, 0x61, 0x73, + 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, + 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, + 0x12, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, + 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x3f, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x4c, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, + 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, + 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x49, 0x0a, 0x13, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0d, 0x44, 0x69, + 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, - 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, - 0x12, 0x33, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x0a, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, - 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, - 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, - 0x0a, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x51, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x12, - 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, - 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, - 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x74, 0x6f, - 0x70, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x67, + 0x65, 0x12, 0x48, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, + 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0f, 0x53, + 0x65, 0x74, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0c, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, + 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, + 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, 0x0a, 0x12, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, + 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x36, 0x5a, 0x34, - 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x50, 0x72, 0x6f, 0x74, 0x6f, - 0x6e, 0x4d, 0x61, 0x69, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2d, 0x62, 0x72, 0x69, - 0x64, 0x67, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, - 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, + 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x15, + 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, + 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, + 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x49, 0x73, 0x50, 0x6f, 0x72, + 0x74, 0x46, 0x72, 0x65, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, + 0x0a, 0x12, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, + 0x61, 0x69, 0x6e, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, + 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, + 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, + 0x68, 0x61, 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, + 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, + 0x73, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x0a, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x55, 0x73, + 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, + 0x42, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, + 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x51, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x67, 0x75, 0x72, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, + 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, + 0x72, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x75, + 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, + 0x72, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, + 0x74, 0x6f, 0x70, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x36, + 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x50, 0x72, 0x6f, + 0x74, 0x6f, 0x6e, 0x4d, 0x61, 0x69, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2d, 0x62, + 0x72, 0x69, 0x64, 0x67, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, + 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4906,104 +4902,102 @@ var file_bridge_proto_depIdxs = []int32{ 68, // 66: grpc.Bridge.IsBetaEnabled:input_type -> google.protobuf.Empty 69, // 67: grpc.Bridge.SetIsAllMailVisible:input_type -> google.protobuf.BoolValue 68, // 68: grpc.Bridge.IsAllMailVisible:input_type -> google.protobuf.Empty - 68, // 69: grpc.Bridge.GoOs:input_type -> google.protobuf.Empty - 68, // 70: grpc.Bridge.TriggerReset:input_type -> google.protobuf.Empty - 68, // 71: grpc.Bridge.Version:input_type -> google.protobuf.Empty - 68, // 72: grpc.Bridge.LogsPath:input_type -> google.protobuf.Empty - 68, // 73: grpc.Bridge.LicensePath:input_type -> google.protobuf.Empty - 68, // 74: grpc.Bridge.ReleaseNotesPageLink:input_type -> google.protobuf.Empty - 68, // 75: grpc.Bridge.DependencyLicensesLink:input_type -> google.protobuf.Empty - 68, // 76: grpc.Bridge.LandingPageLink:input_type -> google.protobuf.Empty - 67, // 77: grpc.Bridge.SetColorSchemeName:input_type -> google.protobuf.StringValue - 68, // 78: grpc.Bridge.ColorSchemeName:input_type -> google.protobuf.Empty - 68, // 79: grpc.Bridge.CurrentEmailClient:input_type -> google.protobuf.Empty - 9, // 80: grpc.Bridge.ReportBug:input_type -> grpc.ReportBugRequest - 67, // 81: grpc.Bridge.ExportTLSCertificates:input_type -> google.protobuf.StringValue - 67, // 82: grpc.Bridge.ForceLauncher:input_type -> google.protobuf.StringValue - 67, // 83: grpc.Bridge.SetMainExecutable:input_type -> google.protobuf.StringValue - 10, // 84: grpc.Bridge.Login:input_type -> grpc.LoginRequest - 10, // 85: grpc.Bridge.Login2FA:input_type -> grpc.LoginRequest - 10, // 86: grpc.Bridge.Login2Passwords:input_type -> grpc.LoginRequest - 11, // 87: grpc.Bridge.LoginAbort:input_type -> grpc.LoginAbortRequest - 68, // 88: grpc.Bridge.CheckUpdate:input_type -> google.protobuf.Empty - 68, // 89: grpc.Bridge.InstallUpdate:input_type -> google.protobuf.Empty - 69, // 90: grpc.Bridge.SetIsAutomaticUpdateOn:input_type -> google.protobuf.BoolValue - 68, // 91: grpc.Bridge.IsAutomaticUpdateOn:input_type -> google.protobuf.Empty - 68, // 92: grpc.Bridge.DiskCachePath:input_type -> google.protobuf.Empty - 67, // 93: grpc.Bridge.SetDiskCachePath:input_type -> google.protobuf.StringValue - 69, // 94: grpc.Bridge.SetIsDoHEnabled:input_type -> google.protobuf.BoolValue - 68, // 95: grpc.Bridge.IsDoHEnabled:input_type -> google.protobuf.Empty - 68, // 96: grpc.Bridge.MailServerSettings:input_type -> google.protobuf.Empty - 12, // 97: grpc.Bridge.SetMailServerSettings:input_type -> grpc.ImapSmtpSettings - 68, // 98: grpc.Bridge.Hostname:input_type -> google.protobuf.Empty - 70, // 99: grpc.Bridge.IsPortFree:input_type -> google.protobuf.Int32Value - 68, // 100: grpc.Bridge.AvailableKeychains:input_type -> google.protobuf.Empty - 67, // 101: grpc.Bridge.SetCurrentKeychain:input_type -> google.protobuf.StringValue - 68, // 102: grpc.Bridge.CurrentKeychain:input_type -> google.protobuf.Empty - 68, // 103: grpc.Bridge.GetUserList:input_type -> google.protobuf.Empty - 67, // 104: grpc.Bridge.GetUser:input_type -> google.protobuf.StringValue - 15, // 105: grpc.Bridge.SetUserSplitMode:input_type -> grpc.UserSplitModeRequest - 67, // 106: grpc.Bridge.LogoutUser:input_type -> google.protobuf.StringValue - 67, // 107: grpc.Bridge.RemoveUser:input_type -> google.protobuf.StringValue - 17, // 108: grpc.Bridge.ConfigureUserAppleMail:input_type -> grpc.ConfigureAppleMailRequest - 18, // 109: grpc.Bridge.RunEventStream:input_type -> grpc.EventStreamRequest - 68, // 110: grpc.Bridge.StopEventStream:input_type -> google.protobuf.Empty - 67, // 111: grpc.Bridge.CheckTokens:output_type -> google.protobuf.StringValue - 68, // 112: grpc.Bridge.AddLogEntry:output_type -> google.protobuf.Empty - 8, // 113: grpc.Bridge.GuiReady:output_type -> grpc.GuiReadyResponse - 68, // 114: grpc.Bridge.Quit:output_type -> google.protobuf.Empty - 68, // 115: grpc.Bridge.Restart:output_type -> google.protobuf.Empty - 69, // 116: grpc.Bridge.ShowOnStartup:output_type -> google.protobuf.BoolValue - 68, // 117: grpc.Bridge.SetIsAutostartOn:output_type -> google.protobuf.Empty - 69, // 118: grpc.Bridge.IsAutostartOn:output_type -> google.protobuf.BoolValue - 68, // 119: grpc.Bridge.SetIsBetaEnabled:output_type -> google.protobuf.Empty - 69, // 120: grpc.Bridge.IsBetaEnabled:output_type -> google.protobuf.BoolValue - 68, // 121: grpc.Bridge.SetIsAllMailVisible:output_type -> google.protobuf.Empty - 69, // 122: grpc.Bridge.IsAllMailVisible:output_type -> google.protobuf.BoolValue - 67, // 123: grpc.Bridge.GoOs:output_type -> google.protobuf.StringValue - 68, // 124: grpc.Bridge.TriggerReset:output_type -> google.protobuf.Empty - 67, // 125: grpc.Bridge.Version:output_type -> google.protobuf.StringValue - 67, // 126: grpc.Bridge.LogsPath:output_type -> google.protobuf.StringValue - 67, // 127: grpc.Bridge.LicensePath:output_type -> google.protobuf.StringValue - 67, // 128: grpc.Bridge.ReleaseNotesPageLink:output_type -> google.protobuf.StringValue - 67, // 129: grpc.Bridge.DependencyLicensesLink:output_type -> google.protobuf.StringValue - 67, // 130: grpc.Bridge.LandingPageLink:output_type -> google.protobuf.StringValue - 68, // 131: grpc.Bridge.SetColorSchemeName:output_type -> google.protobuf.Empty - 67, // 132: grpc.Bridge.ColorSchemeName:output_type -> google.protobuf.StringValue - 67, // 133: grpc.Bridge.CurrentEmailClient:output_type -> google.protobuf.StringValue - 68, // 134: grpc.Bridge.ReportBug:output_type -> google.protobuf.Empty - 68, // 135: grpc.Bridge.ExportTLSCertificates:output_type -> google.protobuf.Empty - 68, // 136: grpc.Bridge.ForceLauncher:output_type -> google.protobuf.Empty - 68, // 137: grpc.Bridge.SetMainExecutable:output_type -> google.protobuf.Empty - 68, // 138: grpc.Bridge.Login:output_type -> google.protobuf.Empty - 68, // 139: grpc.Bridge.Login2FA:output_type -> google.protobuf.Empty - 68, // 140: grpc.Bridge.Login2Passwords:output_type -> google.protobuf.Empty - 68, // 141: grpc.Bridge.LoginAbort:output_type -> google.protobuf.Empty - 68, // 142: grpc.Bridge.CheckUpdate:output_type -> google.protobuf.Empty - 68, // 143: grpc.Bridge.InstallUpdate:output_type -> google.protobuf.Empty - 68, // 144: grpc.Bridge.SetIsAutomaticUpdateOn:output_type -> google.protobuf.Empty - 69, // 145: grpc.Bridge.IsAutomaticUpdateOn:output_type -> google.protobuf.BoolValue - 67, // 146: grpc.Bridge.DiskCachePath:output_type -> google.protobuf.StringValue - 68, // 147: grpc.Bridge.SetDiskCachePath:output_type -> google.protobuf.Empty - 68, // 148: grpc.Bridge.SetIsDoHEnabled:output_type -> google.protobuf.Empty - 69, // 149: grpc.Bridge.IsDoHEnabled:output_type -> google.protobuf.BoolValue - 12, // 150: grpc.Bridge.MailServerSettings:output_type -> grpc.ImapSmtpSettings - 68, // 151: grpc.Bridge.SetMailServerSettings:output_type -> google.protobuf.Empty - 67, // 152: grpc.Bridge.Hostname:output_type -> google.protobuf.StringValue - 69, // 153: grpc.Bridge.IsPortFree:output_type -> google.protobuf.BoolValue - 13, // 154: grpc.Bridge.AvailableKeychains:output_type -> grpc.AvailableKeychainsResponse - 68, // 155: grpc.Bridge.SetCurrentKeychain:output_type -> google.protobuf.Empty - 67, // 156: grpc.Bridge.CurrentKeychain:output_type -> google.protobuf.StringValue - 16, // 157: grpc.Bridge.GetUserList:output_type -> grpc.UserListResponse - 14, // 158: grpc.Bridge.GetUser:output_type -> grpc.User - 68, // 159: grpc.Bridge.SetUserSplitMode:output_type -> google.protobuf.Empty - 68, // 160: grpc.Bridge.LogoutUser:output_type -> google.protobuf.Empty - 68, // 161: grpc.Bridge.RemoveUser:output_type -> google.protobuf.Empty - 68, // 162: grpc.Bridge.ConfigureUserAppleMail:output_type -> google.protobuf.Empty - 19, // 163: grpc.Bridge.RunEventStream:output_type -> grpc.StreamEvent - 68, // 164: grpc.Bridge.StopEventStream:output_type -> google.protobuf.Empty - 111, // [111:165] is the sub-list for method output_type - 57, // [57:111] is the sub-list for method input_type + 68, // 69: grpc.Bridge.TriggerReset:input_type -> google.protobuf.Empty + 68, // 70: grpc.Bridge.Version:input_type -> google.protobuf.Empty + 68, // 71: grpc.Bridge.LogsPath:input_type -> google.protobuf.Empty + 68, // 72: grpc.Bridge.LicensePath:input_type -> google.protobuf.Empty + 68, // 73: grpc.Bridge.ReleaseNotesPageLink:input_type -> google.protobuf.Empty + 68, // 74: grpc.Bridge.DependencyLicensesLink:input_type -> google.protobuf.Empty + 68, // 75: grpc.Bridge.LandingPageLink:input_type -> google.protobuf.Empty + 67, // 76: grpc.Bridge.SetColorSchemeName:input_type -> google.protobuf.StringValue + 68, // 77: grpc.Bridge.ColorSchemeName:input_type -> google.protobuf.Empty + 68, // 78: grpc.Bridge.CurrentEmailClient:input_type -> google.protobuf.Empty + 9, // 79: grpc.Bridge.ReportBug:input_type -> grpc.ReportBugRequest + 67, // 80: grpc.Bridge.ExportTLSCertificates:input_type -> google.protobuf.StringValue + 67, // 81: grpc.Bridge.ForceLauncher:input_type -> google.protobuf.StringValue + 67, // 82: grpc.Bridge.SetMainExecutable:input_type -> google.protobuf.StringValue + 10, // 83: grpc.Bridge.Login:input_type -> grpc.LoginRequest + 10, // 84: grpc.Bridge.Login2FA:input_type -> grpc.LoginRequest + 10, // 85: grpc.Bridge.Login2Passwords:input_type -> grpc.LoginRequest + 11, // 86: grpc.Bridge.LoginAbort:input_type -> grpc.LoginAbortRequest + 68, // 87: grpc.Bridge.CheckUpdate:input_type -> google.protobuf.Empty + 68, // 88: grpc.Bridge.InstallUpdate:input_type -> google.protobuf.Empty + 69, // 89: grpc.Bridge.SetIsAutomaticUpdateOn:input_type -> google.protobuf.BoolValue + 68, // 90: grpc.Bridge.IsAutomaticUpdateOn:input_type -> google.protobuf.Empty + 68, // 91: grpc.Bridge.DiskCachePath:input_type -> google.protobuf.Empty + 67, // 92: grpc.Bridge.SetDiskCachePath:input_type -> google.protobuf.StringValue + 69, // 93: grpc.Bridge.SetIsDoHEnabled:input_type -> google.protobuf.BoolValue + 68, // 94: grpc.Bridge.IsDoHEnabled:input_type -> google.protobuf.Empty + 68, // 95: grpc.Bridge.MailServerSettings:input_type -> google.protobuf.Empty + 12, // 96: grpc.Bridge.SetMailServerSettings:input_type -> grpc.ImapSmtpSettings + 68, // 97: grpc.Bridge.Hostname:input_type -> google.protobuf.Empty + 70, // 98: grpc.Bridge.IsPortFree:input_type -> google.protobuf.Int32Value + 68, // 99: grpc.Bridge.AvailableKeychains:input_type -> google.protobuf.Empty + 67, // 100: grpc.Bridge.SetCurrentKeychain:input_type -> google.protobuf.StringValue + 68, // 101: grpc.Bridge.CurrentKeychain:input_type -> google.protobuf.Empty + 68, // 102: grpc.Bridge.GetUserList:input_type -> google.protobuf.Empty + 67, // 103: grpc.Bridge.GetUser:input_type -> google.protobuf.StringValue + 15, // 104: grpc.Bridge.SetUserSplitMode:input_type -> grpc.UserSplitModeRequest + 67, // 105: grpc.Bridge.LogoutUser:input_type -> google.protobuf.StringValue + 67, // 106: grpc.Bridge.RemoveUser:input_type -> google.protobuf.StringValue + 17, // 107: grpc.Bridge.ConfigureUserAppleMail:input_type -> grpc.ConfigureAppleMailRequest + 18, // 108: grpc.Bridge.RunEventStream:input_type -> grpc.EventStreamRequest + 68, // 109: grpc.Bridge.StopEventStream:input_type -> google.protobuf.Empty + 67, // 110: grpc.Bridge.CheckTokens:output_type -> google.protobuf.StringValue + 68, // 111: grpc.Bridge.AddLogEntry:output_type -> google.protobuf.Empty + 8, // 112: grpc.Bridge.GuiReady:output_type -> grpc.GuiReadyResponse + 68, // 113: grpc.Bridge.Quit:output_type -> google.protobuf.Empty + 68, // 114: grpc.Bridge.Restart:output_type -> google.protobuf.Empty + 69, // 115: grpc.Bridge.ShowOnStartup:output_type -> google.protobuf.BoolValue + 68, // 116: grpc.Bridge.SetIsAutostartOn:output_type -> google.protobuf.Empty + 69, // 117: grpc.Bridge.IsAutostartOn:output_type -> google.protobuf.BoolValue + 68, // 118: grpc.Bridge.SetIsBetaEnabled:output_type -> google.protobuf.Empty + 69, // 119: grpc.Bridge.IsBetaEnabled:output_type -> google.protobuf.BoolValue + 68, // 120: grpc.Bridge.SetIsAllMailVisible:output_type -> google.protobuf.Empty + 69, // 121: grpc.Bridge.IsAllMailVisible:output_type -> google.protobuf.BoolValue + 68, // 122: grpc.Bridge.TriggerReset:output_type -> google.protobuf.Empty + 67, // 123: grpc.Bridge.Version:output_type -> google.protobuf.StringValue + 67, // 124: grpc.Bridge.LogsPath:output_type -> google.protobuf.StringValue + 67, // 125: grpc.Bridge.LicensePath:output_type -> google.protobuf.StringValue + 67, // 126: grpc.Bridge.ReleaseNotesPageLink:output_type -> google.protobuf.StringValue + 67, // 127: grpc.Bridge.DependencyLicensesLink:output_type -> google.protobuf.StringValue + 67, // 128: grpc.Bridge.LandingPageLink:output_type -> google.protobuf.StringValue + 68, // 129: grpc.Bridge.SetColorSchemeName:output_type -> google.protobuf.Empty + 67, // 130: grpc.Bridge.ColorSchemeName:output_type -> google.protobuf.StringValue + 67, // 131: grpc.Bridge.CurrentEmailClient:output_type -> google.protobuf.StringValue + 68, // 132: grpc.Bridge.ReportBug:output_type -> google.protobuf.Empty + 68, // 133: grpc.Bridge.ExportTLSCertificates:output_type -> google.protobuf.Empty + 68, // 134: grpc.Bridge.ForceLauncher:output_type -> google.protobuf.Empty + 68, // 135: grpc.Bridge.SetMainExecutable:output_type -> google.protobuf.Empty + 68, // 136: grpc.Bridge.Login:output_type -> google.protobuf.Empty + 68, // 137: grpc.Bridge.Login2FA:output_type -> google.protobuf.Empty + 68, // 138: grpc.Bridge.Login2Passwords:output_type -> google.protobuf.Empty + 68, // 139: grpc.Bridge.LoginAbort:output_type -> google.protobuf.Empty + 68, // 140: grpc.Bridge.CheckUpdate:output_type -> google.protobuf.Empty + 68, // 141: grpc.Bridge.InstallUpdate:output_type -> google.protobuf.Empty + 68, // 142: grpc.Bridge.SetIsAutomaticUpdateOn:output_type -> google.protobuf.Empty + 69, // 143: grpc.Bridge.IsAutomaticUpdateOn:output_type -> google.protobuf.BoolValue + 67, // 144: grpc.Bridge.DiskCachePath:output_type -> google.protobuf.StringValue + 68, // 145: grpc.Bridge.SetDiskCachePath:output_type -> google.protobuf.Empty + 68, // 146: grpc.Bridge.SetIsDoHEnabled:output_type -> google.protobuf.Empty + 69, // 147: grpc.Bridge.IsDoHEnabled:output_type -> google.protobuf.BoolValue + 12, // 148: grpc.Bridge.MailServerSettings:output_type -> grpc.ImapSmtpSettings + 68, // 149: grpc.Bridge.SetMailServerSettings:output_type -> google.protobuf.Empty + 67, // 150: grpc.Bridge.Hostname:output_type -> google.protobuf.StringValue + 69, // 151: grpc.Bridge.IsPortFree:output_type -> google.protobuf.BoolValue + 13, // 152: grpc.Bridge.AvailableKeychains:output_type -> grpc.AvailableKeychainsResponse + 68, // 153: grpc.Bridge.SetCurrentKeychain:output_type -> google.protobuf.Empty + 67, // 154: grpc.Bridge.CurrentKeychain:output_type -> google.protobuf.StringValue + 16, // 155: grpc.Bridge.GetUserList:output_type -> grpc.UserListResponse + 14, // 156: grpc.Bridge.GetUser:output_type -> grpc.User + 68, // 157: grpc.Bridge.SetUserSplitMode:output_type -> google.protobuf.Empty + 68, // 158: grpc.Bridge.LogoutUser:output_type -> google.protobuf.Empty + 68, // 159: grpc.Bridge.RemoveUser:output_type -> google.protobuf.Empty + 68, // 160: grpc.Bridge.ConfigureUserAppleMail:output_type -> google.protobuf.Empty + 19, // 161: grpc.Bridge.RunEventStream:output_type -> grpc.StreamEvent + 68, // 162: grpc.Bridge.StopEventStream:output_type -> google.protobuf.Empty + 110, // [110:163] is the sub-list for method output_type + 57, // [57:110] is the sub-list for method input_type 57, // [57:57] is the sub-list for extension type_name 57, // [57:57] is the sub-list for extension extendee 0, // [0:57] is the sub-list for field type_name diff --git a/internal/frontend/grpc/bridge.proto b/internal/frontend/grpc/bridge.proto index 5d9aeba7..fc9b9b53 100644 --- a/internal/frontend/grpc/bridge.proto +++ b/internal/frontend/grpc/bridge.proto @@ -42,7 +42,6 @@ service Bridge { rpc IsBetaEnabled(google.protobuf.Empty) returns (google.protobuf.BoolValue); rpc SetIsAllMailVisible(google.protobuf.BoolValue) returns (google.protobuf.Empty); rpc IsAllMailVisible(google.protobuf.Empty) returns (google.protobuf.BoolValue); - rpc GoOs(google.protobuf.Empty) returns (google.protobuf.StringValue); rpc TriggerReset(google.protobuf.Empty) returns (google.protobuf.Empty); rpc Version(google.protobuf.Empty) returns (google.protobuf.StringValue); rpc LogsPath(google.protobuf.Empty) returns (google.protobuf.StringValue); diff --git a/internal/frontend/grpc/bridge_grpc.pb.go b/internal/frontend/grpc/bridge_grpc.pb.go index 84e3c73f..e2097ff5 100644 --- a/internal/frontend/grpc/bridge_grpc.pb.go +++ b/internal/frontend/grpc/bridge_grpc.pb.go @@ -37,7 +37,6 @@ type BridgeClient interface { IsBetaEnabled(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) SetIsAllMailVisible(ctx context.Context, in *wrapperspb.BoolValue, opts ...grpc.CallOption) (*emptypb.Empty, error) IsAllMailVisible(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) - GoOs(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) TriggerReset(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) Version(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) LogsPath(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) @@ -204,15 +203,6 @@ func (c *bridgeClient) IsAllMailVisible(ctx context.Context, in *emptypb.Empty, return out, nil } -func (c *bridgeClient) GoOs(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) { - out := new(wrapperspb.StringValue) - err := c.cc.Invoke(ctx, "/grpc.Bridge/GoOs", in, out, opts...) - if err != nil { - return nil, err - } - return out, nil -} - func (c *bridgeClient) TriggerReset(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) err := c.cc.Invoke(ctx, "/grpc.Bridge/TriggerReset", in, out, opts...) @@ -622,7 +612,6 @@ type BridgeServer interface { IsBetaEnabled(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) SetIsAllMailVisible(context.Context, *wrapperspb.BoolValue) (*emptypb.Empty, error) IsAllMailVisible(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) - GoOs(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) TriggerReset(context.Context, *emptypb.Empty) (*emptypb.Empty, error) Version(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) LogsPath(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) @@ -714,9 +703,6 @@ func (UnimplementedBridgeServer) SetIsAllMailVisible(context.Context, *wrappersp func (UnimplementedBridgeServer) IsAllMailVisible(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) { return nil, status.Errorf(codes.Unimplemented, "method IsAllMailVisible not implemented") } -func (UnimplementedBridgeServer) GoOs(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) { - return nil, status.Errorf(codes.Unimplemented, "method GoOs not implemented") -} func (UnimplementedBridgeServer) TriggerReset(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method TriggerReset not implemented") } @@ -1069,24 +1055,6 @@ func _Bridge_IsAllMailVisible_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } -func _Bridge_GoOs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(emptypb.Empty) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(BridgeServer).GoOs(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: "/grpc.Bridge/GoOs", - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(BridgeServer).GoOs(ctx, req.(*emptypb.Empty)) - } - return interceptor(ctx, in, info, handler) -} - func _Bridge_TriggerReset_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { @@ -1883,10 +1851,6 @@ var Bridge_ServiceDesc = grpc.ServiceDesc{ MethodName: "IsAllMailVisible", Handler: _Bridge_IsAllMailVisible_Handler, }, - { - MethodName: "GoOs", - Handler: _Bridge_GoOs_Handler, - }, { MethodName: "TriggerReset", Handler: _Bridge_TriggerReset_Handler, diff --git a/internal/frontend/grpc/service_methods.go b/internal/frontend/grpc/service_methods.go index 4ef13cee..874f35c2 100644 --- a/internal/frontend/grpc/service_methods.go +++ b/internal/frontend/grpc/service_methods.go @@ -211,12 +211,6 @@ func (s *Service) IsAllMailVisible(ctx context.Context, _ *emptypb.Empty) (*wrap return wrapperspb.Bool(s.bridge.GetShowAllMail()), nil } -func (s *Service) GoOs(ctx context.Context, _ *emptypb.Empty) (*wrapperspb.StringValue, error) { - s.log.Debug("GoOs") // TO-DO We can probably get rid of this and use QSysInfo::product name - - return wrapperspb.String(runtime.GOOS), nil -} - func (s *Service) TriggerReset(ctx context.Context, _ *emptypb.Empty) (*emptypb.Empty, error) { s.log.Debug("TriggerReset") diff --git a/pkg/bridgelib/bridgelib.go b/pkg/bridgelib/bridgelib.go new file mode 100644 index 00000000..754937ca --- /dev/null +++ b/pkg/bridgelib/bridgelib.go @@ -0,0 +1,108 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + +package main + +// bridgelib export bridge go code as a C library. [More info](https://pkg.go.dev/cmd/go#hdr-Build_modes). +// on Windows bridge-gui is built using the MSVC compiler with cannot link against mingw static library, +// As a consequence, the library should be built as a C shared library (.dll/.so/.dylib depending on the platform): +// +// macOS: go build -buildmode=c-shared -o bridgelib.dylib bridgelib.go +// Linux: go build -buildmode=c-shared -o bridgelib.so bridgelib.go +// Windows: go build -buildmode=c-shared -o bridgelib.dll bridgelib.go +// +// In addition to the library file, the header will export a C header file container the relevant type declarations. +// +// Requirements to export a go library +// +// - The package name must be main, and as a consequence, must contain a main() function. +// - The package must import "C" +// - Functions to be exported must be annotated with the cgo //export comment. +// +// Heap allocated data such as go string needs to be released. On macOS and linux, the caller of the library function can call free/delete, +// but it crashes on Windows because of the VC++/MinGW incompatibility. As a consequence, the caller is responsible for freeing the memory +// using the DeleteCString function. + +//#include +import "C" +import ( + "path/filepath" + "runtime" + "sync" + "unsafe" + + "github.com/ProtonMail/proton-bridge/v3/internal/constants" + "github.com/ProtonMail/proton-bridge/v3/internal/locations" +) + +// main is empty but required. +func main() { +} + +var locs *locations.DefaultProvider //nolint:gochecknoglobals +var locsMutex sync.Mutex //nolint:gochecknoglobals + +// GoOS returns the value of runtime.GOOS. +// +//export GoOS +func GoOS() *C.char { + return C.CString(runtime.GOOS) +} + +// UserCacheDir returns the path of the user's cache directory. +// +//export UserCacheDir +func UserCacheDir() *C.char { + return withLocationProvider(func(loc *locations.DefaultProvider) string { return loc.UserCache() }) +} + +// UserConfigDir returns the path of the user's config directory. +// +//export UserConfigDir +func UserConfigDir() *C.char { + return withLocationProvider(func(loc *locations.DefaultProvider) string { return loc.UserConfig() }) +} + +// UserDataDir returns the path of the user's data directory. +// +//export UserDataDir +func UserDataDir() *C.char { + return withLocationProvider(func(loc *locations.DefaultProvider) string { return loc.UserData() }) +} + +// DeleteCString deletes a C-style string allocated by one of the library calls. +// +//export DeleteCString +func DeleteCString(cStr *C.char) { + if cStr != nil { + C.free(unsafe.Pointer(cStr)) + } +} + +func withLocationProvider(fn func(provider *locations.DefaultProvider) string) *C.char { + locsMutex.Lock() + defer locsMutex.Unlock() + + if locs == nil { + var err error + if locs, err = locations.NewDefaultProvider(filepath.Join(constants.VendorName, constants.ConfigName)); err != nil { + return nil + } + } + + return C.CString(fn(locs)) +} From 0b796f4401ff092a76c73415591d5347a1055357 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Mon, 20 Feb 2023 12:59:47 +0100 Subject: [PATCH 063/130] feat(GODT-2373): bridgelib tests. --- pkg/bridgelib/bridgelib.go | 8 +++++++ pkg/bridgelib/bridgelib_test.go | 38 +++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 pkg/bridgelib/bridgelib_test.go diff --git a/pkg/bridgelib/bridgelib.go b/pkg/bridgelib/bridgelib.go index 754937ca..351b6db8 100644 --- a/pkg/bridgelib/bridgelib.go +++ b/pkg/bridgelib/bridgelib.go @@ -106,3 +106,11 @@ func withLocationProvider(fn func(provider *locations.DefaultProvider) string) * return C.CString(fn(locs)) } + +// cStringToGoString converts a cString to a GoString and release the memory for the C-String. This function is implemented +// here because cgo code is not allowed in Go test files. +func cStringToGoString(cStr *C.char) string { + str := C.GoString(cStr) + DeleteCString(cStr) // preferred over a direct call to C.free so that the former is covered in tests. + return str +} diff --git a/pkg/bridgelib/bridgelib_test.go b/pkg/bridgelib/bridgelib_test.go new file mode 100644 index 00000000..c233a835 --- /dev/null +++ b/pkg/bridgelib/bridgelib_test.go @@ -0,0 +1,38 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + +package main + +import ( + "path/filepath" + "runtime" + "testing" + + "github.com/ProtonMail/proton-bridge/v3/internal/constants" + "github.com/ProtonMail/proton-bridge/v3/internal/locations" + "github.com/stretchr/testify/require" +) + +func TestBridgelib(t *testing.T) { + locs, err := locations.NewDefaultProvider(filepath.Join(constants.VendorName, constants.ConfigName)) + require.NoError(t, err) + + require.Equal(t, cStringToGoString(GoOS()), runtime.GOOS) + require.Equal(t, cStringToGoString(UserCacheDir()), locs.UserCache()) + require.Equal(t, cStringToGoString(UserConfigDir()), locs.UserConfig()) + require.Equal(t, cStringToGoString(UserDataDir()), locs.UserData()) +} From 9dfdd07f7acc2ab0f7c028566c48345e9f319bf4 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Mon, 20 Feb 2023 15:35:56 +0100 Subject: [PATCH 064/130] fix(GODT-2381): Unset draft flag on sent messages --- go.mod | 2 +- go.sum | 4 +- internal/bridge/user_event_test.go | 100 +++++++++++++++++++++++++++++ internal/user/events.go | 1 + 4 files changed, 104 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 60a41da3..018fab24 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230217111735-c6aa35929f2e + github.com/ProtonMail/gluon v0.14.2-0.20230220142004-09ab7050bc08 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 8b1b5f23..b7c249e8 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230217111735-c6aa35929f2e h1:WWFhucLz1VeNLggqD/Jw14FwQ47TK8rgboSo+Ttu5qk= -github.com/ProtonMail/gluon v0.14.2-0.20230217111735-c6aa35929f2e/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230220142004-09ab7050bc08 h1:SSXME1MQg1In5zalVi6vxJKnnfYy92mwi6hhugDIxzA= +github.com/ProtonMail/gluon v0.14.2-0.20230220142004-09ab7050bc08/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/internal/bridge/user_event_test.go b/internal/bridge/user_event_test.go index 5b463a7a..87d5cfc2 100644 --- a/internal/bridge/user_event_test.go +++ b/internal/bridge/user_event_test.go @@ -31,6 +31,7 @@ import ( "github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" + "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/events" @@ -434,6 +435,105 @@ func TestBridge_User_UpdateDraftAndCreateOtherMessage(t *testing.T) { }) } +func TestBridge_User_SendDraftRemoveDraftFlag(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + // Create a bridge user. + _, _, err := s.CreateUser("user", password) + require.NoError(t, err) + + // Initially sync the user. + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + userLoginAndSync(ctx, t, bridge, "user", password) + }) + + withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { + user, err := c.GetUser(ctx) + require.NoError(t, err) + + addrs, err := c.GetAddresses(ctx) + require.NoError(t, err) + + salts, err := c.GetSalts(ctx) + require.NoError(t, err) + + keyPass, err := salts.SaltForKey(password, user.Keys.Primary().ID) + require.NoError(t, err) + + _, addrKRs, err := proton.Unlock(user, addrs, keyPass) + require.NoError(t, err) + + // Create a draft (generating a "create draft message" event). + draft, err := c.CreateDraft(ctx, addrKRs[addrs[0].ID], proton.CreateDraftReq{ + Message: proton.DraftTemplate{ + Subject: "subject", + ToList: []*mail.Address{{Address: addrs[0].Email}}, + Sender: &mail.Address{Name: "sender", Address: addrs[0].Email}, + Body: "body", + MIMEType: rfc822.TextPlain, + }, + }) + require.NoError(t, err) + + // Process those events + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + userContinueEventProcess(ctx, t, s, bridge) + + info, err := bridge.QueryUserInfo("user") + require.NoError(t, err) + + client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort())) + require.NoError(t, err) + require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) + defer func() { _ = client.Logout() }() + + messages, err := clientFetch(client, "Drafts") + require.NoError(t, err) + require.Len(t, messages, 1) + require.Contains(t, messages[0].Flags, imap.DraftFlag) + }) + + // Send the draft (generating an "update message" event). + { + pubKeys, recType, err := c.GetPublicKeys(ctx, addrs[0].Email) + require.NoError(t, err) + require.Equal(t, recType, proton.RecipientTypeInternal) + + var req proton.SendDraftReq + + require.NoError(t, req.AddTextPackage(addrKRs[addrs[0].ID], "body", rfc822.TextPlain, map[string]proton.SendPreferences{ + addrs[0].Email: { + Encrypt: true, + PubKey: must(crypto.NewKeyRing(must(crypto.NewKeyFromArmored(pubKeys[0].PublicKey)))), + SignatureType: proton.DetachedSignature, + EncryptionScheme: proton.InternalScheme, + MIMEType: rfc822.TextPlain, + }, + }, nil)) + + require.NoError(t, getErr(c.SendDraft(ctx, draft.ID, req))) + } + + // Process those events; the draft will move to the sent folder and lose the draft flag. + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + userContinueEventProcess(ctx, t, s, bridge) + + info, err := bridge.QueryUserInfo("user") + require.NoError(t, err) + + client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort())) + require.NoError(t, err) + require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) + defer func() { _ = client.Logout() }() + + messages, err := clientFetch(client, "Sent") + require.NoError(t, err) + require.Len(t, messages, 1) + require.NotContains(t, messages[0].Flags, imap.DraftFlag) + }) + }) + }) +} + // userLoginAndSync logs in user and waits until user is fully synced. func userLoginAndSync( ctx context.Context, diff --git a/internal/user/events.go b/internal/user/events.go index 37e80352..e36c25ab 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -570,6 +570,7 @@ func (user *User) handleUpdateMessageEvent(ctx context.Context, event proton.Mes mapTo[string, imap.MailboxID](wantLabels(user.apiLabels, event.Message.LabelIDs)), event.Message.Seen(), event.Message.Starred(), + event.Message.IsDraft(), ) user.updateCh[event.Message.AddressID].Enqueue(update) From 889f3286b5445a7a2db96b48cd05fff32e55f676 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 21 Feb 2023 12:15:37 +0100 Subject: [PATCH 065/130] chore: Bump gluon to use new address parser --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 018fab24..afc8b9d5 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230220142004-09ab7050bc08 + github.com/ProtonMail/gluon v0.14.2-0.20230221105731-a6bbc989768a github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index b7c249e8..7353de84 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230220142004-09ab7050bc08 h1:SSXME1MQg1In5zalVi6vxJKnnfYy92mwi6hhugDIxzA= -github.com/ProtonMail/gluon v0.14.2-0.20230220142004-09ab7050bc08/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230221105731-a6bbc989768a h1:fnDGQG/FPd6Gu9KtxYyj0iBuqH/0S685n/RZ+rYIkN8= +github.com/ProtonMail/gluon v0.14.2-0.20230221105731-a6bbc989768a/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= From 2bd8f6938a73e08109675b41b98afa1c41f806e8 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 21 Feb 2023 12:53:05 +0100 Subject: [PATCH 066/130] chore: Bump gluon to create missing messages during MessageUpdated --- go.mod | 2 +- go.sum | 4 ++-- internal/user/events.go | 16 +++++++++------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/go.mod b/go.mod index afc8b9d5..744a51ba 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230221105731-a6bbc989768a + github.com/ProtonMail/gluon v0.14.2-0.20230221114509-a4e1a32c42b9 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 7353de84..541a918b 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230221105731-a6bbc989768a h1:fnDGQG/FPd6Gu9KtxYyj0iBuqH/0S685n/RZ+rYIkN8= -github.com/ProtonMail/gluon v0.14.2-0.20230221105731-a6bbc989768a/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230221114509-a4e1a32c42b9 h1:QEkeqblKjA+pslf/1oj8+Uu348NZXTTURT8ski9+a5s= +github.com/ProtonMail/gluon v0.14.2-0.20230221114509-a4e1a32c42b9/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/internal/user/events.go b/internal/user/events.go index e36c25ab..55f1111e 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -504,11 +504,16 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto } func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.MessageEvent) ([]imap.Update, error) { + user.log.WithFields(logrus.Fields{ + "messageID": event.ID, + "subject": logging.Sensitive(event.Message.Subject), + }).Info("Handling message created event") + full, err := user.client.GetFullMessage(ctx, event.Message.ID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) if err != nil { // If the message is not found, it means that it has been deleted before we could fetch it. if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status == http.StatusUnprocessableEntity { - user.log.WithField("messageID", event.Message.ID).Warn("Cannot add new message: full message is missing on API") + user.log.WithField("messageID", event.Message.ID).Warn("Cannot create new message: full message is missing on API") return nil, nil } @@ -516,12 +521,8 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.Mes } return safe.RLockRetErr(func() ([]imap.Update, error) { - user.log.WithFields(logrus.Fields{ - "messageID": event.ID, - "subject": logging.Sensitive(event.Message.Subject), - }).Info("Handling message created event") - var update imap.Update + if err := withAddrKR(user.apiUser, user.apiAddrs[event.Message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error { res := buildRFC822(user.apiLabels, full, addrKR, new(bytes.Buffer)) @@ -606,7 +607,7 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event proton.Messa if err != nil { // If the message is not found, it means that it has been deleted before we could fetch it. if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status == http.StatusUnprocessableEntity { - user.log.WithField("messageID", event.Message.ID).Warn("Cannot add new draft: full message is missing on API") + user.log.WithField("messageID", event.Message.ID).Warn("Cannot update draft: full message is missing on API") return nil, nil } @@ -644,6 +645,7 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event proton.Messa res.update.Literal, res.update.MailboxIDs, res.update.ParsedMessage, + true, // Is the message doesn't exist, silently create it. ) user.updateCh[full.AddressID].Enqueue(update) From 038eb6d24345611594644c3962730c8ac8724545 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 21 Feb 2023 14:15:16 +0100 Subject: [PATCH 067/130] feat(GODT-2366): Handle failed message updates as creates MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This handles the following case: - event says message was created - we try to fetch the message but API says the doesn’t exist yet — we skip applying the “message created” update - event then says message was updated at some point in the future - we try to handle it but fail because we don’t have the message — we should treat it as a creation --- go.mod | 2 +- go.sum | 4 +-- internal/user/events.go | 56 ++++++++++++++++++++++++++--------------- 3 files changed, 39 insertions(+), 23 deletions(-) diff --git a/go.mod b/go.mod index 744a51ba..a647c141 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230221114509-a4e1a32c42b9 + github.com/ProtonMail/gluon v0.14.2-0.20230221141542-0259255ec9ff github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 541a918b..d7e93417 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230221114509-a4e1a32c42b9 h1:QEkeqblKjA+pslf/1oj8+Uu348NZXTTURT8ski9+a5s= -github.com/ProtonMail/gluon v0.14.2-0.20230221114509-a4e1a32c42b9/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230221141542-0259255ec9ff h1:uOaWgCaR+0XmwPTaSx9Cv5Z1lCto27bkuvNVur4A4I4= +github.com/ProtonMail/gluon v0.14.2-0.20230221141542-0259255ec9ff/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/internal/user/events.go b/internal/user/events.go index 55f1111e..b80180b2 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -24,6 +24,7 @@ import ( "fmt" "net/http" + "github.com/ProtonMail/gluon" "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/gluon/reporter" @@ -420,7 +421,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto switch event.Action { case proton.EventCreate: - updates, err := user.handleCreateMessageEvent(logging.WithLogrusField(ctx, "action", "create message"), event) + updates, err := user.handleCreateMessageEvent(logging.WithLogrusField(ctx, "action", "create message"), event.Message) if err != nil { if rerr := user.reporter.ReportMessageWithContext("Failed to apply create message event", reporter.Context{ "error": err, @@ -449,6 +450,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto }); rerr != nil { user.log.WithError(err).Error("Failed to report update draft message event error") } + return fmt.Errorf("failed to handle update draft event: %w", err) } @@ -465,7 +467,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto // Issue regular update to handle mailboxes and flag changes. updates, err := user.handleUpdateMessageEvent( logging.WithLogrusField(ctx, "action", "update message"), - event, + event.Message, ) if err != nil { if rerr := user.reporter.ReportMessageWithContext("Failed to apply update message event", reporter.Context{ @@ -473,10 +475,23 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto }); rerr != nil { user.log.WithError(err).Error("Failed to report update message event error") } + return fmt.Errorf("failed to handle update message event: %w", err) } - if err := waitOnIMAPUpdates(ctx, updates); err != nil { + // If the update fails on the gluon side because it doesn't exist, we try to create the message instead. + if err := waitOnIMAPUpdates(ctx, updates); gluon.IsNoSuchMessage(err) { + user.log.WithError(err).Error("Failed to handle update message event in gluon, will try creating it") + + updates, err := user.handleCreateMessageEvent(ctx, event.Message) + if err != nil { + return fmt.Errorf("failed to handle update message event as create: %w", err) + } + + if err := waitOnIMAPUpdates(ctx, updates); err != nil { + return err + } + } else if err != nil { return err } @@ -491,6 +506,7 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto }); rerr != nil { user.log.WithError(err).Error("Failed to report delete message event error") } + return fmt.Errorf("failed to handle delete message event: %w", err) } @@ -503,17 +519,17 @@ func (user *User) handleMessageEvents(ctx context.Context, messageEvents []proto return nil } -func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.MessageEvent) ([]imap.Update, error) { +func (user *User) handleCreateMessageEvent(ctx context.Context, message proton.MessageMetadata) ([]imap.Update, error) { user.log.WithFields(logrus.Fields{ - "messageID": event.ID, - "subject": logging.Sensitive(event.Message.Subject), + "messageID": message.ID, + "subject": logging.Sensitive(message.Subject), }).Info("Handling message created event") - full, err := user.client.GetFullMessage(ctx, event.Message.ID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) + full, err := user.client.GetFullMessage(ctx, message.ID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) if err != nil { // If the message is not found, it means that it has been deleted before we could fetch it. if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status == http.StatusUnprocessableEntity { - user.log.WithField("messageID", event.Message.ID).Warn("Cannot create new message: full message is missing on API") + user.log.WithField("messageID", message.ID).Warn("Cannot create new message: full message is missing on API") return nil, nil } @@ -523,13 +539,13 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.Mes return safe.RLockRetErr(func() ([]imap.Update, error) { var update imap.Update - if err := withAddrKR(user.apiUser, user.apiAddrs[event.Message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error { + if err := withAddrKR(user.apiUser, user.apiAddrs[message.AddressID], user.vault.KeyPass(), func(_, addrKR *crypto.KeyRing) error { res := buildRFC822(user.apiLabels, full, addrKR, new(bytes.Buffer)) if res.err != nil { user.log.WithError(err).Error("Failed to build RFC822 message") - if err := user.vault.AddFailedMessageID(event.ID); err != nil { + if err := user.vault.AddFailedMessageID(message.ID); err != nil { user.log.WithError(err).Error("Failed to add failed message ID to vault") } @@ -543,7 +559,7 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.Mes return nil } - if err := user.vault.RemFailedMessageID(event.ID); err != nil { + if err := user.vault.RemFailedMessageID(message.ID); err != nil { user.log.WithError(err).Error("Failed to remove failed message ID from vault") } @@ -559,22 +575,22 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, event proton.Mes }, user.apiUserLock, user.apiAddrsLock, user.apiLabelsLock, user.updateChLock) } -func (user *User) handleUpdateMessageEvent(ctx context.Context, event proton.MessageEvent) ([]imap.Update, error) { //nolint:unparam +func (user *User) handleUpdateMessageEvent(ctx context.Context, message proton.MessageMetadata) ([]imap.Update, error) { //nolint:unparam return safe.RLockRetErr(func() ([]imap.Update, error) { user.log.WithFields(logrus.Fields{ - "messageID": event.ID, - "subject": logging.Sensitive(event.Message.Subject), + "messageID": message.ID, + "subject": logging.Sensitive(message.Subject), }).Info("Handling message updated event") update := imap.NewMessageMailboxesUpdated( - imap.MessageID(event.ID), - mapTo[string, imap.MailboxID](wantLabels(user.apiLabels, event.Message.LabelIDs)), - event.Message.Seen(), - event.Message.Starred(), - event.Message.IsDraft(), + imap.MessageID(message.ID), + mapTo[string, imap.MailboxID](wantLabels(user.apiLabels, message.LabelIDs)), + message.Seen(), + message.Starred(), + message.IsDraft(), ) - user.updateCh[event.Message.AddressID].Enqueue(update) + user.updateCh[message.AddressID].Enqueue(update) return []imap.Update{update}, nil }, user.apiLabelsLock, user.updateChLock) From a75a72a2b9204734b87ba021bb3ef80b821058b8 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Tue, 21 Feb 2023 15:46:24 +0100 Subject: [PATCH 068/130] chore: Bump Gluon version for Go rfc5322 date parser --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index a647c141..29ae6d2b 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230221141542-0259255ec9ff + github.com/ProtonMail/gluon v0.14.2-0.20230221144046-c8f22fc170e9 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index d7e93417..e8648e7f 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230221141542-0259255ec9ff h1:uOaWgCaR+0XmwPTaSx9Cv5Z1lCto27bkuvNVur4A4I4= -github.com/ProtonMail/gluon v0.14.2-0.20230221141542-0259255ec9ff/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.14.2-0.20230221144046-c8f22fc170e9 h1:938+11VjjzuIJ0YJfS16ZMPvWe8msmCY6is0llEv6TM= +github.com/ProtonMail/gluon v0.14.2-0.20230221144046-c8f22fc170e9/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= From 4775fb4b22c70cf0ef10fd8a9cbafaa241040639 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Wed, 22 Feb 2023 09:07:21 +0100 Subject: [PATCH 069/130] fix(GODT-2201): Add missing rfc5322.CharsetReader initialization --- pkg/mime/encoding.go | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pkg/mime/encoding.go b/pkg/mime/encoding.go index 70b21518..8fa8edcf 100644 --- a/pkg/mime/encoding.go +++ b/pkg/mime/encoding.go @@ -25,6 +25,7 @@ import ( "strings" "unicode/utf8" + "github.com/ProtonMail/gluon/rfc5322" "github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/go-proton-api" "github.com/pkg/errors" @@ -37,6 +38,7 @@ import ( func init() { rfc822.ParseMediaType = ParseMediaType proton.CharsetReader = CharsetReader + rfc5322.CharsetReader = CharsetReader } func CharsetReader(charset string, input io.Reader) (io.Reader, error) { From 5007d451c2760a7a95b26a94c13de65fe0b66c8e Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Wed, 22 Feb 2023 11:55:03 +0100 Subject: [PATCH 070/130] feat(GODT-2385): Gluon cache fallback Update Gluon to have access to the cache fallback reader. Provide fallback reader to handle old cache file format. Remove the old logic to erase all cache files on start as the fallback option renders this irrelevant. --- go.mod | 2 +- go.sum | 4 ++-- internal/app/app.go | 12 ------------ internal/bridge/imap.go | 2 ++ 4 files changed, 5 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 29ae6d2b..e7c698ff 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.14.2-0.20230221144046-c8f22fc170e9 + github.com/ProtonMail/gluon v0.15.0 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index e8648e7f..83b3f40b 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.14.2-0.20230221144046-c8f22fc170e9 h1:938+11VjjzuIJ0YJfS16ZMPvWe8msmCY6is0llEv6TM= -github.com/ProtonMail/gluon v0.14.2-0.20230221144046-c8f22fc170e9/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.15.0 h1:Hai69s25OFrubR3rSNsLtErZn+jtknGnZ3ATzlog7Ds= +github.com/ProtonMail/gluon v0.15.0/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/internal/app/app.go b/internal/app/app.go index 4a30b0ab..36240e74 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -226,18 +226,6 @@ func run(c *cli.Context) error { _ = reporter.ReportMessageWithContext("Vault is corrupt", map[string]interface{}{}) } - // Force re-sync if last version <= 3.0.12 due to chances in the gluon cache format. - if lastVersion := v.GetLastVersion(); lastVersion != nil { - versionWithLZ4Cache := semver.MustParse("3.0.13") - if lastVersion.LessThan(versionWithLZ4Cache) { - if err := v.ForUser(1, func(user *vault.User) error { - return user.ClearSyncStatus() - }); err != nil { - logrus.WithError(err).Error("Failed to force resync on user") - } - } - } - if !v.Migrated() { // Migrate old settings into the vault. if err := migrateOldSettings(v); err != nil { diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index 37afae0b..d6efff44 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -31,6 +31,7 @@ import ( "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/gluon/store" + "github.com/ProtonMail/gluon/store/fallback_v0" "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/events" @@ -377,6 +378,7 @@ func (*storeBuilder) New(path, userID string, passphrase []byte) (store.Store, e return store.NewOnDiskStore( filepath.Join(path, userID), passphrase, + store.WithFallback(fallback_v0.NewOnDiskStoreV0WithCompressor(&fallback_v0.GZipCompressor{})), ) } From 89112baf96ce73b32b46bb17b6a5a259e0524056 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Tue, 21 Feb 2023 15:25:50 +0100 Subject: [PATCH 071/130] feat(GODT-2261): sync progress in GUI. --- .../bridge-gui-tester/CMakeLists.txt | 44 + .../bridge-gui-tester/GRPCServerWorker.cpp | 4 +- .../bridge-gui-tester/GRPCService.cpp | 11 - .../bridge-gui-tester/GRPCService.h | 1 - .../bridge-gui-tester/Tabs/SettingsTab.cpp | 3 +- .../bridge-gui-tester/Tabs/UsersTab.cpp | 53 + .../bridge-gui-tester/Tabs/UsersTab.h | 3 +- .../bridge-gui-tester/Tabs/UsersTab.ui | 50 +- .../bridge-gui/bridge-gui-tester/main.cpp | 8 +- .../bridge-gui/bridge-gui/CMakeLists.txt | 3 +- .../bridge-gui/{Log.cpp => LogUtils.cpp} | 4 +- .../bridge-gui/{Log.h => LogUtils.h} | 6 +- .../bridge-gui/bridge-gui/QMLBackend.cpp | 2 +- .../bridge-gui/bridge-gui/SentryUtils.cpp | 6 +- .../bridge-gui/bridge-gui/UserList.cpp | 47 + .../frontend/bridge-gui/bridge-gui/UserList.h | 5 +- .../frontend/bridge-gui/bridge-gui/main.cpp | 4 +- .../bridge-gui/qml/AccountDelegate.qml | 45 +- .../bridge-gui/qml/Proton/Style.qml | 2 +- .../bridge-gui/bridgepp/CMakeLists.txt | 1 + .../bridgepp}/BridgeLib.cpp | 0 .../bridgepp}/BridgeLib.h | 0 .../bridgepp/bridgepp/GRPC/EventFactory.cpp | 45 + .../bridgepp/bridgepp/GRPC/EventFactory.h | 3 + .../bridgepp/bridgepp/GRPC/GRPCClient.cpp | 22 + .../bridgepp/bridgepp/GRPC/GRPCClient.h | 3 + .../bridgepp/bridgepp/GRPC/bridge.pb.cc | 1234 +++++++++++++++-- .../bridgepp/bridgepp/GRPC/bridge.pb.h | 1022 +++++++++++++- .../bridgepp/bridgepp/User/User.cpp | 42 + .../bridge-gui/bridgepp/bridgepp/User/User.h | 10 + internal/frontend/grpc/bridge.pb.go | 1122 +++++++++------ internal/frontend/grpc/bridge.proto | 18 + internal/frontend/grpc/event_factory.go | 17 + internal/frontend/grpc/service.go | 9 + 34 files changed, 3243 insertions(+), 606 deletions(-) rename internal/frontend/bridge-gui/bridge-gui/{Log.cpp => LogUtils.cpp} (98%) rename internal/frontend/bridge-gui/bridge-gui/{Log.h => LogUtils.h} (90%) rename internal/frontend/bridge-gui/{bridge-gui => bridgepp/bridgepp}/BridgeLib.cpp (100%) rename internal/frontend/bridge-gui/{bridge-gui => bridgepp/bridgepp}/BridgeLib.h (100%) diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/CMakeLists.txt b/internal/frontend/bridge-gui/bridge-gui-tester/CMakeLists.txt index 812dcbc9..63cd2f94 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridge-gui-tester/CMakeLists.txt @@ -49,6 +49,48 @@ qt_standard_project_setup() message(STATUS "Using Qt ${Qt6_VERSION}") +#***************************************************************************************************************************************************** +# bridgelib +#***************************************************************************************************************************************************** +find_program(GO_BIN "go") +if (NOT GO_BIN) + message(FATAL_ERROR "Could not location go compiler") +endif() +message(STATUS "go compiler is ${GO_BIN}") + +if (APPLE) # set some env variable for go compiler on macOS. Note the CGO_ENABLED=1 is required when cross-compiling. + if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64") + set(GO_BIN "MACOSX_DEPLOYMENT_TARGET=11.0" "GOARCH=arm64" "CGO_CFLAGS=\"-mmacosx-version-min=11.0\"" CGO_ENABLED=1 ${GO_BIN}) + else () + set(GO_BIN "MACOSX_DEPLOYMENT_TARGET=10.15" "GOARCH=amd64" "CGO_CFLAGS=\"-mmacosx-version-min=10.15\"" CGO_ENABLED=1 ${GO_BIN}) + endif() +endif() + +file(REAL_PATH "pkg/bridgelib" BRIDGELIB_DIR BASE_DIRECTORY "${BRIDGE_REPO_ROOT}") +message(STATUS "bridgelib folder is ${BRIDGELIB_DIR}") + +set(BRIDGELIB_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) +set(BRIDGELIB_BASE_NAME "bridgelib") +if (UNIX AND NOT APPLE) + set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.so") +endif() +if (APPLE) + set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.dylib") +endif() +if (WIN32) + set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.dll") +endif() + +set(BRIDGELIB_OUTPUT_PATH "${BRIDGELIB_OUTPUT_DIR}/${BRIDGELIB_LIB_FILE}") + +add_custom_target( + bridgelib + COMMAND ${GO_BIN} build -o ${BRIDGELIB_OUTPUT_PATH} --buildmode c-shared + WORKING_DIRECTORY ${BRIDGELIB_DIR} + COMMENT "Compile bridgelib library" +) + + #***************************************************************************************************************************************************** # Source files and output #***************************************************************************************************************************************************** @@ -72,6 +114,8 @@ add_executable(bridge-gui-tester UserTable.cpp UserTable.h ) +add_dependencies(bridge-gui-tester bridgelib) + target_precompile_headers(bridge-gui-tester PRIVATE Pch.h) target_include_directories(bridge-gui-tester PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(bridge-gui-tester PRIVATE BRIDGE_APP_VERSION=\"${BRIDGE_APP_VERSION}\") diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/GRPCServerWorker.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/GRPCServerWorker.cpp index 94ca25d5..90045444 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/GRPCServerWorker.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/GRPCServerWorker.cpp @@ -19,6 +19,7 @@ #include "GRPCServerWorker.h" #include "Cert.h" #include "GRPCService.h" +#include #include #include #include @@ -33,7 +34,6 @@ using namespace grpc; //**************************************************************************************************************************************************** GRPCServerWorker::GRPCServerWorker(QObject *parent) : Worker(parent) { - } @@ -81,7 +81,7 @@ void GRPCServerWorker::run() { config.port = port; QString err; - if (!config.save(grpcServerConfigPath(), &err)) { + if (!config.save(grpcServerConfigPath(bridgelib::userConfigDir()), &err)) { throw Exception(QString("Could not save gRPC server config. %1").arg(err)); } diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/GRPCService.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/GRPCService.cpp index 36c7a0ef..70478cff 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/GRPCService.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/GRPCService.cpp @@ -192,17 +192,6 @@ Status GRPCService::IsAllMailVisible(ServerContext *, Empty const *request, Bool } -//**************************************************************************************************************************************************** -/// \param[out] response The response. -/// \return The status for the call. -//**************************************************************************************************************************************************** -Status GRPCService::GoOs(ServerContext *, Empty const *, StringValue *response) { - app().log().debug(__FUNCTION__); - response->set_value(app().mainWindow().settingsTab().os().toStdString()); - return Status::OK; -} - - //**************************************************************************************************************************************************** /// \return The status for the call. //**************************************************************************************************************************************************** diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/GRPCService.h b/internal/frontend/bridge-gui/bridge-gui-tester/GRPCService.h index 9c2a390c..a4b29b4c 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/GRPCService.h +++ b/internal/frontend/bridge-gui/bridge-gui-tester/GRPCService.h @@ -51,7 +51,6 @@ public: // member functions. grpc::Status IsBetaEnabled(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::BoolValue *response) override; grpc::Status SetIsAllMailVisible(::grpc::ServerContext *context, ::google::protobuf::BoolValue const *request, ::google::protobuf::Empty *response) override; grpc::Status IsAllMailVisible(::grpc::ServerContext *context, ::google::protobuf::Empty const *request, ::google::protobuf::BoolValue *response) override; - grpc::Status GoOs(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::StringValue *response) override; grpc::Status TriggerReset(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::Empty *) override; grpc::Status Version(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::StringValue *response) override; grpc::Status LogsPath(::grpc::ServerContext *, ::google::protobuf::Empty const *, ::google::protobuf::StringValue *response) override; diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/SettingsTab.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/SettingsTab.cpp index e22d1055..c7fe3fbd 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/SettingsTab.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/SettingsTab.cpp @@ -18,6 +18,7 @@ #include "SettingsTab.h" #include "GRPCService.h" +#include #include #include @@ -438,7 +439,7 @@ void SettingsTab::resetUI() { this->setClientPlatform("Unknown"); ui_.editVersion->setText(BRIDGE_APP_VERSION); - ui_.comboOS->setCurrentText(bridgepp::goos()); + ui_.comboOS->setCurrentText(bridgelib::goos()); ui_.editCurrentEmailClient->setText("Thunderbird/102.0.3"); ui_.checkShowOnStartup->setChecked(true); ui_.checkShowSplashScreen->setChecked(false); diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp index b0139f73..2b936e4e 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.cpp @@ -55,6 +55,8 @@ UsersTab::UsersTab(QWidget *parent) connect(ui_.buttonImapLoginFailed, &QPushButton::clicked, this, &UsersTab::onSendIMAPLoginFailedEvent); connect(ui_.buttonUsedBytesChanged, &QPushButton::clicked, this, &UsersTab::onSendUsedBytesChangedEvent); connect(ui_.checkUsernamePasswordError, &QCheckBox::toggled, this, &UsersTab::updateGUIState); + connect(ui_.checkSync, &QCheckBox::toggled, this, &UsersTab::onCheckSyncToggled); + connect(ui_.sliderSync, &QSlider::valueChanged, this, &UsersTab::onSliderSyncValueChanged); users_.append(randomUser()); @@ -217,9 +219,19 @@ void UsersTab::updateGUIState() { ui_.groupBoxUsedSpace->setEnabled(hasSelectedUser && (UserState::Connected == state)); ui_.editUsernamePasswordError->setEnabled(ui_.checkUsernamePasswordError->isChecked()); ui_.spinUsedBytes->setValue(user ? user->usedBytes() : 0.0); + ui_.groupboxSync->setEnabled(user.get()); if (user) ui_.editIMAPLoginFailedUsername->setText(user->primaryEmailOrUsername()); + + QSignalBlocker b(ui_.checkSync); + bool const syncing = user && user->isSyncing(); + ui_.checkSync->setChecked(syncing); + b = QSignalBlocker(ui_.sliderSync); + ui_.sliderSync->setEnabled(syncing); + qint32 const progressPercent = syncing ? qint32(user->syncProgress() * 100.0f) : 0; + ui_.sliderSync->setValue(progressPercent); + ui_.labelSync->setText(syncing ? QString("%1%").arg(progressPercent) : "" ); } @@ -398,3 +410,44 @@ void UsersTab::configureUserAppleMail(QString const &userID, QString const &addr app().log().info(QString("Apple mail configuration was requested for user %1, address %2").arg(userID, address)); } + + +//**************************************************************************************************************************************************** +/// \param[in] checked Is the sync checkbox checked? +//**************************************************************************************************************************************************** +void UsersTab::onCheckSyncToggled(bool checked) { + SPUser const user = this->selectedUser(); + if ((!user) || (user->isSyncing() == checked)) { + return; + } + + user->setIsSyncing(checked); + user->setSyncProgress(0.0); + GRPCService &grpc = app().grpc(); + + // we do not apply delay for these event. + if (checked) { + grpc.sendEvent(newSyncStartedEvent(user->id())); + grpc.sendEvent(newSyncProgressEvent(user->id(), 0.0, 1, 1)); + } else { + grpc.sendEvent(newSyncFinishedEvent(user->id())); + } + + this->updateGUIState(); +} + + +//**************************************************************************************************************************************************** +/// \param[in] value The value for the slider. +//**************************************************************************************************************************************************** +void UsersTab::onSliderSyncValueChanged(int value) { + SPUser const user = this->selectedUser(); + if ((!user) || (!user->isSyncing()) || user->syncProgress() == value) { + return; + } + + double const progress = value / 100.0; + user->setSyncProgress(progress); + app().grpc().sendEvent(newSyncProgressEvent(user->id(), progress, 1, 1)); // we do not simulate elapsed & remaining. + this->updateGUIState(); +} diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h index 868e094c..99fa01a1 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.h @@ -54,7 +54,6 @@ public slots: void logoutUser(QString const &userID); ///< slot for the logging out of a user. void removeUser(QString const &userID); ///< Slot for the removal of a user. void configureUserAppleMail(QString const &userID, QString const &address); ///< Slot for the configuration of Apple mail. - private slots: void onAddUserButton(); ///< Add a user to the user list. void onEditUserButton(); ///< Edit the currently selected user. @@ -63,6 +62,8 @@ private slots: void onSendUserBadEvent(); ///< Slot for the 'Send Bad Event Error' button. void onSendUsedBytesChangedEvent(); ///< Slot for the 'Send Used Bytes Changed Event' button. void onSendIMAPLoginFailedEvent(); ///< Slot for the 'Send IMAP Login failure Event' button. + void onCheckSyncToggled(bool checked); ///< Slot for the 'Synchronizing' check box. + void onSliderSyncValueChanged(int value); ///< Slot for the sync 'Progress' slider. void updateGUIState(); ///< Update the GUI state. private: // member functions. diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui index 36c8cec4..40dfbaaf 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/UsersTab.ui @@ -6,8 +6,8 @@ 0 0 - 1225 - 717 + 1221 + 894 @@ -66,6 +66,52 @@
+ + + + + 0 + 0 + + + + Sync + + + + + + + + Synchronizing + + + + + + + 0% + + + + + + + + + 100 + + + Qt::Horizontal + + + 10 + + + + + + diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp index 4011aa64..6b941491 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp @@ -19,6 +19,7 @@ #include "MainWindow.h" #include "AppController.h" #include "GRPCServerWorker.h" +#include #include #include @@ -54,6 +55,8 @@ int main(int argc, char **argv) { QApplication::setOrganizationDomain("proton.ch"); QApplication::setQuitOnLastWindowClosed(true); + bridgelib::loadLibrary(); + Log &log = app().log(); log.setEchoInConsole(true); log.setLevel(Log::Level::Debug); @@ -85,7 +88,10 @@ int main(int argc, char **argv) { return exitCode; } catch (Exception const &e) { - QTextStream(stderr) << QString("A fatal error occurred: %1\n").arg(e.qwhat()); + QString message = e.qwhat(); + if (!e.details().isEmpty()) + message += "\n\nDetails:\n" + e.details(); + QTextStream(stderr) << QString("A fatal error occurred: %1\n").arg(message); return EXIT_FAILURE; } } diff --git a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt index edff2992..3b7b8e9e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt @@ -152,10 +152,9 @@ add_executable(bridge-gui Resources.qrc AppController.cpp AppController.h BridgeApp.cpp BridgeApp.h - BridgeLib.cpp BridgeLib.h CommandLine.cpp CommandLine.h EventStreamWorker.cpp EventStreamWorker.h - Log.cpp Log.h + LogUtils.cpp LogUtils.h main.cpp Pch.h QMLBackend.cpp QMLBackend.h diff --git a/internal/frontend/bridge-gui/bridge-gui/Log.cpp b/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp similarity index 98% rename from internal/frontend/bridge-gui/bridge-gui/Log.cpp rename to internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp index 75e81d78..95be99a1 100644 --- a/internal/frontend/bridge-gui/bridge-gui/Log.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp @@ -16,9 +16,9 @@ // along with Proton Mail Bridge. If not, see . -#include "Log.h" -#include "BridgeLib.h" +#include "LogUtils.h" #include "BuildConfig.h" +#include using namespace bridgepp; diff --git a/internal/frontend/bridge-gui/bridge-gui/Log.h b/internal/frontend/bridge-gui/bridge-gui/LogUtils.h similarity index 90% rename from internal/frontend/bridge-gui/bridge-gui/Log.h rename to internal/frontend/bridge-gui/bridge-gui/LogUtils.h index bd20fd08..b324301e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/Log.h +++ b/internal/frontend/bridge-gui/bridge-gui/LogUtils.h @@ -16,8 +16,8 @@ // along with Proton Mail Bridge. If not, see . -#ifndef BRIDGE_GUI_LOG_H -#define BRIDGE_GUI_LOG_H +#ifndef BRIDGE_GUI_LOG_UTILS_H +#define BRIDGE_GUI_LOG_UTILS_H #include @@ -26,4 +26,4 @@ bridgepp::Log &initLog(); ///< Initialize the application log. -#endif //BRIDGE_GUI_LOG_H +#endif //BRIDGE_GUI_LOG_UTILS_H diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp index d50ac0b2..f11727ea 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp @@ -18,8 +18,8 @@ #include "QMLBackend.h" #include "BuildConfig.h" -#include "BridgeLib.h" #include "EventStreamWorker.h" +#include #include #include #include diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index 3e091514..c5924833 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -17,12 +17,8 @@ #include "SentryUtils.h" #include "BuildConfig.h" -#include "BridgeLib.h" +#include #include -#include -#include -#include -#include using namespace bridgepp; diff --git a/internal/frontend/bridge-gui/bridge-gui/UserList.cpp b/internal/frontend/bridge-gui/bridge-gui/UserList.cpp index 36d60e8e..059d0b1e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/UserList.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/UserList.cpp @@ -39,6 +39,9 @@ void UserList::connectGRPCEvents() const { connect(&client, &GRPCClient::userChanged, this, &UserList::onUserChanged); connect(&client, &GRPCClient::toggleSplitModeFinished, this, &UserList::onToggleSplitModeFinished); connect(&client, &GRPCClient::usedBytesChanged, this, &UserList::onUsedBytesChanged); + connect(&client, &GRPCClient::syncStarted, this, &UserList::onSyncStarted); + connect(&client, &GRPCClient::syncFinished, this, &UserList::onSyncFinished); + connect(&client, &GRPCClient::syncProgress, this, &UserList::onSyncProgress); } @@ -251,3 +254,47 @@ void UserList::onUsedBytesChanged(QString const &userID, qint64 usedBytes) { } users_[index]->setUsedBytes(usedBytes); } + + +//**************************************************************************************************************************************************** +/// \param[in] userID The userID. +//**************************************************************************************************************************************************** +void UserList::onSyncStarted(QString const &userID) { + int const index = this->rowOfUserID(userID); + if (index < 0) { + app().log().error(QString("Received onSyncStarted event for unknown userID %1").arg(userID)); + return; + } + users_[index]->setIsSyncing(true); +} + + +//**************************************************************************************************************************************************** +/// \param[in] userID The userID. +//**************************************************************************************************************************************************** +void UserList::onSyncFinished(QString const &userID) { + int const index = this->rowOfUserID(userID); + if (index < 0) { + app().log().error(QString("Received onSyncFinished event for unknown userID %1").arg(userID)); + return; + } + users_[index]->setIsSyncing(false); +} + + +//**************************************************************************************************************************************************** +/// \param[in] userID The userID. +/// \param[in] progress The sync progress ratio. +/// \param[in] elapsedMs The elapsed sync time in milliseconds. +/// \param[in] remainingMs The remaining sync time in milliseconds. +//**************************************************************************************************************************************************** +void UserList::onSyncProgress(QString const &userID, double progress, float elapsedMs, float remainingMs) { + Q_UNUSED(elapsedMs) + Q_UNUSED(remainingMs) + int const index = this->rowOfUserID(userID); + if (index < 0) { + app().log().error(QString("Received onSyncFinished event for unknown userID %1").arg(userID)); + return; + } + users_[index]->setSyncProgress(progress); +} diff --git a/internal/frontend/bridge-gui/bridge-gui/UserList.h b/internal/frontend/bridge-gui/bridge-gui/UserList.h index 7c308895..170b5c04 100644 --- a/internal/frontend/bridge-gui/bridge-gui/UserList.h +++ b/internal/frontend/bridge-gui/bridge-gui/UserList.h @@ -61,7 +61,10 @@ public slots: ///< handler for signals coming from the gRPC service void onUserChanged(QString const &userID); void onToggleSplitModeFinished(QString const &userID); void onUsedBytesChanged(QString const &userID, qint64 usedBytes); ///< Slot for usedBytesChanged events. - + void onSyncStarted(QString const &userID); ///< Slot for syncStarted events. + void onSyncFinished(QString const &userID); ///< Slot for syncFinished events. + void onSyncProgress(QString const &userID, double progress, float elapsedMs, float remainingMs); ///< Slot for syncFinished events. + private: // data members QList users_; ///< The user list. }; diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 9aa55d7e..90b1ebe2 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -18,12 +18,12 @@ #include "Pch.h" #include "BridgeApp.h" -#include "BridgeLib.h" #include "CommandLine.h" -#include "Log.h" +#include "LogUtils.h" #include "QMLBackend.h" #include "SentryUtils.h" #include "BuildConfig.h" +#include #include #include #include diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/AccountDelegate.qml b/internal/frontend/bridge-gui/bridge-gui/qml/AccountDelegate.qml index 9a5648e4..a0671e76 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/AccountDelegate.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/AccountDelegate.qml @@ -29,14 +29,19 @@ Item { property var _spacing: 12 * ProtonStyle.px - property color usedSpaceColor : { + property color progressColor : { if (!root.enabled) return root.colorScheme.text_weak if (root.type == AccountDelegate.SmallView) return root.colorScheme.text_weak - if (root.usedFraction < .50) return root.colorScheme.signal_success - if (root.usedFraction < .75) return root.colorScheme.signal_warning + if (root.user && root.user.isSyncing) return root.colorScheme.text_weak + if (root.progressRatio < .50) return root.colorScheme.signal_success + if (root.progressRatio < .75) return root.colorScheme.signal_warning return root.colorScheme.signal_danger } - property real usedFraction: root.user ? reasonableFraction(root.user.usedBytes, root.user.totalBytes) : 0 + property real progressRatio: { + if (!root.user) + return 0 + return root.user.isSyncing ? root.user.syncProgress : reasonableFraction(root.user.usedBytes, root.user.totalBytes) + } property string totalSpace: root.spaceWithUnits(root.user ? root.reasonableBytes(root.user.totalBytes) : 0) property string usedSpace: root.spaceWithUnits(root.user ? root.reasonableBytes(root.user.usedBytes) : 0) @@ -171,18 +176,21 @@ Item { case EUserState.Locked: return qsTr("Connecting") + dotsTimer.dots case EUserState.Connected: - return root.usedSpace + if (root.user.isSyncing) + return qsTr("Synchronizing (%1%)").arg(Math.floor(root.user.syncProgress * 100)) + dotsTimer.dots + else + return root.usedSpace } } - Timer { // dots animation while connecting. 1 sec cycle, roughly similar to the webmail loading page. + Timer { // dots animation while connecting & syncing. id:dotsTimer property string dots: "" - interval: 250; + interval: 500; repeat: true; - running: (root.user != null) && (root.user.state === EUserState.Locked) + running: (root.user != null) && ((root.user.state === EUserState.Locked) || (root.user.isSyncing)) onTriggered: { - dots = dots + "." + dots += "." if (dots.length > 3) dots = "" } @@ -191,7 +199,7 @@ Item { } } - color: root.usedSpaceColor + color: root.progressColor type: { switch (root.type) { case AccountDelegate.SmallView: return Label.Caption @@ -202,7 +210,7 @@ Item { Label { colorScheme: root.colorScheme - text: root.user && root.user.state == EUserState.Connected ? " / " + root.totalSpace : "" + text: root.user && root.user.state == EUserState.Connected && !root.user.isSyncing ? " / " + root.totalSpace : "" color: root.colorScheme.text_weak type: { switch (root.type) { @@ -213,26 +221,27 @@ Item { } } + Item { implicitHeight: root.type == AccountDelegate.LargeView ? 3 * ProtonStyle.px : 0 } Rectangle { - id: storage_bar + id: progress_bar visible: root.user ? root.type == AccountDelegate.LargeView : false width: 140 * ProtonStyle.px height: 4 * ProtonStyle.px - radius: ProtonStyle.storage_bar_radius + radius: ProtonStyle.progress_bar_radius color: root.colorScheme.border_weak Rectangle { - id: storage_bar_filled - radius: ProtonStyle.storage_bar_radius - color: root.usedSpaceColor - visible: root.user ? parent.visible && (root.user.state == EUserState.Connected) : false + id: progress_bar_filled + radius: ProtonStyle.progress_bar_radius + color: root.progressColor + visible: root.user ? parent.visible && (root.user.state == EUserState.Connected): false anchors { top : parent.top bottom : parent.bottom left : parent.left } - width: Math.min(1,Math.max(0.02,root.usedFraction)) * parent.width + width: Math.min(1,Math.max(0.02,root.progressRatio)) * parent.width } } } diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/Proton/Style.qml b/internal/frontend/bridge-gui/bridge-gui/qml/Proton/Style.qml index fe759194..4d542822 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/Proton/Style.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/Proton/Style.qml @@ -362,7 +362,7 @@ QtObject { property real banner_radius : 12 * root.px // px property real dialog_radius : 12 * root.px // px property real card_radius : 12 * root.px // px - property real storage_bar_radius : 3 * root.px // px + property real progress_bar_radius : 3 * root.px // px property real tooltip_radius : 8 * root.px // px property int heading_font_size: 28 diff --git a/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt b/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt index 3b3ed991..363c3bd2 100644 --- a/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt @@ -135,6 +135,7 @@ add_custom_command( add_library(bridgepp + bridgepp/BridgeLib.cpp bridgepp/BridgeLib.h bridgepp/BridgeUtils.cpp bridgepp/BridgeUtils.h bridgepp/Exception/Exception.h bridgepp/Exception/Exception.cpp bridgepp/GRPC/GRPCClient.cpp bridgepp/GRPC/GRPCClient.h diff --git a/internal/frontend/bridge-gui/bridge-gui/BridgeLib.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp similarity index 100% rename from internal/frontend/bridge-gui/bridge-gui/BridgeLib.cpp rename to internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp diff --git a/internal/frontend/bridge-gui/bridge-gui/BridgeLib.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.h similarity index 100% rename from internal/frontend/bridge-gui/bridge-gui/BridgeLib.h rename to internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.h diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp index 4259b4cd..7457e17e 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.cpp @@ -601,6 +601,51 @@ SPStreamEvent newIMAPLoginFailedEvent(QString const &username) { } +//**************************************************************************************************************************************************** +/// \param[in] userID The userID. +/// \return The event. +//**************************************************************************************************************************************************** +SPStreamEvent newSyncStartedEvent(QString const &userID) { + auto event = new grpc::SyncStartedEvent; + event->set_userid(userID.toStdString()); + auto userEvent = new grpc::UserEvent; + userEvent->set_allocated_syncstartedevent(event); + return wrapUserEvent(userEvent); +} + + +//**************************************************************************************************************************************************** +/// \param[in] userID The userID. +/// \return The event. +//**************************************************************************************************************************************************** +SPStreamEvent newSyncFinishedEvent(QString const &userID) { + auto event = new grpc::SyncFinishedEvent; + event->set_userid(userID.toStdString()); + auto userEvent = new grpc::UserEvent; + userEvent->set_allocated_syncfinishedevent(event); + return wrapUserEvent(userEvent); +} + + +//**************************************************************************************************************************************************** +/// \param[in] userID The userID. +/// \param[in] progress The progress ratio. +/// \param[in] elapsedMs The elapsed time in milliseconds. +/// \param[in] remainingMs The remaining time in milliseconds. +/// \return The event. +//**************************************************************************************************************************************************** +SPStreamEvent newSyncProgressEvent(QString const &userID, double progress, qint64 elapsedMs, qint64 remainingMs) { + auto event = new grpc::SyncProgressEvent; + event->set_userid(userID.toStdString()); + event->set_progress(progress); + event->set_elapsedms(elapsedMs); + event->set_remainingms(remainingMs); + auto userEvent = new grpc::UserEvent; + userEvent->set_allocated_syncprogressevent(event); + return wrapUserEvent(userEvent); +} + + //**************************************************************************************************************************************************** /// \param[in] errorCode The error errorCode. /// \return The event. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h index 76569b2e..44a6deae 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/EventFactory.h @@ -80,6 +80,9 @@ SPStreamEvent newUserChangedEvent(QString const &userID); ///< Create a new User SPStreamEvent newUserBadEvent(QString const &userID, QString const& errorMessage); ///< Create a new UserBadEvent event. SPStreamEvent newUsedBytesChangedEvent(QString const &userID, qint64 usedBytes); ///< Create a new UsedBytesChangedEvent event. SPStreamEvent newIMAPLoginFailedEvent(QString const &username); ///< Create a new ImapLoginFailedEvent event. +SPStreamEvent newSyncStartedEvent(QString const &userID); ///< Create a new SyncStarted event. +SPStreamEvent newSyncFinishedEvent(QString const &userID); ///< Create a new SyncFinished event. +SPStreamEvent newSyncProgressEvent(QString const &userID, double progress, qint64 elapsedMs, qint64 remainingMs); ///< Create a new SyncFinished event. // Generic error event SPStreamEvent newGenericErrorEvent(grpc::ErrorCode errorCode); ///< Create a new GenericErrrorEvent event. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp index a3c1b9c9..8e361031 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp @@ -1380,6 +1380,28 @@ void GRPCClient::processUserEvent(UserEvent const &event) { emit imapLoginFailed(username); break; } + case UserEvent::kSyncStartedEvent: { + SyncStartedEvent const &e = event.syncstartedevent(); + QString const &userID = QString::fromStdString(e.userid()); + this->logTrace(QString("User event received: SyncStarted (userID = %1).:").arg(userID)); + emit syncStarted(userID); + break; + } + case UserEvent::kSyncFinishedEvent: { + SyncFinishedEvent const &e = event.syncfinishedevent(); + QString const &userID = QString::fromStdString(e.userid()); + this->logTrace(QString("User event received: SyncFinished (userID = %1).:").arg(userID)); + emit syncFinished(userID); + break; + } + case UserEvent::kSyncProgressEvent: { + SyncProgressEvent const &e = event.syncprogressevent(); + QString const &userID = QString::fromStdString(e.userid()); + this->logTrace(QString("User event received SyncProgress (userID = %1, progress = %2, elapsedMs = %3, remainingMs = %4).").arg(userID) + .arg(e.progress()).arg(e.elapsedms()).arg(e.remainingms())); + emit syncProgress(userID, e.progress(), e.elapsedms(), e.remainingms()); + break; + } default: this->logError("Unknown User event received."); } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h index 3bc16973..9bae4e14 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h @@ -181,6 +181,9 @@ signals: void userBadEvent(QString const &userID, QString const& errorMessage); void usedBytesChanged(QString const &userID, qint64 usedBytes); void imapLoginFailed(QString const& username); + void syncStarted(QString const &userID); + void syncFinished(QString const &userID); + void syncProgress(QString const &userID, double progress, qint64 elapsedMs, qint64 remainingMs); public: // keychain related calls grpc::Status availableKeychains(QStringList &outKeychains); diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc index 65a5edf0..d658ed53 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc @@ -786,6 +786,48 @@ struct ImapLoginFailedEventDefaultTypeInternal { }; }; PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ImapLoginFailedEventDefaultTypeInternal _ImapLoginFailedEvent_default_instance_; +PROTOBUF_CONSTEXPR SyncStartedEvent::SyncStartedEvent( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.userid_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct SyncStartedEventDefaultTypeInternal { + PROTOBUF_CONSTEXPR SyncStartedEventDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~SyncStartedEventDefaultTypeInternal() {} + union { + SyncStartedEvent _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SyncStartedEventDefaultTypeInternal _SyncStartedEvent_default_instance_; +PROTOBUF_CONSTEXPR SyncFinishedEvent::SyncFinishedEvent( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.userid_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct SyncFinishedEventDefaultTypeInternal { + PROTOBUF_CONSTEXPR SyncFinishedEventDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~SyncFinishedEventDefaultTypeInternal() {} + union { + SyncFinishedEvent _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SyncFinishedEventDefaultTypeInternal _SyncFinishedEvent_default_instance_; +PROTOBUF_CONSTEXPR SyncProgressEvent::SyncProgressEvent( + ::_pbi::ConstantInitialized): _impl_{ + /*decltype(_impl_.userid_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}} + , /*decltype(_impl_.progress_)*/0 + , /*decltype(_impl_.elapsedms_)*/int64_t{0} + , /*decltype(_impl_.remainingms_)*/int64_t{0} + , /*decltype(_impl_._cached_size_)*/{}} {} +struct SyncProgressEventDefaultTypeInternal { + PROTOBUF_CONSTEXPR SyncProgressEventDefaultTypeInternal() + : _instance(::_pbi::ConstantInitialized{}) {} + ~SyncProgressEventDefaultTypeInternal() {} + union { + SyncProgressEvent _instance; + }; +}; +PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SyncProgressEventDefaultTypeInternal _SyncProgressEvent_default_instance_; PROTOBUF_CONSTEXPR GenericErrorEvent::GenericErrorEvent( ::_pbi::ConstantInitialized): _impl_{ /*decltype(_impl_.code_)*/0 @@ -800,7 +842,7 @@ struct GenericErrorEventDefaultTypeInternal { }; PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GenericErrorEventDefaultTypeInternal _GenericErrorEvent_default_instance_; } // namespace grpc -static ::_pb::Metadata file_level_metadata_bridge_2eproto[60]; +static ::_pb::Metadata file_level_metadata_bridge_2eproto[63]; static const ::_pb::EnumDescriptor* file_level_enum_descriptors_bridge_2eproto[7]; static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_bridge_2eproto = nullptr; @@ -1228,6 +1270,9 @@ const uint32_t TableStruct_bridge_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(p ::_pbi::kInvalidFieldOffsetTag, ::_pbi::kInvalidFieldOffsetTag, ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, + ::_pbi::kInvalidFieldOffsetTag, PROTOBUF_FIELD_OFFSET(::grpc::UserEvent, _impl_.event_), ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::grpc::ToggleSplitModeFinishedEvent, _internal_metadata_), @@ -1274,6 +1319,30 @@ const uint32_t TableStruct_bridge_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(p ~0u, // no _inlined_string_donated_ PROTOBUF_FIELD_OFFSET(::grpc::ImapLoginFailedEvent, _impl_.username_), ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::grpc::SyncStartedEvent, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::grpc::SyncStartedEvent, _impl_.userid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::grpc::SyncFinishedEvent, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::grpc::SyncFinishedEvent, _impl_.userid_), + ~0u, // no _has_bits_ + PROTOBUF_FIELD_OFFSET(::grpc::SyncProgressEvent, _internal_metadata_), + ~0u, // no _extensions_ + ~0u, // no _oneof_case_ + ~0u, // no _weak_field_map_ + ~0u, // no _inlined_string_donated_ + PROTOBUF_FIELD_OFFSET(::grpc::SyncProgressEvent, _impl_.userid_), + PROTOBUF_FIELD_OFFSET(::grpc::SyncProgressEvent, _impl_.progress_), + PROTOBUF_FIELD_OFFSET(::grpc::SyncProgressEvent, _impl_.elapsedms_), + PROTOBUF_FIELD_OFFSET(::grpc::SyncProgressEvent, _impl_.remainingms_), + ~0u, // no _has_bits_ PROTOBUF_FIELD_OFFSET(::grpc::GenericErrorEvent, _internal_metadata_), ~0u, // no _extensions_ ~0u, // no _oneof_case_ @@ -1335,13 +1404,16 @@ static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protode { 398, -1, -1, sizeof(::grpc::AddressChangedLogoutEvent)}, { 405, -1, -1, sizeof(::grpc::ApiCertIssueEvent)}, { 411, -1, -1, sizeof(::grpc::UserEvent)}, - { 424, -1, -1, sizeof(::grpc::ToggleSplitModeFinishedEvent)}, - { 431, -1, -1, sizeof(::grpc::UserDisconnectedEvent)}, - { 438, -1, -1, sizeof(::grpc::UserChangedEvent)}, - { 445, -1, -1, sizeof(::grpc::UserBadEvent)}, - { 453, -1, -1, sizeof(::grpc::UsedBytesChangedEvent)}, - { 461, -1, -1, sizeof(::grpc::ImapLoginFailedEvent)}, - { 468, -1, -1, sizeof(::grpc::GenericErrorEvent)}, + { 427, -1, -1, sizeof(::grpc::ToggleSplitModeFinishedEvent)}, + { 434, -1, -1, sizeof(::grpc::UserDisconnectedEvent)}, + { 441, -1, -1, sizeof(::grpc::UserChangedEvent)}, + { 448, -1, -1, sizeof(::grpc::UserBadEvent)}, + { 456, -1, -1, sizeof(::grpc::UsedBytesChangedEvent)}, + { 464, -1, -1, sizeof(::grpc::ImapLoginFailedEvent)}, + { 471, -1, -1, sizeof(::grpc::SyncStartedEvent)}, + { 478, -1, -1, sizeof(::grpc::SyncFinishedEvent)}, + { 485, -1, -1, sizeof(::grpc::SyncProgressEvent)}, + { 495, -1, -1, sizeof(::grpc::GenericErrorEvent)}, }; static const ::_pb::Message* const file_default_instances[] = { @@ -1404,6 +1476,9 @@ static const ::_pb::Message* const file_default_instances[] = { &::grpc::_UserBadEvent_default_instance_._instance, &::grpc::_UsedBytesChangedEvent_default_instance_._instance, &::grpc::_ImapLoginFailedEvent_default_instance_._instance, + &::grpc::_SyncStartedEvent_default_instance_._instance, + &::grpc::_SyncFinishedEvent_default_instance_._instance, + &::grpc::_SyncProgressEvent_default_instance_._instance, &::grpc::_GenericErrorEvent_default_instance_._instance, }; @@ -1525,7 +1600,7 @@ const char descriptor_table_protodef_bridge_2eproto[] PROTOBUF_SECTION_VARIABLE( "KeyForRecipientEvent\022\r\n\005email\030\001 \001(\t\"&\n\023A" "ddressChangedEvent\022\017\n\007address\030\001 \001(\t\",\n\031A" "ddressChangedLogoutEvent\022\017\n\007address\030\001 \001(" - "\t\"\023\n\021ApiCertIssueEvent\"\351\002\n\tUserEvent\022E\n\027" + "\t\"\023\n\021ApiCertIssueEvent\"\211\004\n\tUserEvent\022E\n\027" "toggleSplitModeFinished\030\001 \001(\0132\".grpc.Tog" "gleSplitModeFinishedEventH\000\0227\n\020userDisco" "nnected\030\002 \001(\0132\033.grpc.UserDisconnectedEve" @@ -1534,130 +1609,138 @@ const char descriptor_table_protodef_bridge_2eproto[] PROTOBUF_SECTION_VARIABLE( ".UserBadEventH\000\022<\n\025usedBytesChangedEvent" "\030\005 \001(\0132\033.grpc.UsedBytesChangedEventH\000\022:\n" "\024imapLoginFailedEvent\030\006 \001(\0132\032.grpc.ImapL" - "oginFailedEventH\000B\007\n\005event\".\n\034ToggleSpli" + "oginFailedEventH\000\0222\n\020syncStartedEvent\030\007 " + "\001(\0132\026.grpc.SyncStartedEventH\000\0224\n\021syncFin" + "ishedEvent\030\010 \001(\0132\027.grpc.SyncFinishedEven" + "tH\000\0224\n\021syncProgressEvent\030\t \001(\0132\027.grpc.Sy" + "ncProgressEventH\000B\007\n\005event\".\n\034ToggleSpli" "tModeFinishedEvent\022\016\n\006userID\030\001 \001(\t\")\n\025Us" "erDisconnectedEvent\022\020\n\010username\030\001 \001(\t\"\"\n" "\020UserChangedEvent\022\016\n\006userID\030\001 \001(\t\"4\n\014Use" "rBadEvent\022\016\n\006userID\030\001 \001(\t\022\024\n\014errorMessag" "e\030\002 \001(\t\":\n\025UsedBytesChangedEvent\022\016\n\006user" "ID\030\001 \001(\t\022\021\n\tusedBytes\030\002 \001(\003\"(\n\024ImapLogin" - "FailedEvent\022\020\n\010username\030\001 \001(\t\"2\n\021Generic" - "ErrorEvent\022\035\n\004code\030\001 \001(\0162\017.grpc.ErrorCod" - "e*q\n\010LogLevel\022\r\n\tLOG_PANIC\020\000\022\r\n\tLOG_FATA" - "L\020\001\022\r\n\tLOG_ERROR\020\002\022\014\n\010LOG_WARN\020\003\022\014\n\010LOG_" - "INFO\020\004\022\r\n\tLOG_DEBUG\020\005\022\r\n\tLOG_TRACE\020\006*6\n\t" - "UserState\022\016\n\nSIGNED_OUT\020\000\022\n\n\006LOCKED\020\001\022\r\n" - "\tCONNECTED\020\002*\242\001\n\016LoginErrorType\022\033\n\027USERN" - "AME_PASSWORD_ERROR\020\000\022\r\n\tFREE_USER\020\001\022\024\n\020C" - "ONNECTION_ERROR\020\002\022\r\n\tTFA_ERROR\020\003\022\r\n\tTFA_" - "ABORT\020\004\022\027\n\023TWO_PASSWORDS_ERROR\020\005\022\027\n\023TWO_" - "PASSWORDS_ABORT\020\006*[\n\017UpdateErrorType\022\027\n\023" - "UPDATE_MANUAL_ERROR\020\000\022\026\n\022UPDATE_FORCE_ER" - "ROR\020\001\022\027\n\023UPDATE_SILENT_ERROR\020\002*k\n\022DiskCa" - "cheErrorType\022 \n\034DISK_CACHE_UNAVAILABLE_E" - "RROR\020\000\022\036\n\032CANT_MOVE_DISK_CACHE_ERROR\020\001\022\023" - "\n\017DISK_FULL_ERROR\020\002*\335\001\n\033MailServerSettin" - "gsErrorType\022\033\n\027IMAP_PORT_STARTUP_ERROR\020\000" - "\022\033\n\027SMTP_PORT_STARTUP_ERROR\020\001\022\032\n\026IMAP_PO" - "RT_CHANGE_ERROR\020\002\022\032\n\026SMTP_PORT_CHANGE_ER" - "ROR\020\003\022%\n!IMAP_CONNECTION_MODE_CHANGE_ERR" - "OR\020\004\022%\n!SMTP_CONNECTION_MODE_CHANGE_ERRO" - "R\020\005*S\n\tErrorCode\022\021\n\rUNKNOWN_ERROR\020\000\022\031\n\025T" - "LS_CERT_EXPORT_ERROR\020\001\022\030\n\024TLS_KEY_EXPORT" - "_ERROR\020\0022\333\034\n\006Bridge\022I\n\013CheckTokens\022\034.goo" - "gle.protobuf.StringValue\032\034.google.protob" - "uf.StringValue\022\?\n\013AddLogEntry\022\030.grpc.Add" - "LogEntryRequest\032\026.google.protobuf.Empty\022" - ":\n\010GuiReady\022\026.google.protobuf.Empty\032\026.gr" - "pc.GuiReadyResponse\0226\n\004Quit\022\026.google.pro" - "tobuf.Empty\032\026.google.protobuf.Empty\0229\n\007R" - "estart\022\026.google.protobuf.Empty\032\026.google." - "protobuf.Empty\022C\n\rShowOnStartup\022\026.google" - ".protobuf.Empty\032\032.google.protobuf.BoolVa" - "lue\022F\n\020SetIsAutostartOn\022\032.google.protobu" - "f.BoolValue\032\026.google.protobuf.Empty\022C\n\rI" - "sAutostartOn\022\026.google.protobuf.Empty\032\032.g" - "oogle.protobuf.BoolValue\022F\n\020SetIsBetaEna" - "bled\022\032.google.protobuf.BoolValue\032\026.googl" - "e.protobuf.Empty\022C\n\rIsBetaEnabled\022\026.goog" - "le.protobuf.Empty\032\032.google.protobuf.Bool" - "Value\022I\n\023SetIsAllMailVisible\022\032.google.pr" - "otobuf.BoolValue\032\026.google.protobuf.Empty" - "\022F\n\020IsAllMailVisible\022\026.google.protobuf.E" - "mpty\032\032.google.protobuf.BoolValue\022>\n\014Trig" - "gerReset\022\026.google.protobuf.Empty\032\026.googl" - "e.protobuf.Empty\022\?\n\007Version\022\026.google.pro" - "tobuf.Empty\032\034.google.protobuf.StringValu" - "e\022@\n\010LogsPath\022\026.google.protobuf.Empty\032\034." - "google.protobuf.StringValue\022C\n\013LicensePa" - "th\022\026.google.protobuf.Empty\032\034.google.prot" - "obuf.StringValue\022L\n\024ReleaseNotesPageLink" - "\022\026.google.protobuf.Empty\032\034.google.protob" - "uf.StringValue\022N\n\026DependencyLicensesLink" - "\022\026.google.protobuf.Empty\032\034.google.protob" - "uf.StringValue\022G\n\017LandingPageLink\022\026.goog" - "le.protobuf.Empty\032\034.google.protobuf.Stri" - "ngValue\022J\n\022SetColorSchemeName\022\034.google.p" - "rotobuf.StringValue\032\026.google.protobuf.Em" - "pty\022G\n\017ColorSchemeName\022\026.google.protobuf" - ".Empty\032\034.google.protobuf.StringValue\022J\n\022" - "CurrentEmailClient\022\026.google.protobuf.Emp" - "ty\032\034.google.protobuf.StringValue\022;\n\tRepo" - "rtBug\022\026.grpc.ReportBugRequest\032\026.google.p" - "rotobuf.Empty\022M\n\025ExportTLSCertificates\022\034" - ".google.protobuf.StringValue\032\026.google.pr" - "otobuf.Empty\022E\n\rForceLauncher\022\034.google.p" - "rotobuf.StringValue\032\026.google.protobuf.Em" - "pty\022I\n\021SetMainExecutable\022\034.google.protob" - "uf.StringValue\032\026.google.protobuf.Empty\0223" - "\n\005Login\022\022.grpc.LoginRequest\032\026.google.pro" - "tobuf.Empty\0226\n\010Login2FA\022\022.grpc.LoginRequ" - "est\032\026.google.protobuf.Empty\022=\n\017Login2Pas" - "swords\022\022.grpc.LoginRequest\032\026.google.prot" - "obuf.Empty\022=\n\nLoginAbort\022\027.grpc.LoginAbo" - "rtRequest\032\026.google.protobuf.Empty\022=\n\013Che" - "ckUpdate\022\026.google.protobuf.Empty\032\026.googl" - "e.protobuf.Empty\022\?\n\rInstallUpdate\022\026.goog" - "le.protobuf.Empty\032\026.google.protobuf.Empt" - "y\022L\n\026SetIsAutomaticUpdateOn\022\032.google.pro" - "tobuf.BoolValue\032\026.google.protobuf.Empty\022" - "I\n\023IsAutomaticUpdateOn\022\026.google.protobuf" - ".Empty\032\032.google.protobuf.BoolValue\022E\n\rDi" - "skCachePath\022\026.google.protobuf.Empty\032\034.go" - "ogle.protobuf.StringValue\022H\n\020SetDiskCach" - "ePath\022\034.google.protobuf.StringValue\032\026.go" - "ogle.protobuf.Empty\022E\n\017SetIsDoHEnabled\022\032" - ".google.protobuf.BoolValue\032\026.google.prot" - "obuf.Empty\022B\n\014IsDoHEnabled\022\026.google.prot" - "obuf.Empty\032\032.google.protobuf.BoolValue\022D" - "\n\022MailServerSettings\022\026.google.protobuf.E" - "mpty\032\026.grpc.ImapSmtpSettings\022G\n\025SetMailS" - "erverSettings\022\026.grpc.ImapSmtpSettings\032\026." - "google.protobuf.Empty\022@\n\010Hostname\022\026.goog" - "le.protobuf.Empty\032\034.google.protobuf.Stri" - "ngValue\022E\n\nIsPortFree\022\033.google.protobuf." - "Int32Value\032\032.google.protobuf.BoolValue\022N" - "\n\022AvailableKeychains\022\026.google.protobuf.E" - "mpty\032 .grpc.AvailableKeychainsResponse\022J" - "\n\022SetCurrentKeychain\022\034.google.protobuf.S" - "tringValue\032\026.google.protobuf.Empty\022G\n\017Cu" - "rrentKeychain\022\026.google.protobuf.Empty\032\034." - "google.protobuf.StringValue\022=\n\013GetUserLi" - "st\022\026.google.protobuf.Empty\032\026.grpc.UserLi" - "stResponse\0223\n\007GetUser\022\034.google.protobuf." - "StringValue\032\n.grpc.User\022F\n\020SetUserSplitM" - "ode\022\032.grpc.UserSplitModeRequest\032\026.google" - ".protobuf.Empty\022B\n\nLogoutUser\022\034.google.p" - "rotobuf.StringValue\032\026.google.protobuf.Em" - "pty\022B\n\nRemoveUser\022\034.google.protobuf.Stri" - "ngValue\032\026.google.protobuf.Empty\022Q\n\026Confi" - "gureUserAppleMail\022\037.grpc.ConfigureAppleM" - "ailRequest\032\026.google.protobuf.Empty\022\?\n\016Ru" - "nEventStream\022\030.grpc.EventStreamRequest\032\021" - ".grpc.StreamEvent0\001\022A\n\017StopEventStream\022\026" - ".google.protobuf.Empty\032\026.google.protobuf" - ".EmptyB6Z4github.com/ProtonMail/proton-b" - "ridge/v3/internal/grpcb\006proto3" + "FailedEvent\022\020\n\010username\030\001 \001(\t\"\"\n\020SyncSta" + "rtedEvent\022\016\n\006userID\030\001 \001(\t\"#\n\021SyncFinishe" + "dEvent\022\016\n\006userID\030\001 \001(\t\"]\n\021SyncProgressEv" + "ent\022\016\n\006userID\030\001 \001(\t\022\020\n\010progress\030\002 \001(\001\022\021\n" + "\telapsedMs\030\003 \001(\003\022\023\n\013remainingMs\030\004 \001(\003\"2\n" + "\021GenericErrorEvent\022\035\n\004code\030\001 \001(\0162\017.grpc." + "ErrorCode*q\n\010LogLevel\022\r\n\tLOG_PANIC\020\000\022\r\n\t" + "LOG_FATAL\020\001\022\r\n\tLOG_ERROR\020\002\022\014\n\010LOG_WARN\020\003" + "\022\014\n\010LOG_INFO\020\004\022\r\n\tLOG_DEBUG\020\005\022\r\n\tLOG_TRA" + "CE\020\006*6\n\tUserState\022\016\n\nSIGNED_OUT\020\000\022\n\n\006LOC" + "KED\020\001\022\r\n\tCONNECTED\020\002*\242\001\n\016LoginErrorType\022" + "\033\n\027USERNAME_PASSWORD_ERROR\020\000\022\r\n\tFREE_USE" + "R\020\001\022\024\n\020CONNECTION_ERROR\020\002\022\r\n\tTFA_ERROR\020\003" + "\022\r\n\tTFA_ABORT\020\004\022\027\n\023TWO_PASSWORDS_ERROR\020\005" + "\022\027\n\023TWO_PASSWORDS_ABORT\020\006*[\n\017UpdateError" + "Type\022\027\n\023UPDATE_MANUAL_ERROR\020\000\022\026\n\022UPDATE_" + "FORCE_ERROR\020\001\022\027\n\023UPDATE_SILENT_ERROR\020\002*k" + "\n\022DiskCacheErrorType\022 \n\034DISK_CACHE_UNAVA" + "ILABLE_ERROR\020\000\022\036\n\032CANT_MOVE_DISK_CACHE_E" + "RROR\020\001\022\023\n\017DISK_FULL_ERROR\020\002*\335\001\n\033MailServ" + "erSettingsErrorType\022\033\n\027IMAP_PORT_STARTUP" + "_ERROR\020\000\022\033\n\027SMTP_PORT_STARTUP_ERROR\020\001\022\032\n" + "\026IMAP_PORT_CHANGE_ERROR\020\002\022\032\n\026SMTP_PORT_C" + "HANGE_ERROR\020\003\022%\n!IMAP_CONNECTION_MODE_CH" + "ANGE_ERROR\020\004\022%\n!SMTP_CONNECTION_MODE_CHA" + "NGE_ERROR\020\005*S\n\tErrorCode\022\021\n\rUNKNOWN_ERRO" + "R\020\000\022\031\n\025TLS_CERT_EXPORT_ERROR\020\001\022\030\n\024TLS_KE" + "Y_EXPORT_ERROR\020\0022\333\034\n\006Bridge\022I\n\013CheckToke" + "ns\022\034.google.protobuf.StringValue\032\034.googl" + "e.protobuf.StringValue\022\?\n\013AddLogEntry\022\030." + "grpc.AddLogEntryRequest\032\026.google.protobu" + "f.Empty\022:\n\010GuiReady\022\026.google.protobuf.Em" + "pty\032\026.grpc.GuiReadyResponse\0226\n\004Quit\022\026.go" + "ogle.protobuf.Empty\032\026.google.protobuf.Em" + "pty\0229\n\007Restart\022\026.google.protobuf.Empty\032\026" + ".google.protobuf.Empty\022C\n\rShowOnStartup\022" + "\026.google.protobuf.Empty\032\032.google.protobu" + "f.BoolValue\022F\n\020SetIsAutostartOn\022\032.google" + ".protobuf.BoolValue\032\026.google.protobuf.Em" + "pty\022C\n\rIsAutostartOn\022\026.google.protobuf.E" + "mpty\032\032.google.protobuf.BoolValue\022F\n\020SetI" + "sBetaEnabled\022\032.google.protobuf.BoolValue" + "\032\026.google.protobuf.Empty\022C\n\rIsBetaEnable" + "d\022\026.google.protobuf.Empty\032\032.google.proto" + "buf.BoolValue\022I\n\023SetIsAllMailVisible\022\032.g" + "oogle.protobuf.BoolValue\032\026.google.protob" + "uf.Empty\022F\n\020IsAllMailVisible\022\026.google.pr" + "otobuf.Empty\032\032.google.protobuf.BoolValue" + "\022>\n\014TriggerReset\022\026.google.protobuf.Empty" + "\032\026.google.protobuf.Empty\022\?\n\007Version\022\026.go" + "ogle.protobuf.Empty\032\034.google.protobuf.St" + "ringValue\022@\n\010LogsPath\022\026.google.protobuf." + "Empty\032\034.google.protobuf.StringValue\022C\n\013L" + "icensePath\022\026.google.protobuf.Empty\032\034.goo" + "gle.protobuf.StringValue\022L\n\024ReleaseNotes" + "PageLink\022\026.google.protobuf.Empty\032\034.googl" + "e.protobuf.StringValue\022N\n\026DependencyLice" + "nsesLink\022\026.google.protobuf.Empty\032\034.googl" + "e.protobuf.StringValue\022G\n\017LandingPageLin" + "k\022\026.google.protobuf.Empty\032\034.google.proto" + "buf.StringValue\022J\n\022SetColorSchemeName\022\034." + "google.protobuf.StringValue\032\026.google.pro" + "tobuf.Empty\022G\n\017ColorSchemeName\022\026.google." + "protobuf.Empty\032\034.google.protobuf.StringV" + "alue\022J\n\022CurrentEmailClient\022\026.google.prot" + "obuf.Empty\032\034.google.protobuf.StringValue" + "\022;\n\tReportBug\022\026.grpc.ReportBugRequest\032\026." + "google.protobuf.Empty\022M\n\025ExportTLSCertif" + "icates\022\034.google.protobuf.StringValue\032\026.g" + "oogle.protobuf.Empty\022E\n\rForceLauncher\022\034." + "google.protobuf.StringValue\032\026.google.pro" + "tobuf.Empty\022I\n\021SetMainExecutable\022\034.googl" + "e.protobuf.StringValue\032\026.google.protobuf" + ".Empty\0223\n\005Login\022\022.grpc.LoginRequest\032\026.go" + "ogle.protobuf.Empty\0226\n\010Login2FA\022\022.grpc.L" + "oginRequest\032\026.google.protobuf.Empty\022=\n\017L" + "ogin2Passwords\022\022.grpc.LoginRequest\032\026.goo" + "gle.protobuf.Empty\022=\n\nLoginAbort\022\027.grpc." + "LoginAbortRequest\032\026.google.protobuf.Empt" + "y\022=\n\013CheckUpdate\022\026.google.protobuf.Empty" + "\032\026.google.protobuf.Empty\022\?\n\rInstallUpdat" + "e\022\026.google.protobuf.Empty\032\026.google.proto" + "buf.Empty\022L\n\026SetIsAutomaticUpdateOn\022\032.go" + "ogle.protobuf.BoolValue\032\026.google.protobu" + "f.Empty\022I\n\023IsAutomaticUpdateOn\022\026.google." + "protobuf.Empty\032\032.google.protobuf.BoolVal" + "ue\022E\n\rDiskCachePath\022\026.google.protobuf.Em" + "pty\032\034.google.protobuf.StringValue\022H\n\020Set" + "DiskCachePath\022\034.google.protobuf.StringVa" + "lue\032\026.google.protobuf.Empty\022E\n\017SetIsDoHE" + "nabled\022\032.google.protobuf.BoolValue\032\026.goo" + "gle.protobuf.Empty\022B\n\014IsDoHEnabled\022\026.goo" + "gle.protobuf.Empty\032\032.google.protobuf.Boo" + "lValue\022D\n\022MailServerSettings\022\026.google.pr" + "otobuf.Empty\032\026.grpc.ImapSmtpSettings\022G\n\025" + "SetMailServerSettings\022\026.grpc.ImapSmtpSet" + "tings\032\026.google.protobuf.Empty\022@\n\010Hostnam" + "e\022\026.google.protobuf.Empty\032\034.google.proto" + "buf.StringValue\022E\n\nIsPortFree\022\033.google.p" + "rotobuf.Int32Value\032\032.google.protobuf.Boo" + "lValue\022N\n\022AvailableKeychains\022\026.google.pr" + "otobuf.Empty\032 .grpc.AvailableKeychainsRe" + "sponse\022J\n\022SetCurrentKeychain\022\034.google.pr" + "otobuf.StringValue\032\026.google.protobuf.Emp" + "ty\022G\n\017CurrentKeychain\022\026.google.protobuf." + "Empty\032\034.google.protobuf.StringValue\022=\n\013G" + "etUserList\022\026.google.protobuf.Empty\032\026.grp" + "c.UserListResponse\0223\n\007GetUser\022\034.google.p" + "rotobuf.StringValue\032\n.grpc.User\022F\n\020SetUs" + "erSplitMode\022\032.grpc.UserSplitModeRequest\032" + "\026.google.protobuf.Empty\022B\n\nLogoutUser\022\034." + "google.protobuf.StringValue\032\026.google.pro" + "tobuf.Empty\022B\n\nRemoveUser\022\034.google.proto" + "buf.StringValue\032\026.google.protobuf.Empty\022" + "Q\n\026ConfigureUserAppleMail\022\037.grpc.Configu" + "reAppleMailRequest\032\026.google.protobuf.Emp" + "ty\022\?\n\016RunEventStream\022\030.grpc.EventStreamR" + "equest\032\021.grpc.StreamEvent0\001\022A\n\017StopEvent" + "Stream\022\026.google.protobuf.Empty\032\026.google." + "protobuf.EmptyB6Z4github.com/ProtonMail/" + "proton-bridge/v3/internal/grpcb\006proto3" ; static const ::_pbi::DescriptorTable* const descriptor_table_bridge_2eproto_deps[2] = { &::descriptor_table_google_2fprotobuf_2fempty_2eproto, @@ -1665,9 +1748,9 @@ static const ::_pbi::DescriptorTable* const descriptor_table_bridge_2eproto_deps }; static ::_pbi::once_flag descriptor_table_bridge_2eproto_once; const ::_pbi::DescriptorTable descriptor_table_bridge_2eproto = { - false, false, 9990, descriptor_table_protodef_bridge_2eproto, + false, false, 10318, descriptor_table_protodef_bridge_2eproto, "bridge.proto", - &descriptor_table_bridge_2eproto_once, descriptor_table_bridge_2eproto_deps, 2, 60, + &descriptor_table_bridge_2eproto_once, descriptor_table_bridge_2eproto_deps, 2, 63, schemas, file_default_instances, TableStruct_bridge_2eproto::offsets, file_level_metadata_bridge_2eproto, file_level_enum_descriptors_bridge_2eproto, file_level_service_descriptors_bridge_2eproto, @@ -12432,6 +12515,9 @@ class UserEvent::_Internal { static const ::grpc::UserBadEvent& userbadevent(const UserEvent* msg); static const ::grpc::UsedBytesChangedEvent& usedbyteschangedevent(const UserEvent* msg); static const ::grpc::ImapLoginFailedEvent& imaploginfailedevent(const UserEvent* msg); + static const ::grpc::SyncStartedEvent& syncstartedevent(const UserEvent* msg); + static const ::grpc::SyncFinishedEvent& syncfinishedevent(const UserEvent* msg); + static const ::grpc::SyncProgressEvent& syncprogressevent(const UserEvent* msg); }; const ::grpc::ToggleSplitModeFinishedEvent& @@ -12458,6 +12544,18 @@ const ::grpc::ImapLoginFailedEvent& UserEvent::_Internal::imaploginfailedevent(const UserEvent* msg) { return *msg->_impl_.event_.imaploginfailedevent_; } +const ::grpc::SyncStartedEvent& +UserEvent::_Internal::syncstartedevent(const UserEvent* msg) { + return *msg->_impl_.event_.syncstartedevent_; +} +const ::grpc::SyncFinishedEvent& +UserEvent::_Internal::syncfinishedevent(const UserEvent* msg) { + return *msg->_impl_.event_.syncfinishedevent_; +} +const ::grpc::SyncProgressEvent& +UserEvent::_Internal::syncprogressevent(const UserEvent* msg) { + return *msg->_impl_.event_.syncprogressevent_; +} void UserEvent::set_allocated_togglesplitmodefinished(::grpc::ToggleSplitModeFinishedEvent* togglesplitmodefinished) { ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); clear_event(); @@ -12548,6 +12646,51 @@ void UserEvent::set_allocated_imaploginfailedevent(::grpc::ImapLoginFailedEvent* } // @@protoc_insertion_point(field_set_allocated:grpc.UserEvent.imapLoginFailedEvent) } +void UserEvent::set_allocated_syncstartedevent(::grpc::SyncStartedEvent* syncstartedevent) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + clear_event(); + if (syncstartedevent) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(syncstartedevent); + if (message_arena != submessage_arena) { + syncstartedevent = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, syncstartedevent, submessage_arena); + } + set_has_syncstartedevent(); + _impl_.event_.syncstartedevent_ = syncstartedevent; + } + // @@protoc_insertion_point(field_set_allocated:grpc.UserEvent.syncStartedEvent) +} +void UserEvent::set_allocated_syncfinishedevent(::grpc::SyncFinishedEvent* syncfinishedevent) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + clear_event(); + if (syncfinishedevent) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(syncfinishedevent); + if (message_arena != submessage_arena) { + syncfinishedevent = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, syncfinishedevent, submessage_arena); + } + set_has_syncfinishedevent(); + _impl_.event_.syncfinishedevent_ = syncfinishedevent; + } + // @@protoc_insertion_point(field_set_allocated:grpc.UserEvent.syncFinishedEvent) +} +void UserEvent::set_allocated_syncprogressevent(::grpc::SyncProgressEvent* syncprogressevent) { + ::PROTOBUF_NAMESPACE_ID::Arena* message_arena = GetArenaForAllocation(); + clear_event(); + if (syncprogressevent) { + ::PROTOBUF_NAMESPACE_ID::Arena* submessage_arena = + ::PROTOBUF_NAMESPACE_ID::Arena::InternalGetOwningArena(syncprogressevent); + if (message_arena != submessage_arena) { + syncprogressevent = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage( + message_arena, syncprogressevent, submessage_arena); + } + set_has_syncprogressevent(); + _impl_.event_.syncprogressevent_ = syncprogressevent; + } + // @@protoc_insertion_point(field_set_allocated:grpc.UserEvent.syncProgressEvent) +} UserEvent::UserEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned) : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { @@ -12595,6 +12738,21 @@ UserEvent::UserEvent(const UserEvent& from) from._internal_imaploginfailedevent()); break; } + case kSyncStartedEvent: { + _this->_internal_mutable_syncstartedevent()->::grpc::SyncStartedEvent::MergeFrom( + from._internal_syncstartedevent()); + break; + } + case kSyncFinishedEvent: { + _this->_internal_mutable_syncfinishedevent()->::grpc::SyncFinishedEvent::MergeFrom( + from._internal_syncfinishedevent()); + break; + } + case kSyncProgressEvent: { + _this->_internal_mutable_syncprogressevent()->::grpc::SyncProgressEvent::MergeFrom( + from._internal_syncprogressevent()); + break; + } case EVENT_NOT_SET: { break; } @@ -12673,6 +12831,24 @@ void UserEvent::clear_event() { } break; } + case kSyncStartedEvent: { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.event_.syncstartedevent_; + } + break; + } + case kSyncFinishedEvent: { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.event_.syncfinishedevent_; + } + break; + } + case kSyncProgressEvent: { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.event_.syncprogressevent_; + } + break; + } case EVENT_NOT_SET: { break; } @@ -12745,6 +12921,30 @@ const char* UserEvent::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx } else goto handle_unusual; continue; + // .grpc.SyncStartedEvent syncStartedEvent = 7; + case 7: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 58)) { + ptr = ctx->ParseMessage(_internal_mutable_syncstartedevent(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // .grpc.SyncFinishedEvent syncFinishedEvent = 8; + case 8: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 66)) { + ptr = ctx->ParseMessage(_internal_mutable_syncfinishedevent(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // .grpc.SyncProgressEvent syncProgressEvent = 9; + case 9: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 74)) { + ptr = ctx->ParseMessage(_internal_mutable_syncprogressevent(), ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; default: goto handle_unusual; } // switch @@ -12816,6 +13016,27 @@ uint8_t* UserEvent::_InternalSerialize( _Internal::imaploginfailedevent(this).GetCachedSize(), target, stream); } + // .grpc.SyncStartedEvent syncStartedEvent = 7; + if (_internal_has_syncstartedevent()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(7, _Internal::syncstartedevent(this), + _Internal::syncstartedevent(this).GetCachedSize(), target, stream); + } + + // .grpc.SyncFinishedEvent syncFinishedEvent = 8; + if (_internal_has_syncfinishedevent()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(8, _Internal::syncfinishedevent(this), + _Internal::syncfinishedevent(this).GetCachedSize(), target, stream); + } + + // .grpc.SyncProgressEvent syncProgressEvent = 9; + if (_internal_has_syncprogressevent()) { + target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite:: + InternalWriteMessage(9, _Internal::syncprogressevent(this), + _Internal::syncprogressevent(this).GetCachedSize(), target, stream); + } + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); @@ -12875,6 +13096,27 @@ size_t UserEvent::ByteSizeLong() const { *_impl_.event_.imaploginfailedevent_); break; } + // .grpc.SyncStartedEvent syncStartedEvent = 7; + case kSyncStartedEvent: { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.event_.syncstartedevent_); + break; + } + // .grpc.SyncFinishedEvent syncFinishedEvent = 8; + case kSyncFinishedEvent: { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.event_.syncfinishedevent_); + break; + } + // .grpc.SyncProgressEvent syncProgressEvent = 9; + case kSyncProgressEvent: { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize( + *_impl_.event_.syncprogressevent_); + break; + } case EVENT_NOT_SET: { break; } @@ -12928,6 +13170,21 @@ void UserEvent::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROT from._internal_imaploginfailedevent()); break; } + case kSyncStartedEvent: { + _this->_internal_mutable_syncstartedevent()->::grpc::SyncStartedEvent::MergeFrom( + from._internal_syncstartedevent()); + break; + } + case kSyncFinishedEvent: { + _this->_internal_mutable_syncfinishedevent()->::grpc::SyncFinishedEvent::MergeFrom( + from._internal_syncfinishedevent()); + break; + } + case kSyncProgressEvent: { + _this->_internal_mutable_syncprogressevent()->::grpc::SyncProgressEvent::MergeFrom( + from._internal_syncprogressevent()); + break; + } case EVENT_NOT_SET: { break; } @@ -14256,6 +14513,711 @@ void ImapLoginFailedEvent::InternalSwap(ImapLoginFailedEvent* other) { // =================================================================== +class SyncStartedEvent::_Internal { + public: +}; + +SyncStartedEvent::SyncStartedEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:grpc.SyncStartedEvent) +} +SyncStartedEvent::SyncStartedEvent(const SyncStartedEvent& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + SyncStartedEvent* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.userid_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.userid_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.userid_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_userid().empty()) { + _this->_impl_.userid_.Set(from._internal_userid(), + _this->GetArenaForAllocation()); + } + // @@protoc_insertion_point(copy_constructor:grpc.SyncStartedEvent) +} + +inline void SyncStartedEvent::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.userid_){} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.userid_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.userid_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +SyncStartedEvent::~SyncStartedEvent() { + // @@protoc_insertion_point(destructor:grpc.SyncStartedEvent) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void SyncStartedEvent::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.userid_.Destroy(); +} + +void SyncStartedEvent::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void SyncStartedEvent::Clear() { +// @@protoc_insertion_point(message_clear_start:grpc.SyncStartedEvent) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.userid_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* SyncStartedEvent::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string userID = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 10)) { + auto str = _internal_mutable_userid(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "grpc.SyncStartedEvent.userID")); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* SyncStartedEvent::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:grpc.SyncStartedEvent) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string userID = 1; + if (!this->_internal_userid().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_userid().data(), static_cast(this->_internal_userid().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "grpc.SyncStartedEvent.userID"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_userid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:grpc.SyncStartedEvent) + return target; +} + +size_t SyncStartedEvent::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:grpc.SyncStartedEvent) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string userID = 1; + if (!this->_internal_userid().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_userid()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData SyncStartedEvent::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + SyncStartedEvent::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*SyncStartedEvent::GetClassData() const { return &_class_data_; } + + +void SyncStartedEvent::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:grpc.SyncStartedEvent) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_userid().empty()) { + _this->_internal_set_userid(from._internal_userid()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void SyncStartedEvent::CopyFrom(const SyncStartedEvent& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:grpc.SyncStartedEvent) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SyncStartedEvent::IsInitialized() const { + return true; +} + +void SyncStartedEvent::InternalSwap(SyncStartedEvent* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.userid_, lhs_arena, + &other->_impl_.userid_, rhs_arena + ); +} + +::PROTOBUF_NAMESPACE_ID::Metadata SyncStartedEvent::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_bridge_2eproto_getter, &descriptor_table_bridge_2eproto_once, + file_level_metadata_bridge_2eproto[59]); +} + +// =================================================================== + +class SyncFinishedEvent::_Internal { + public: +}; + +SyncFinishedEvent::SyncFinishedEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:grpc.SyncFinishedEvent) +} +SyncFinishedEvent::SyncFinishedEvent(const SyncFinishedEvent& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + SyncFinishedEvent* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.userid_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.userid_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.userid_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_userid().empty()) { + _this->_impl_.userid_.Set(from._internal_userid(), + _this->GetArenaForAllocation()); + } + // @@protoc_insertion_point(copy_constructor:grpc.SyncFinishedEvent) +} + +inline void SyncFinishedEvent::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.userid_){} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.userid_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.userid_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +SyncFinishedEvent::~SyncFinishedEvent() { + // @@protoc_insertion_point(destructor:grpc.SyncFinishedEvent) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void SyncFinishedEvent::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.userid_.Destroy(); +} + +void SyncFinishedEvent::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void SyncFinishedEvent::Clear() { +// @@protoc_insertion_point(message_clear_start:grpc.SyncFinishedEvent) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.userid_.ClearToEmpty(); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* SyncFinishedEvent::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string userID = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 10)) { + auto str = _internal_mutable_userid(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "grpc.SyncFinishedEvent.userID")); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* SyncFinishedEvent::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:grpc.SyncFinishedEvent) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string userID = 1; + if (!this->_internal_userid().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_userid().data(), static_cast(this->_internal_userid().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "grpc.SyncFinishedEvent.userID"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_userid(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:grpc.SyncFinishedEvent) + return target; +} + +size_t SyncFinishedEvent::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:grpc.SyncFinishedEvent) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string userID = 1; + if (!this->_internal_userid().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_userid()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData SyncFinishedEvent::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + SyncFinishedEvent::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*SyncFinishedEvent::GetClassData() const { return &_class_data_; } + + +void SyncFinishedEvent::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:grpc.SyncFinishedEvent) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_userid().empty()) { + _this->_internal_set_userid(from._internal_userid()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void SyncFinishedEvent::CopyFrom(const SyncFinishedEvent& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:grpc.SyncFinishedEvent) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SyncFinishedEvent::IsInitialized() const { + return true; +} + +void SyncFinishedEvent::InternalSwap(SyncFinishedEvent* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.userid_, lhs_arena, + &other->_impl_.userid_, rhs_arena + ); +} + +::PROTOBUF_NAMESPACE_ID::Metadata SyncFinishedEvent::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_bridge_2eproto_getter, &descriptor_table_bridge_2eproto_once, + file_level_metadata_bridge_2eproto[60]); +} + +// =================================================================== + +class SyncProgressEvent::_Internal { + public: +}; + +SyncProgressEvent::SyncProgressEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned) + : ::PROTOBUF_NAMESPACE_ID::Message(arena, is_message_owned) { + SharedCtor(arena, is_message_owned); + // @@protoc_insertion_point(arena_constructor:grpc.SyncProgressEvent) +} +SyncProgressEvent::SyncProgressEvent(const SyncProgressEvent& from) + : ::PROTOBUF_NAMESPACE_ID::Message() { + SyncProgressEvent* const _this = this; (void)_this; + new (&_impl_) Impl_{ + decltype(_impl_.userid_){} + , decltype(_impl_.progress_){} + , decltype(_impl_.elapsedms_){} + , decltype(_impl_.remainingms_){} + , /*decltype(_impl_._cached_size_)*/{}}; + + _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); + _impl_.userid_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.userid_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (!from._internal_userid().empty()) { + _this->_impl_.userid_.Set(from._internal_userid(), + _this->GetArenaForAllocation()); + } + ::memcpy(&_impl_.progress_, &from._impl_.progress_, + static_cast(reinterpret_cast(&_impl_.remainingms_) - + reinterpret_cast(&_impl_.progress_)) + sizeof(_impl_.remainingms_)); + // @@protoc_insertion_point(copy_constructor:grpc.SyncProgressEvent) +} + +inline void SyncProgressEvent::SharedCtor( + ::_pb::Arena* arena, bool is_message_owned) { + (void)arena; + (void)is_message_owned; + new (&_impl_) Impl_{ + decltype(_impl_.userid_){} + , decltype(_impl_.progress_){0} + , decltype(_impl_.elapsedms_){int64_t{0}} + , decltype(_impl_.remainingms_){int64_t{0}} + , /*decltype(_impl_._cached_size_)*/{} + }; + _impl_.userid_.InitDefault(); + #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + _impl_.userid_.Set("", GetArenaForAllocation()); + #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING +} + +SyncProgressEvent::~SyncProgressEvent() { + // @@protoc_insertion_point(destructor:grpc.SyncProgressEvent) + if (auto *arena = _internal_metadata_.DeleteReturnArena<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>()) { + (void)arena; + return; + } + SharedDtor(); +} + +inline void SyncProgressEvent::SharedDtor() { + GOOGLE_DCHECK(GetArenaForAllocation() == nullptr); + _impl_.userid_.Destroy(); +} + +void SyncProgressEvent::SetCachedSize(int size) const { + _impl_._cached_size_.Set(size); +} + +void SyncProgressEvent::Clear() { +// @@protoc_insertion_point(message_clear_start:grpc.SyncProgressEvent) + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + _impl_.userid_.ClearToEmpty(); + ::memset(&_impl_.progress_, 0, static_cast( + reinterpret_cast(&_impl_.remainingms_) - + reinterpret_cast(&_impl_.progress_)) + sizeof(_impl_.remainingms_)); + _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(); +} + +const char* SyncProgressEvent::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) { +#define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure + while (!ctx->Done(&ptr)) { + uint32_t tag; + ptr = ::_pbi::ReadTag(ptr, &tag); + switch (tag >> 3) { + // string userID = 1; + case 1: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 10)) { + auto str = _internal_mutable_userid(); + ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx); + CHK_(ptr); + CHK_(::_pbi::VerifyUTF8(str, "grpc.SyncProgressEvent.userID")); + } else + goto handle_unusual; + continue; + // double progress = 2; + case 2: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 17)) { + _impl_.progress_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad(ptr); + ptr += sizeof(double); + } else + goto handle_unusual; + continue; + // int64 elapsedMs = 3; + case 3: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 24)) { + _impl_.elapsedms_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + // int64 remainingMs = 4; + case 4: + if (PROTOBUF_PREDICT_TRUE(static_cast(tag) == 32)) { + _impl_.remainingms_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr); + CHK_(ptr); + } else + goto handle_unusual; + continue; + default: + goto handle_unusual; + } // switch + handle_unusual: + if ((tag == 0) || ((tag & 7) == 4)) { + CHK_(ptr); + ctx->SetLastTag(tag); + goto message_done; + } + ptr = UnknownFieldParse( + tag, + _internal_metadata_.mutable_unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(), + ptr, ctx); + CHK_(ptr != nullptr); + } // while +message_done: + return ptr; +failure: + ptr = nullptr; + goto message_done; +#undef CHK_ +} + +uint8_t* SyncProgressEvent::_InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const { + // @@protoc_insertion_point(serialize_to_array_start:grpc.SyncProgressEvent) + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + // string userID = 1; + if (!this->_internal_userid().empty()) { + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String( + this->_internal_userid().data(), static_cast(this->_internal_userid().length()), + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE, + "grpc.SyncProgressEvent.userID"); + target = stream->WriteStringMaybeAliased( + 1, this->_internal_userid(), target); + } + + // double progress = 2; + static_assert(sizeof(uint64_t) == sizeof(double), "Code assumes uint64_t and double are the same size."); + double tmp_progress = this->_internal_progress(); + uint64_t raw_progress; + memcpy(&raw_progress, &tmp_progress, sizeof(tmp_progress)); + if (raw_progress != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteDoubleToArray(2, this->_internal_progress(), target); + } + + // int64 elapsedMs = 3; + if (this->_internal_elapsedms() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt64ToArray(3, this->_internal_elapsedms(), target); + } + + // int64 remainingMs = 4; + if (this->_internal_remainingms() != 0) { + target = stream->EnsureSpace(target); + target = ::_pbi::WireFormatLite::WriteInt64ToArray(4, this->_internal_remainingms(), target); + } + + if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) { + target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray( + _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream); + } + // @@protoc_insertion_point(serialize_to_array_end:grpc.SyncProgressEvent) + return target; +} + +size_t SyncProgressEvent::ByteSizeLong() const { +// @@protoc_insertion_point(message_byte_size_start:grpc.SyncProgressEvent) + size_t total_size = 0; + + uint32_t cached_has_bits = 0; + // Prevent compiler warnings about cached_has_bits being unused + (void) cached_has_bits; + + // string userID = 1; + if (!this->_internal_userid().empty()) { + total_size += 1 + + ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize( + this->_internal_userid()); + } + + // double progress = 2; + static_assert(sizeof(uint64_t) == sizeof(double), "Code assumes uint64_t and double are the same size."); + double tmp_progress = this->_internal_progress(); + uint64_t raw_progress; + memcpy(&raw_progress, &tmp_progress, sizeof(tmp_progress)); + if (raw_progress != 0) { + total_size += 1 + 8; + } + + // int64 elapsedMs = 3; + if (this->_internal_elapsedms() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne(this->_internal_elapsedms()); + } + + // int64 remainingMs = 4; + if (this->_internal_remainingms() != 0) { + total_size += ::_pbi::WireFormatLite::Int64SizePlusOne(this->_internal_remainingms()); + } + + return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_); +} + +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData SyncProgressEvent::_class_data_ = { + ::PROTOBUF_NAMESPACE_ID::Message::CopyWithSourceCheck, + SyncProgressEvent::MergeImpl +}; +const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*SyncProgressEvent::GetClassData() const { return &_class_data_; } + + +void SyncProgressEvent::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) { + auto* const _this = static_cast(&to_msg); + auto& from = static_cast(from_msg); + // @@protoc_insertion_point(class_specific_merge_from_start:grpc.SyncProgressEvent) + GOOGLE_DCHECK_NE(&from, _this); + uint32_t cached_has_bits = 0; + (void) cached_has_bits; + + if (!from._internal_userid().empty()) { + _this->_internal_set_userid(from._internal_userid()); + } + static_assert(sizeof(uint64_t) == sizeof(double), "Code assumes uint64_t and double are the same size."); + double tmp_progress = from._internal_progress(); + uint64_t raw_progress; + memcpy(&raw_progress, &tmp_progress, sizeof(tmp_progress)); + if (raw_progress != 0) { + _this->_internal_set_progress(from._internal_progress()); + } + if (from._internal_elapsedms() != 0) { + _this->_internal_set_elapsedms(from._internal_elapsedms()); + } + if (from._internal_remainingms() != 0) { + _this->_internal_set_remainingms(from._internal_remainingms()); + } + _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_); +} + +void SyncProgressEvent::CopyFrom(const SyncProgressEvent& from) { +// @@protoc_insertion_point(class_specific_copy_from_start:grpc.SyncProgressEvent) + if (&from == this) return; + Clear(); + MergeFrom(from); +} + +bool SyncProgressEvent::IsInitialized() const { + return true; +} + +void SyncProgressEvent::InternalSwap(SyncProgressEvent* other) { + using std::swap; + auto* lhs_arena = GetArenaForAllocation(); + auto* rhs_arena = other->GetArenaForAllocation(); + _internal_metadata_.InternalSwap(&other->_internal_metadata_); + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap( + &_impl_.userid_, lhs_arena, + &other->_impl_.userid_, rhs_arena + ); + ::PROTOBUF_NAMESPACE_ID::internal::memswap< + PROTOBUF_FIELD_OFFSET(SyncProgressEvent, _impl_.remainingms_) + + sizeof(SyncProgressEvent::_impl_.remainingms_) + - PROTOBUF_FIELD_OFFSET(SyncProgressEvent, _impl_.progress_)>( + reinterpret_cast(&_impl_.progress_), + reinterpret_cast(&other->_impl_.progress_)); +} + +::PROTOBUF_NAMESPACE_ID::Metadata SyncProgressEvent::GetMetadata() const { + return ::_pbi::AssignDescriptors( + &descriptor_table_bridge_2eproto_getter, &descriptor_table_bridge_2eproto_once, + file_level_metadata_bridge_2eproto[61]); +} + +// =================================================================== + class GenericErrorEvent::_Internal { public: }; @@ -14432,7 +15394,7 @@ void GenericErrorEvent::InternalSwap(GenericErrorEvent* other) { ::PROTOBUF_NAMESPACE_ID::Metadata GenericErrorEvent::GetMetadata() const { return ::_pbi::AssignDescriptors( &descriptor_table_bridge_2eproto_getter, &descriptor_table_bridge_2eproto_once, - file_level_metadata_bridge_2eproto[59]); + file_level_metadata_bridge_2eproto[62]); } // @@protoc_insertion_point(namespace_scope) @@ -14674,6 +15636,18 @@ template<> PROTOBUF_NOINLINE ::grpc::ImapLoginFailedEvent* Arena::CreateMaybeMessage< ::grpc::ImapLoginFailedEvent >(Arena* arena) { return Arena::CreateMessageInternal< ::grpc::ImapLoginFailedEvent >(arena); } +template<> PROTOBUF_NOINLINE ::grpc::SyncStartedEvent* +Arena::CreateMaybeMessage< ::grpc::SyncStartedEvent >(Arena* arena) { + return Arena::CreateMessageInternal< ::grpc::SyncStartedEvent >(arena); +} +template<> PROTOBUF_NOINLINE ::grpc::SyncFinishedEvent* +Arena::CreateMaybeMessage< ::grpc::SyncFinishedEvent >(Arena* arena) { + return Arena::CreateMessageInternal< ::grpc::SyncFinishedEvent >(arena); +} +template<> PROTOBUF_NOINLINE ::grpc::SyncProgressEvent* +Arena::CreateMaybeMessage< ::grpc::SyncProgressEvent >(Arena* arena) { + return Arena::CreateMessageInternal< ::grpc::SyncProgressEvent >(arena); +} template<> PROTOBUF_NOINLINE ::grpc::GenericErrorEvent* Arena::CreateMaybeMessage< ::grpc::GenericErrorEvent >(Arena* arena) { return Arena::CreateMessageInternal< ::grpc::GenericErrorEvent >(arena); diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h index e223ea57..1abcc509 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.h @@ -172,6 +172,15 @@ extern ShowMainWindowEventDefaultTypeInternal _ShowMainWindowEvent_default_insta class StreamEvent; struct StreamEventDefaultTypeInternal; extern StreamEventDefaultTypeInternal _StreamEvent_default_instance_; +class SyncFinishedEvent; +struct SyncFinishedEventDefaultTypeInternal; +extern SyncFinishedEventDefaultTypeInternal _SyncFinishedEvent_default_instance_; +class SyncProgressEvent; +struct SyncProgressEventDefaultTypeInternal; +extern SyncProgressEventDefaultTypeInternal _SyncProgressEvent_default_instance_; +class SyncStartedEvent; +struct SyncStartedEventDefaultTypeInternal; +extern SyncStartedEventDefaultTypeInternal _SyncStartedEvent_default_instance_; class ToggleAutostartFinishedEvent; struct ToggleAutostartFinishedEventDefaultTypeInternal; extern ToggleAutostartFinishedEventDefaultTypeInternal _ToggleAutostartFinishedEvent_default_instance_; @@ -272,6 +281,9 @@ template<> ::grpc::ReportBugSuccessEvent* Arena::CreateMaybeMessage<::grpc::Repo template<> ::grpc::ResetFinishedEvent* Arena::CreateMaybeMessage<::grpc::ResetFinishedEvent>(Arena*); template<> ::grpc::ShowMainWindowEvent* Arena::CreateMaybeMessage<::grpc::ShowMainWindowEvent>(Arena*); template<> ::grpc::StreamEvent* Arena::CreateMaybeMessage<::grpc::StreamEvent>(Arena*); +template<> ::grpc::SyncFinishedEvent* Arena::CreateMaybeMessage<::grpc::SyncFinishedEvent>(Arena*); +template<> ::grpc::SyncProgressEvent* Arena::CreateMaybeMessage<::grpc::SyncProgressEvent>(Arena*); +template<> ::grpc::SyncStartedEvent* Arena::CreateMaybeMessage<::grpc::SyncStartedEvent>(Arena*); template<> ::grpc::ToggleAutostartFinishedEvent* Arena::CreateMaybeMessage<::grpc::ToggleAutostartFinishedEvent>(Arena*); template<> ::grpc::ToggleSplitModeFinishedEvent* Arena::CreateMaybeMessage<::grpc::ToggleSplitModeFinishedEvent>(Arena*); template<> ::grpc::UpdateCheckFinished* Arena::CreateMaybeMessage<::grpc::UpdateCheckFinished>(Arena*); @@ -9087,6 +9099,9 @@ class UserEvent final : kUserBadEvent = 4, kUsedBytesChangedEvent = 5, kImapLoginFailedEvent = 6, + kSyncStartedEvent = 7, + kSyncFinishedEvent = 8, + kSyncProgressEvent = 9, EVENT_NOT_SET = 0, }; @@ -9174,6 +9189,9 @@ class UserEvent final : kUserBadEventFieldNumber = 4, kUsedBytesChangedEventFieldNumber = 5, kImapLoginFailedEventFieldNumber = 6, + kSyncStartedEventFieldNumber = 7, + kSyncFinishedEventFieldNumber = 8, + kSyncProgressEventFieldNumber = 9, }; // .grpc.ToggleSplitModeFinishedEvent toggleSplitModeFinished = 1; bool has_togglesplitmodefinished() const; @@ -9283,6 +9301,60 @@ class UserEvent final : ::grpc::ImapLoginFailedEvent* imaploginfailedevent); ::grpc::ImapLoginFailedEvent* unsafe_arena_release_imaploginfailedevent(); + // .grpc.SyncStartedEvent syncStartedEvent = 7; + bool has_syncstartedevent() const; + private: + bool _internal_has_syncstartedevent() const; + public: + void clear_syncstartedevent(); + const ::grpc::SyncStartedEvent& syncstartedevent() const; + PROTOBUF_NODISCARD ::grpc::SyncStartedEvent* release_syncstartedevent(); + ::grpc::SyncStartedEvent* mutable_syncstartedevent(); + void set_allocated_syncstartedevent(::grpc::SyncStartedEvent* syncstartedevent); + private: + const ::grpc::SyncStartedEvent& _internal_syncstartedevent() const; + ::grpc::SyncStartedEvent* _internal_mutable_syncstartedevent(); + public: + void unsafe_arena_set_allocated_syncstartedevent( + ::grpc::SyncStartedEvent* syncstartedevent); + ::grpc::SyncStartedEvent* unsafe_arena_release_syncstartedevent(); + + // .grpc.SyncFinishedEvent syncFinishedEvent = 8; + bool has_syncfinishedevent() const; + private: + bool _internal_has_syncfinishedevent() const; + public: + void clear_syncfinishedevent(); + const ::grpc::SyncFinishedEvent& syncfinishedevent() const; + PROTOBUF_NODISCARD ::grpc::SyncFinishedEvent* release_syncfinishedevent(); + ::grpc::SyncFinishedEvent* mutable_syncfinishedevent(); + void set_allocated_syncfinishedevent(::grpc::SyncFinishedEvent* syncfinishedevent); + private: + const ::grpc::SyncFinishedEvent& _internal_syncfinishedevent() const; + ::grpc::SyncFinishedEvent* _internal_mutable_syncfinishedevent(); + public: + void unsafe_arena_set_allocated_syncfinishedevent( + ::grpc::SyncFinishedEvent* syncfinishedevent); + ::grpc::SyncFinishedEvent* unsafe_arena_release_syncfinishedevent(); + + // .grpc.SyncProgressEvent syncProgressEvent = 9; + bool has_syncprogressevent() const; + private: + bool _internal_has_syncprogressevent() const; + public: + void clear_syncprogressevent(); + const ::grpc::SyncProgressEvent& syncprogressevent() const; + PROTOBUF_NODISCARD ::grpc::SyncProgressEvent* release_syncprogressevent(); + ::grpc::SyncProgressEvent* mutable_syncprogressevent(); + void set_allocated_syncprogressevent(::grpc::SyncProgressEvent* syncprogressevent); + private: + const ::grpc::SyncProgressEvent& _internal_syncprogressevent() const; + ::grpc::SyncProgressEvent* _internal_mutable_syncprogressevent(); + public: + void unsafe_arena_set_allocated_syncprogressevent( + ::grpc::SyncProgressEvent* syncprogressevent); + ::grpc::SyncProgressEvent* unsafe_arena_release_syncprogressevent(); + void clear_event(); EventCase event_case() const; // @@protoc_insertion_point(class_scope:grpc.UserEvent) @@ -9294,6 +9366,9 @@ class UserEvent final : void set_has_userbadevent(); void set_has_usedbyteschangedevent(); void set_has_imaploginfailedevent(); + void set_has_syncstartedevent(); + void set_has_syncfinishedevent(); + void set_has_syncprogressevent(); inline bool has_event() const; inline void clear_has_event(); @@ -9311,6 +9386,9 @@ class UserEvent final : ::grpc::UserBadEvent* userbadevent_; ::grpc::UsedBytesChangedEvent* usedbyteschangedevent_; ::grpc::ImapLoginFailedEvent* imaploginfailedevent_; + ::grpc::SyncStartedEvent* syncstartedevent_; + ::grpc::SyncFinishedEvent* syncfinishedevent_; + ::grpc::SyncProgressEvent* syncprogressevent_; } event_; mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; uint32_t _oneof_case_[1]; @@ -10266,6 +10344,498 @@ class ImapLoginFailedEvent final : }; // ------------------------------------------------------------------- +class SyncStartedEvent final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:grpc.SyncStartedEvent) */ { + public: + inline SyncStartedEvent() : SyncStartedEvent(nullptr) {} + ~SyncStartedEvent() override; + explicit PROTOBUF_CONSTEXPR SyncStartedEvent(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + SyncStartedEvent(const SyncStartedEvent& from); + SyncStartedEvent(SyncStartedEvent&& from) noexcept + : SyncStartedEvent() { + *this = ::std::move(from); + } + + inline SyncStartedEvent& operator=(const SyncStartedEvent& from) { + CopyFrom(from); + return *this; + } + inline SyncStartedEvent& operator=(SyncStartedEvent&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SyncStartedEvent& default_instance() { + return *internal_default_instance(); + } + static inline const SyncStartedEvent* internal_default_instance() { + return reinterpret_cast( + &_SyncStartedEvent_default_instance_); + } + static constexpr int kIndexInFileMessages = + 59; + + friend void swap(SyncStartedEvent& a, SyncStartedEvent& b) { + a.Swap(&b); + } + inline void Swap(SyncStartedEvent* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SyncStartedEvent* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SyncStartedEvent* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const SyncStartedEvent& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const SyncStartedEvent& from) { + SyncStartedEvent::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SyncStartedEvent* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "grpc.SyncStartedEvent"; + } + protected: + explicit SyncStartedEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUserIDFieldNumber = 1, + }; + // string userID = 1; + void clear_userid(); + const std::string& userid() const; + template + void set_userid(ArgT0&& arg0, ArgT... args); + std::string* mutable_userid(); + PROTOBUF_NODISCARD std::string* release_userid(); + void set_allocated_userid(std::string* userid); + private: + const std::string& _internal_userid() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_userid(const std::string& value); + std::string* _internal_mutable_userid(); + public: + + // @@protoc_insertion_point(class_scope:grpc.SyncStartedEvent) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr userid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_bridge_2eproto; +}; +// ------------------------------------------------------------------- + +class SyncFinishedEvent final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:grpc.SyncFinishedEvent) */ { + public: + inline SyncFinishedEvent() : SyncFinishedEvent(nullptr) {} + ~SyncFinishedEvent() override; + explicit PROTOBUF_CONSTEXPR SyncFinishedEvent(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + SyncFinishedEvent(const SyncFinishedEvent& from); + SyncFinishedEvent(SyncFinishedEvent&& from) noexcept + : SyncFinishedEvent() { + *this = ::std::move(from); + } + + inline SyncFinishedEvent& operator=(const SyncFinishedEvent& from) { + CopyFrom(from); + return *this; + } + inline SyncFinishedEvent& operator=(SyncFinishedEvent&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SyncFinishedEvent& default_instance() { + return *internal_default_instance(); + } + static inline const SyncFinishedEvent* internal_default_instance() { + return reinterpret_cast( + &_SyncFinishedEvent_default_instance_); + } + static constexpr int kIndexInFileMessages = + 60; + + friend void swap(SyncFinishedEvent& a, SyncFinishedEvent& b) { + a.Swap(&b); + } + inline void Swap(SyncFinishedEvent* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SyncFinishedEvent* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SyncFinishedEvent* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const SyncFinishedEvent& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const SyncFinishedEvent& from) { + SyncFinishedEvent::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SyncFinishedEvent* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "grpc.SyncFinishedEvent"; + } + protected: + explicit SyncFinishedEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUserIDFieldNumber = 1, + }; + // string userID = 1; + void clear_userid(); + const std::string& userid() const; + template + void set_userid(ArgT0&& arg0, ArgT... args); + std::string* mutable_userid(); + PROTOBUF_NODISCARD std::string* release_userid(); + void set_allocated_userid(std::string* userid); + private: + const std::string& _internal_userid() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_userid(const std::string& value); + std::string* _internal_mutable_userid(); + public: + + // @@protoc_insertion_point(class_scope:grpc.SyncFinishedEvent) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr userid_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_bridge_2eproto; +}; +// ------------------------------------------------------------------- + +class SyncProgressEvent final : + public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:grpc.SyncProgressEvent) */ { + public: + inline SyncProgressEvent() : SyncProgressEvent(nullptr) {} + ~SyncProgressEvent() override; + explicit PROTOBUF_CONSTEXPR SyncProgressEvent(::PROTOBUF_NAMESPACE_ID::internal::ConstantInitialized); + + SyncProgressEvent(const SyncProgressEvent& from); + SyncProgressEvent(SyncProgressEvent&& from) noexcept + : SyncProgressEvent() { + *this = ::std::move(from); + } + + inline SyncProgressEvent& operator=(const SyncProgressEvent& from) { + CopyFrom(from); + return *this; + } + inline SyncProgressEvent& operator=(SyncProgressEvent&& from) noexcept { + if (this == &from) return *this; + if (GetOwningArena() == from.GetOwningArena() + #ifdef PROTOBUF_FORCE_COPY_IN_MOVE + && GetOwningArena() != nullptr + #endif // !PROTOBUF_FORCE_COPY_IN_MOVE + ) { + InternalSwap(&from); + } else { + CopyFrom(from); + } + return *this; + } + + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* descriptor() { + return GetDescriptor(); + } + static const ::PROTOBUF_NAMESPACE_ID::Descriptor* GetDescriptor() { + return default_instance().GetMetadata().descriptor; + } + static const ::PROTOBUF_NAMESPACE_ID::Reflection* GetReflection() { + return default_instance().GetMetadata().reflection; + } + static const SyncProgressEvent& default_instance() { + return *internal_default_instance(); + } + static inline const SyncProgressEvent* internal_default_instance() { + return reinterpret_cast( + &_SyncProgressEvent_default_instance_); + } + static constexpr int kIndexInFileMessages = + 61; + + friend void swap(SyncProgressEvent& a, SyncProgressEvent& b) { + a.Swap(&b); + } + inline void Swap(SyncProgressEvent* other) { + if (other == this) return; + #ifdef PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() != nullptr && + GetOwningArena() == other->GetOwningArena()) { + #else // PROTOBUF_FORCE_COPY_IN_SWAP + if (GetOwningArena() == other->GetOwningArena()) { + #endif // !PROTOBUF_FORCE_COPY_IN_SWAP + InternalSwap(other); + } else { + ::PROTOBUF_NAMESPACE_ID::internal::GenericSwap(this, other); + } + } + void UnsafeArenaSwap(SyncProgressEvent* other) { + if (other == this) return; + GOOGLE_DCHECK(GetOwningArena() == other->GetOwningArena()); + InternalSwap(other); + } + + // implements Message ---------------------------------------------- + + SyncProgressEvent* New(::PROTOBUF_NAMESPACE_ID::Arena* arena = nullptr) const final { + return CreateMaybeMessage(arena); + } + using ::PROTOBUF_NAMESPACE_ID::Message::CopyFrom; + void CopyFrom(const SyncProgressEvent& from); + using ::PROTOBUF_NAMESPACE_ID::Message::MergeFrom; + void MergeFrom( const SyncProgressEvent& from) { + SyncProgressEvent::MergeImpl(*this, from); + } + private: + static void MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg); + public: + PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final; + bool IsInitialized() const final; + + size_t ByteSizeLong() const final; + const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final; + uint8_t* _InternalSerialize( + uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final; + int GetCachedSize() const final { return _impl_._cached_size_.Get(); } + + private: + void SharedCtor(::PROTOBUF_NAMESPACE_ID::Arena* arena, bool is_message_owned); + void SharedDtor(); + void SetCachedSize(int size) const final; + void InternalSwap(SyncProgressEvent* other); + + private: + friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata; + static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() { + return "grpc.SyncProgressEvent"; + } + protected: + explicit SyncProgressEvent(::PROTOBUF_NAMESPACE_ID::Arena* arena, + bool is_message_owned = false); + public: + + static const ClassData _class_data_; + const ::PROTOBUF_NAMESPACE_ID::Message::ClassData*GetClassData() const final; + + ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final; + + // nested types ---------------------------------------------------- + + // accessors ------------------------------------------------------- + + enum : int { + kUserIDFieldNumber = 1, + kProgressFieldNumber = 2, + kElapsedMsFieldNumber = 3, + kRemainingMsFieldNumber = 4, + }; + // string userID = 1; + void clear_userid(); + const std::string& userid() const; + template + void set_userid(ArgT0&& arg0, ArgT... args); + std::string* mutable_userid(); + PROTOBUF_NODISCARD std::string* release_userid(); + void set_allocated_userid(std::string* userid); + private: + const std::string& _internal_userid() const; + inline PROTOBUF_ALWAYS_INLINE void _internal_set_userid(const std::string& value); + std::string* _internal_mutable_userid(); + public: + + // double progress = 2; + void clear_progress(); + double progress() const; + void set_progress(double value); + private: + double _internal_progress() const; + void _internal_set_progress(double value); + public: + + // int64 elapsedMs = 3; + void clear_elapsedms(); + int64_t elapsedms() const; + void set_elapsedms(int64_t value); + private: + int64_t _internal_elapsedms() const; + void _internal_set_elapsedms(int64_t value); + public: + + // int64 remainingMs = 4; + void clear_remainingms(); + int64_t remainingms() const; + void set_remainingms(int64_t value); + private: + int64_t _internal_remainingms() const; + void _internal_set_remainingms(int64_t value); + public: + + // @@protoc_insertion_point(class_scope:grpc.SyncProgressEvent) + private: + class _Internal; + + template friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper; + typedef void InternalArenaConstructable_; + typedef void DestructorSkippable_; + struct Impl_ { + ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr userid_; + double progress_; + int64_t elapsedms_; + int64_t remainingms_; + mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_; + }; + union { Impl_ _impl_; }; + friend struct ::TableStruct_bridge_2eproto; +}; +// ------------------------------------------------------------------- + class GenericErrorEvent final : public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:grpc.GenericErrorEvent) */ { public: @@ -10314,7 +10884,7 @@ class GenericErrorEvent final : &_GenericErrorEvent_default_instance_); } static constexpr int kIndexInFileMessages = - 59; + 62; friend void swap(GenericErrorEvent& a, GenericErrorEvent& b) { a.Swap(&b); @@ -16245,6 +16815,228 @@ inline ::grpc::ImapLoginFailedEvent* UserEvent::mutable_imaploginfailedevent() { return _msg; } +// .grpc.SyncStartedEvent syncStartedEvent = 7; +inline bool UserEvent::_internal_has_syncstartedevent() const { + return event_case() == kSyncStartedEvent; +} +inline bool UserEvent::has_syncstartedevent() const { + return _internal_has_syncstartedevent(); +} +inline void UserEvent::set_has_syncstartedevent() { + _impl_._oneof_case_[0] = kSyncStartedEvent; +} +inline void UserEvent::clear_syncstartedevent() { + if (_internal_has_syncstartedevent()) { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.event_.syncstartedevent_; + } + clear_has_event(); + } +} +inline ::grpc::SyncStartedEvent* UserEvent::release_syncstartedevent() { + // @@protoc_insertion_point(field_release:grpc.UserEvent.syncStartedEvent) + if (_internal_has_syncstartedevent()) { + clear_has_event(); + ::grpc::SyncStartedEvent* temp = _impl_.event_.syncstartedevent_; + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + _impl_.event_.syncstartedevent_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::grpc::SyncStartedEvent& UserEvent::_internal_syncstartedevent() const { + return _internal_has_syncstartedevent() + ? *_impl_.event_.syncstartedevent_ + : reinterpret_cast< ::grpc::SyncStartedEvent&>(::grpc::_SyncStartedEvent_default_instance_); +} +inline const ::grpc::SyncStartedEvent& UserEvent::syncstartedevent() const { + // @@protoc_insertion_point(field_get:grpc.UserEvent.syncStartedEvent) + return _internal_syncstartedevent(); +} +inline ::grpc::SyncStartedEvent* UserEvent::unsafe_arena_release_syncstartedevent() { + // @@protoc_insertion_point(field_unsafe_arena_release:grpc.UserEvent.syncStartedEvent) + if (_internal_has_syncstartedevent()) { + clear_has_event(); + ::grpc::SyncStartedEvent* temp = _impl_.event_.syncstartedevent_; + _impl_.event_.syncstartedevent_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void UserEvent::unsafe_arena_set_allocated_syncstartedevent(::grpc::SyncStartedEvent* syncstartedevent) { + clear_event(); + if (syncstartedevent) { + set_has_syncstartedevent(); + _impl_.event_.syncstartedevent_ = syncstartedevent; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:grpc.UserEvent.syncStartedEvent) +} +inline ::grpc::SyncStartedEvent* UserEvent::_internal_mutable_syncstartedevent() { + if (!_internal_has_syncstartedevent()) { + clear_event(); + set_has_syncstartedevent(); + _impl_.event_.syncstartedevent_ = CreateMaybeMessage< ::grpc::SyncStartedEvent >(GetArenaForAllocation()); + } + return _impl_.event_.syncstartedevent_; +} +inline ::grpc::SyncStartedEvent* UserEvent::mutable_syncstartedevent() { + ::grpc::SyncStartedEvent* _msg = _internal_mutable_syncstartedevent(); + // @@protoc_insertion_point(field_mutable:grpc.UserEvent.syncStartedEvent) + return _msg; +} + +// .grpc.SyncFinishedEvent syncFinishedEvent = 8; +inline bool UserEvent::_internal_has_syncfinishedevent() const { + return event_case() == kSyncFinishedEvent; +} +inline bool UserEvent::has_syncfinishedevent() const { + return _internal_has_syncfinishedevent(); +} +inline void UserEvent::set_has_syncfinishedevent() { + _impl_._oneof_case_[0] = kSyncFinishedEvent; +} +inline void UserEvent::clear_syncfinishedevent() { + if (_internal_has_syncfinishedevent()) { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.event_.syncfinishedevent_; + } + clear_has_event(); + } +} +inline ::grpc::SyncFinishedEvent* UserEvent::release_syncfinishedevent() { + // @@protoc_insertion_point(field_release:grpc.UserEvent.syncFinishedEvent) + if (_internal_has_syncfinishedevent()) { + clear_has_event(); + ::grpc::SyncFinishedEvent* temp = _impl_.event_.syncfinishedevent_; + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + _impl_.event_.syncfinishedevent_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::grpc::SyncFinishedEvent& UserEvent::_internal_syncfinishedevent() const { + return _internal_has_syncfinishedevent() + ? *_impl_.event_.syncfinishedevent_ + : reinterpret_cast< ::grpc::SyncFinishedEvent&>(::grpc::_SyncFinishedEvent_default_instance_); +} +inline const ::grpc::SyncFinishedEvent& UserEvent::syncfinishedevent() const { + // @@protoc_insertion_point(field_get:grpc.UserEvent.syncFinishedEvent) + return _internal_syncfinishedevent(); +} +inline ::grpc::SyncFinishedEvent* UserEvent::unsafe_arena_release_syncfinishedevent() { + // @@protoc_insertion_point(field_unsafe_arena_release:grpc.UserEvent.syncFinishedEvent) + if (_internal_has_syncfinishedevent()) { + clear_has_event(); + ::grpc::SyncFinishedEvent* temp = _impl_.event_.syncfinishedevent_; + _impl_.event_.syncfinishedevent_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void UserEvent::unsafe_arena_set_allocated_syncfinishedevent(::grpc::SyncFinishedEvent* syncfinishedevent) { + clear_event(); + if (syncfinishedevent) { + set_has_syncfinishedevent(); + _impl_.event_.syncfinishedevent_ = syncfinishedevent; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:grpc.UserEvent.syncFinishedEvent) +} +inline ::grpc::SyncFinishedEvent* UserEvent::_internal_mutable_syncfinishedevent() { + if (!_internal_has_syncfinishedevent()) { + clear_event(); + set_has_syncfinishedevent(); + _impl_.event_.syncfinishedevent_ = CreateMaybeMessage< ::grpc::SyncFinishedEvent >(GetArenaForAllocation()); + } + return _impl_.event_.syncfinishedevent_; +} +inline ::grpc::SyncFinishedEvent* UserEvent::mutable_syncfinishedevent() { + ::grpc::SyncFinishedEvent* _msg = _internal_mutable_syncfinishedevent(); + // @@protoc_insertion_point(field_mutable:grpc.UserEvent.syncFinishedEvent) + return _msg; +} + +// .grpc.SyncProgressEvent syncProgressEvent = 9; +inline bool UserEvent::_internal_has_syncprogressevent() const { + return event_case() == kSyncProgressEvent; +} +inline bool UserEvent::has_syncprogressevent() const { + return _internal_has_syncprogressevent(); +} +inline void UserEvent::set_has_syncprogressevent() { + _impl_._oneof_case_[0] = kSyncProgressEvent; +} +inline void UserEvent::clear_syncprogressevent() { + if (_internal_has_syncprogressevent()) { + if (GetArenaForAllocation() == nullptr) { + delete _impl_.event_.syncprogressevent_; + } + clear_has_event(); + } +} +inline ::grpc::SyncProgressEvent* UserEvent::release_syncprogressevent() { + // @@protoc_insertion_point(field_release:grpc.UserEvent.syncProgressEvent) + if (_internal_has_syncprogressevent()) { + clear_has_event(); + ::grpc::SyncProgressEvent* temp = _impl_.event_.syncprogressevent_; + if (GetArenaForAllocation() != nullptr) { + temp = ::PROTOBUF_NAMESPACE_ID::internal::DuplicateIfNonNull(temp); + } + _impl_.event_.syncprogressevent_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline const ::grpc::SyncProgressEvent& UserEvent::_internal_syncprogressevent() const { + return _internal_has_syncprogressevent() + ? *_impl_.event_.syncprogressevent_ + : reinterpret_cast< ::grpc::SyncProgressEvent&>(::grpc::_SyncProgressEvent_default_instance_); +} +inline const ::grpc::SyncProgressEvent& UserEvent::syncprogressevent() const { + // @@protoc_insertion_point(field_get:grpc.UserEvent.syncProgressEvent) + return _internal_syncprogressevent(); +} +inline ::grpc::SyncProgressEvent* UserEvent::unsafe_arena_release_syncprogressevent() { + // @@protoc_insertion_point(field_unsafe_arena_release:grpc.UserEvent.syncProgressEvent) + if (_internal_has_syncprogressevent()) { + clear_has_event(); + ::grpc::SyncProgressEvent* temp = _impl_.event_.syncprogressevent_; + _impl_.event_.syncprogressevent_ = nullptr; + return temp; + } else { + return nullptr; + } +} +inline void UserEvent::unsafe_arena_set_allocated_syncprogressevent(::grpc::SyncProgressEvent* syncprogressevent) { + clear_event(); + if (syncprogressevent) { + set_has_syncprogressevent(); + _impl_.event_.syncprogressevent_ = syncprogressevent; + } + // @@protoc_insertion_point(field_unsafe_arena_set_allocated:grpc.UserEvent.syncProgressEvent) +} +inline ::grpc::SyncProgressEvent* UserEvent::_internal_mutable_syncprogressevent() { + if (!_internal_has_syncprogressevent()) { + clear_event(); + set_has_syncprogressevent(); + _impl_.event_.syncprogressevent_ = CreateMaybeMessage< ::grpc::SyncProgressEvent >(GetArenaForAllocation()); + } + return _impl_.event_.syncprogressevent_; +} +inline ::grpc::SyncProgressEvent* UserEvent::mutable_syncprogressevent() { + ::grpc::SyncProgressEvent* _msg = _internal_mutable_syncprogressevent(); + // @@protoc_insertion_point(field_mutable:grpc.UserEvent.syncProgressEvent) + return _msg; +} + inline bool UserEvent::has_event() const { return event_case() != EVENT_NOT_SET; } @@ -16650,6 +17442,228 @@ inline void ImapLoginFailedEvent::set_allocated_username(std::string* username) // ------------------------------------------------------------------- +// SyncStartedEvent + +// string userID = 1; +inline void SyncStartedEvent::clear_userid() { + _impl_.userid_.ClearToEmpty(); +} +inline const std::string& SyncStartedEvent::userid() const { + // @@protoc_insertion_point(field_get:grpc.SyncStartedEvent.userID) + return _internal_userid(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void SyncStartedEvent::set_userid(ArgT0&& arg0, ArgT... args) { + + _impl_.userid_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:grpc.SyncStartedEvent.userID) +} +inline std::string* SyncStartedEvent::mutable_userid() { + std::string* _s = _internal_mutable_userid(); + // @@protoc_insertion_point(field_mutable:grpc.SyncStartedEvent.userID) + return _s; +} +inline const std::string& SyncStartedEvent::_internal_userid() const { + return _impl_.userid_.Get(); +} +inline void SyncStartedEvent::_internal_set_userid(const std::string& value) { + + _impl_.userid_.Set(value, GetArenaForAllocation()); +} +inline std::string* SyncStartedEvent::_internal_mutable_userid() { + + return _impl_.userid_.Mutable(GetArenaForAllocation()); +} +inline std::string* SyncStartedEvent::release_userid() { + // @@protoc_insertion_point(field_release:grpc.SyncStartedEvent.userID) + return _impl_.userid_.Release(); +} +inline void SyncStartedEvent::set_allocated_userid(std::string* userid) { + if (userid != nullptr) { + + } else { + + } + _impl_.userid_.SetAllocated(userid, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.userid_.IsDefault()) { + _impl_.userid_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:grpc.SyncStartedEvent.userID) +} + +// ------------------------------------------------------------------- + +// SyncFinishedEvent + +// string userID = 1; +inline void SyncFinishedEvent::clear_userid() { + _impl_.userid_.ClearToEmpty(); +} +inline const std::string& SyncFinishedEvent::userid() const { + // @@protoc_insertion_point(field_get:grpc.SyncFinishedEvent.userID) + return _internal_userid(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void SyncFinishedEvent::set_userid(ArgT0&& arg0, ArgT... args) { + + _impl_.userid_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:grpc.SyncFinishedEvent.userID) +} +inline std::string* SyncFinishedEvent::mutable_userid() { + std::string* _s = _internal_mutable_userid(); + // @@protoc_insertion_point(field_mutable:grpc.SyncFinishedEvent.userID) + return _s; +} +inline const std::string& SyncFinishedEvent::_internal_userid() const { + return _impl_.userid_.Get(); +} +inline void SyncFinishedEvent::_internal_set_userid(const std::string& value) { + + _impl_.userid_.Set(value, GetArenaForAllocation()); +} +inline std::string* SyncFinishedEvent::_internal_mutable_userid() { + + return _impl_.userid_.Mutable(GetArenaForAllocation()); +} +inline std::string* SyncFinishedEvent::release_userid() { + // @@protoc_insertion_point(field_release:grpc.SyncFinishedEvent.userID) + return _impl_.userid_.Release(); +} +inline void SyncFinishedEvent::set_allocated_userid(std::string* userid) { + if (userid != nullptr) { + + } else { + + } + _impl_.userid_.SetAllocated(userid, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.userid_.IsDefault()) { + _impl_.userid_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:grpc.SyncFinishedEvent.userID) +} + +// ------------------------------------------------------------------- + +// SyncProgressEvent + +// string userID = 1; +inline void SyncProgressEvent::clear_userid() { + _impl_.userid_.ClearToEmpty(); +} +inline const std::string& SyncProgressEvent::userid() const { + // @@protoc_insertion_point(field_get:grpc.SyncProgressEvent.userID) + return _internal_userid(); +} +template +inline PROTOBUF_ALWAYS_INLINE +void SyncProgressEvent::set_userid(ArgT0&& arg0, ArgT... args) { + + _impl_.userid_.Set(static_cast(arg0), args..., GetArenaForAllocation()); + // @@protoc_insertion_point(field_set:grpc.SyncProgressEvent.userID) +} +inline std::string* SyncProgressEvent::mutable_userid() { + std::string* _s = _internal_mutable_userid(); + // @@protoc_insertion_point(field_mutable:grpc.SyncProgressEvent.userID) + return _s; +} +inline const std::string& SyncProgressEvent::_internal_userid() const { + return _impl_.userid_.Get(); +} +inline void SyncProgressEvent::_internal_set_userid(const std::string& value) { + + _impl_.userid_.Set(value, GetArenaForAllocation()); +} +inline std::string* SyncProgressEvent::_internal_mutable_userid() { + + return _impl_.userid_.Mutable(GetArenaForAllocation()); +} +inline std::string* SyncProgressEvent::release_userid() { + // @@protoc_insertion_point(field_release:grpc.SyncProgressEvent.userID) + return _impl_.userid_.Release(); +} +inline void SyncProgressEvent::set_allocated_userid(std::string* userid) { + if (userid != nullptr) { + + } else { + + } + _impl_.userid_.SetAllocated(userid, GetArenaForAllocation()); +#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING + if (_impl_.userid_.IsDefault()) { + _impl_.userid_.Set("", GetArenaForAllocation()); + } +#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING + // @@protoc_insertion_point(field_set_allocated:grpc.SyncProgressEvent.userID) +} + +// double progress = 2; +inline void SyncProgressEvent::clear_progress() { + _impl_.progress_ = 0; +} +inline double SyncProgressEvent::_internal_progress() const { + return _impl_.progress_; +} +inline double SyncProgressEvent::progress() const { + // @@protoc_insertion_point(field_get:grpc.SyncProgressEvent.progress) + return _internal_progress(); +} +inline void SyncProgressEvent::_internal_set_progress(double value) { + + _impl_.progress_ = value; +} +inline void SyncProgressEvent::set_progress(double value) { + _internal_set_progress(value); + // @@protoc_insertion_point(field_set:grpc.SyncProgressEvent.progress) +} + +// int64 elapsedMs = 3; +inline void SyncProgressEvent::clear_elapsedms() { + _impl_.elapsedms_ = int64_t{0}; +} +inline int64_t SyncProgressEvent::_internal_elapsedms() const { + return _impl_.elapsedms_; +} +inline int64_t SyncProgressEvent::elapsedms() const { + // @@protoc_insertion_point(field_get:grpc.SyncProgressEvent.elapsedMs) + return _internal_elapsedms(); +} +inline void SyncProgressEvent::_internal_set_elapsedms(int64_t value) { + + _impl_.elapsedms_ = value; +} +inline void SyncProgressEvent::set_elapsedms(int64_t value) { + _internal_set_elapsedms(value); + // @@protoc_insertion_point(field_set:grpc.SyncProgressEvent.elapsedMs) +} + +// int64 remainingMs = 4; +inline void SyncProgressEvent::clear_remainingms() { + _impl_.remainingms_ = int64_t{0}; +} +inline int64_t SyncProgressEvent::_internal_remainingms() const { + return _impl_.remainingms_; +} +inline int64_t SyncProgressEvent::remainingms() const { + // @@protoc_insertion_point(field_get:grpc.SyncProgressEvent.remainingMs) + return _internal_remainingms(); +} +inline void SyncProgressEvent::_internal_set_remainingms(int64_t value) { + + _impl_.remainingms_ = value; +} +inline void SyncProgressEvent::set_remainingms(int64_t value) { + _internal_set_remainingms(value); + // @@protoc_insertion_point(field_set:grpc.SyncProgressEvent.remainingMs) +} + +// ------------------------------------------------------------------- + // GenericErrorEvent // .grpc.ErrorCode code = 1; @@ -16793,6 +17807,12 @@ inline void GenericErrorEvent::set_code(::grpc::ErrorCode value) { // ------------------------------------------------------------------- +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + +// ------------------------------------------------------------------- + // @@protoc_insertion_point(namespace_scope) diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.cpp index dc6a1ec1..041a4d12 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.cpp @@ -294,6 +294,48 @@ void User::setTotalBytes(float totalBytes) { } +//**************************************************************************************************************************************************** +/// \return true iff a sync is in progress. +//**************************************************************************************************************************************************** +bool User::isSyncing() const { + return isSyncing_; +} + + +//**************************************************************************************************************************************************** +/// \param[in] syncing The new value for the sync state. +//**************************************************************************************************************************************************** +void User::setIsSyncing(bool syncing) { + if (isSyncing_ == syncing) { + return; + } + + isSyncing_ = syncing; + emit isSyncingChanged(syncing); +} + + +//**************************************************************************************************************************************************** +/// \return The sync progress ratio +//**************************************************************************************************************************************************** +float User::syncProgress() const { + return syncProgress_; +} + + +//**************************************************************************************************************************************************** +/// \param[in] progress The progress ratio. +//**************************************************************************************************************************************************** +void User::setSyncProgress(float progress) { + if (qAbs(syncProgress_ - progress) < 0.00001) { + return; + } + + syncProgress_ = progress; + emit syncProgressChanged(progress); +} + + //**************************************************************************************************************************************************** /// \param[in] state The user state. /// \return A string describing the state. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h index 28f4c05b..78cfe8c9 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/User/User.h @@ -101,6 +101,8 @@ public: Q_PROPERTY(bool splitMode READ splitMode WRITE setSplitMode NOTIFY splitModeChanged) Q_PROPERTY(float usedBytes READ usedBytes WRITE setUsedBytes NOTIFY usedBytesChanged) Q_PROPERTY(float totalBytes READ totalBytes WRITE setTotalBytes NOTIFY totalBytesChanged) + Q_PROPERTY(bool isSyncing READ isSyncing WRITE setIsSyncing NOTIFY isSyncingChanged) + Q_PROPERTY(float syncProgress READ syncProgress WRITE setSyncProgress NOTIFY syncProgressChanged) QString id() const; void setID(QString const &id); @@ -120,6 +122,10 @@ public: void setUsedBytes(float usedBytes); float totalBytes() const; void setTotalBytes(float totalBytes); + bool isSyncing() const; + void setIsSyncing(bool syncing); + float syncProgress() const; + void setSyncProgress(float progress); signals: // signals used for Qt properties @@ -134,6 +140,8 @@ signals: void usedBytesChanged(float byteCount); void totalBytesChanged(float byteCount); void toggleSplitModeFinished(); + void isSyncingChanged(bool syncing); + void syncProgressChanged(float syncProgress); private: // member functions. User(QObject *parent); ///< Default constructor. @@ -149,6 +157,8 @@ private: // data members. bool splitMode_ { false }; ///< Is split mode active. float usedBytes_ { 0.0f }; ///< The storage used by the user. float totalBytes_ { 1.0f }; ///< The storage quota of the user. + bool isSyncing_ { false }; ///< Is a sync in progress for the user. + float syncProgress_ { 0.0f }; ///< The sync progress. }; diff --git a/internal/frontend/grpc/bridge.pb.go b/internal/frontend/grpc/bridge.pb.go index a9998433..020b4b7e 100644 --- a/internal/frontend/grpc/bridge.pb.go +++ b/internal/frontend/grpc/bridge.pb.go @@ -3564,6 +3564,9 @@ type UserEvent struct { // *UserEvent_UserBadEvent // *UserEvent_UsedBytesChangedEvent // *UserEvent_ImapLoginFailedEvent + // *UserEvent_SyncStartedEvent + // *UserEvent_SyncFinishedEvent + // *UserEvent_SyncProgressEvent Event isUserEvent_Event `protobuf_oneof:"event"` } @@ -3648,6 +3651,27 @@ func (x *UserEvent) GetImapLoginFailedEvent() *ImapLoginFailedEvent { return nil } +func (x *UserEvent) GetSyncStartedEvent() *SyncStartedEvent { + if x, ok := x.GetEvent().(*UserEvent_SyncStartedEvent); ok { + return x.SyncStartedEvent + } + return nil +} + +func (x *UserEvent) GetSyncFinishedEvent() *SyncFinishedEvent { + if x, ok := x.GetEvent().(*UserEvent_SyncFinishedEvent); ok { + return x.SyncFinishedEvent + } + return nil +} + +func (x *UserEvent) GetSyncProgressEvent() *SyncProgressEvent { + if x, ok := x.GetEvent().(*UserEvent_SyncProgressEvent); ok { + return x.SyncProgressEvent + } + return nil +} + type isUserEvent_Event interface { isUserEvent_Event() } @@ -3676,6 +3700,18 @@ type UserEvent_ImapLoginFailedEvent struct { ImapLoginFailedEvent *ImapLoginFailedEvent `protobuf:"bytes,6,opt,name=imapLoginFailedEvent,proto3,oneof"` } +type UserEvent_SyncStartedEvent struct { + SyncStartedEvent *SyncStartedEvent `protobuf:"bytes,7,opt,name=syncStartedEvent,proto3,oneof"` +} + +type UserEvent_SyncFinishedEvent struct { + SyncFinishedEvent *SyncFinishedEvent `protobuf:"bytes,8,opt,name=syncFinishedEvent,proto3,oneof"` +} + +type UserEvent_SyncProgressEvent struct { + SyncProgressEvent *SyncProgressEvent `protobuf:"bytes,9,opt,name=syncProgressEvent,proto3,oneof"` +} + func (*UserEvent_ToggleSplitModeFinished) isUserEvent_Event() {} func (*UserEvent_UserDisconnected) isUserEvent_Event() {} @@ -3688,6 +3724,12 @@ func (*UserEvent_UsedBytesChangedEvent) isUserEvent_Event() {} func (*UserEvent_ImapLoginFailedEvent) isUserEvent_Event() {} +func (*UserEvent_SyncStartedEvent) isUserEvent_Event() {} + +func (*UserEvent_SyncFinishedEvent) isUserEvent_Event() {} + +func (*UserEvent_SyncProgressEvent) isUserEvent_Event() {} + type ToggleSplitModeFinishedEvent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3986,6 +4028,171 @@ func (x *ImapLoginFailedEvent) GetUsername() string { return "" } +type SyncStartedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` +} + +func (x *SyncStartedEvent) Reset() { + *x = SyncStartedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_bridge_proto_msgTypes[59] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SyncStartedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SyncStartedEvent) ProtoMessage() {} + +func (x *SyncStartedEvent) ProtoReflect() protoreflect.Message { + mi := &file_bridge_proto_msgTypes[59] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SyncStartedEvent.ProtoReflect.Descriptor instead. +func (*SyncStartedEvent) Descriptor() ([]byte, []int) { + return file_bridge_proto_rawDescGZIP(), []int{59} +} + +func (x *SyncStartedEvent) GetUserID() string { + if x != nil { + return x.UserID + } + return "" +} + +type SyncFinishedEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` +} + +func (x *SyncFinishedEvent) Reset() { + *x = SyncFinishedEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_bridge_proto_msgTypes[60] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SyncFinishedEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SyncFinishedEvent) ProtoMessage() {} + +func (x *SyncFinishedEvent) ProtoReflect() protoreflect.Message { + mi := &file_bridge_proto_msgTypes[60] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SyncFinishedEvent.ProtoReflect.Descriptor instead. +func (*SyncFinishedEvent) Descriptor() ([]byte, []int) { + return file_bridge_proto_rawDescGZIP(), []int{60} +} + +func (x *SyncFinishedEvent) GetUserID() string { + if x != nil { + return x.UserID + } + return "" +} + +type SyncProgressEvent struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + UserID string `protobuf:"bytes,1,opt,name=userID,proto3" json:"userID,omitempty"` + Progress float64 `protobuf:"fixed64,2,opt,name=progress,proto3" json:"progress,omitempty"` + ElapsedMs int64 `protobuf:"varint,3,opt,name=elapsedMs,proto3" json:"elapsedMs,omitempty"` + RemainingMs int64 `protobuf:"varint,4,opt,name=remainingMs,proto3" json:"remainingMs,omitempty"` +} + +func (x *SyncProgressEvent) Reset() { + *x = SyncProgressEvent{} + if protoimpl.UnsafeEnabled { + mi := &file_bridge_proto_msgTypes[61] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SyncProgressEvent) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SyncProgressEvent) ProtoMessage() {} + +func (x *SyncProgressEvent) ProtoReflect() protoreflect.Message { + mi := &file_bridge_proto_msgTypes[61] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SyncProgressEvent.ProtoReflect.Descriptor instead. +func (*SyncProgressEvent) Descriptor() ([]byte, []int) { + return file_bridge_proto_rawDescGZIP(), []int{61} +} + +func (x *SyncProgressEvent) GetUserID() string { + if x != nil { + return x.UserID + } + return "" +} + +func (x *SyncProgressEvent) GetProgress() float64 { + if x != nil { + return x.Progress + } + return 0 +} + +func (x *SyncProgressEvent) GetElapsedMs() int64 { + if x != nil { + return x.ElapsedMs + } + return 0 +} + +func (x *SyncProgressEvent) GetRemainingMs() int64 { + if x != nil { + return x.RemainingMs + } + return 0 +} + type GenericErrorEvent struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3997,7 +4204,7 @@ type GenericErrorEvent struct { func (x *GenericErrorEvent) Reset() { *x = GenericErrorEvent{} if protoimpl.UnsafeEnabled { - mi := &file_bridge_proto_msgTypes[59] + mi := &file_bridge_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4010,7 +4217,7 @@ func (x *GenericErrorEvent) String() string { func (*GenericErrorEvent) ProtoMessage() {} func (x *GenericErrorEvent) ProtoReflect() protoreflect.Message { - mi := &file_bridge_proto_msgTypes[59] + mi := &file_bridge_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4023,7 +4230,7 @@ func (x *GenericErrorEvent) ProtoReflect() protoreflect.Message { // Deprecated: Use GenericErrorEvent.ProtoReflect.Descriptor instead. func (*GenericErrorEvent) Descriptor() ([]byte, []int) { - return file_bridge_proto_rawDescGZIP(), []int{59} + return file_bridge_proto_rawDescGZIP(), []int{62} } func (x *GenericErrorEvent) GetCode() ErrorCode { @@ -4400,7 +4607,7 @@ var file_bridge_proto_rawDesc = []byte{ 0x74, 0x12, 0x18, 0x0a, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x22, 0x13, 0x0a, 0x11, 0x41, 0x70, 0x69, 0x43, 0x65, 0x72, 0x74, 0x49, 0x73, 0x73, 0x75, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x22, 0xdc, 0x03, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x5e, + 0x22, 0xb4, 0x05, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x5e, 0x0a, 0x17, 0x74, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x70, 0x6c, @@ -4429,320 +4636,348 @@ var file_bridge_proto_rawDesc = []byte{ 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x14, 0x69, 0x6d, 0x61, 0x70, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, - 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, - 0x36, 0x0a, 0x1c, 0x54, 0x6f, 0x67, 0x67, 0x6c, 0x65, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, - 0x64, 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, - 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x33, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, 0x44, - 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2a, 0x0a, 0x10, - 0x55, 0x73, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x4a, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, - 0x42, 0x61, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, + 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x44, 0x0a, 0x10, 0x73, 0x79, 0x6e, 0x63, 0x53, 0x74, + 0x61, 0x72, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x72, + 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x10, 0x73, 0x79, 0x6e, 0x63, + 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x11, + 0x73, 0x79, 0x6e, 0x63, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, + 0x79, 0x6e, 0x63, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x48, 0x00, 0x52, 0x11, 0x73, 0x79, 0x6e, 0x63, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x47, 0x0a, 0x11, 0x73, 0x79, 0x6e, 0x63, 0x50, 0x72, 0x6f, + 0x67, 0x72, 0x65, 0x73, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x09, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x79, 0x6e, 0x63, 0x50, 0x72, 0x6f, 0x67, + 0x72, 0x65, 0x73, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x48, 0x00, 0x52, 0x11, 0x73, 0x79, 0x6e, + 0x63, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x42, 0x07, + 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x22, 0x36, 0x0a, 0x1c, 0x54, 0x6f, 0x67, 0x67, 0x6c, + 0x65, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, + 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, + 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, + 0x33, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x72, 0x44, 0x69, 0x73, 0x63, 0x6f, 0x6e, 0x6e, 0x65, 0x63, + 0x74, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x2a, 0x0a, 0x10, 0x55, 0x73, 0x65, 0x72, 0x43, 0x68, 0x61, 0x6e, + 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, - 0x12, 0x22, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x22, 0x4d, 0x0a, 0x15, 0x55, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, - 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, - 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, - 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1c, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, - 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, - 0x74, 0x65, 0x73, 0x22, 0x32, 0x0a, 0x14, 0x49, 0x6d, 0x61, 0x70, 0x4c, 0x6f, 0x67, 0x69, 0x6e, - 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, - 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, - 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, 0x38, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, - 0x69, 0x63, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x04, - 0x63, 0x6f, 0x64, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, - 0x65, 0x2a, 0x71, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x0d, 0x0a, - 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x50, 0x41, 0x4e, 0x49, 0x43, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, - 0x4c, 0x4f, 0x47, 0x5f, 0x46, 0x41, 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, - 0x4f, 0x47, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, - 0x47, 0x5f, 0x57, 0x41, 0x52, 0x4e, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x47, 0x5f, - 0x49, 0x4e, 0x46, 0x4f, 0x10, 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x44, 0x45, - 0x42, 0x55, 0x47, 0x10, 0x05, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x54, 0x52, 0x41, - 0x43, 0x45, 0x10, 0x06, 0x2a, 0x36, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, - 0x65, 0x12, 0x0e, 0x0a, 0x0a, 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x4f, 0x55, 0x54, 0x10, - 0x00, 0x12, 0x0a, 0x0a, 0x06, 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, - 0x09, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xa2, 0x01, 0x0a, - 0x0e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x1b, 0x0a, 0x17, 0x55, 0x53, 0x45, 0x52, 0x4e, 0x41, 0x4d, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, - 0x57, 0x4f, 0x52, 0x44, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, - 0x46, 0x52, 0x45, 0x45, 0x5f, 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x43, - 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, - 0x02, 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x46, 0x41, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, - 0x12, 0x0d, 0x0a, 0x09, 0x54, 0x46, 0x41, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x04, 0x12, - 0x17, 0x0a, 0x13, 0x54, 0x57, 0x4f, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x53, - 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x57, 0x4f, 0x5f, - 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x53, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, - 0x06, 0x2a, 0x5b, 0x0a, 0x0f, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4d, - 0x41, 0x4e, 0x55, 0x41, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x16, 0x0a, - 0x12, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, - 0x53, 0x49, 0x4c, 0x45, 0x4e, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0x6b, - 0x0a, 0x12, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x1c, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, - 0x48, 0x45, 0x5f, 0x55, 0x4e, 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x43, 0x41, 0x4e, 0x54, 0x5f, 0x4d, - 0x4f, 0x56, 0x45, 0x5f, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x5f, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x46, - 0x55, 0x4c, 0x4c, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0xdd, 0x01, 0x0a, 0x1b, - 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x49, - 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, - 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4d, 0x54, 0x50, - 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, 0x5f, 0x45, 0x52, - 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, - 0x52, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, - 0x02, 0x12, 0x1a, 0x0a, 0x16, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x43, - 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x25, 0x0a, - 0x21, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, - 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, - 0x4f, 0x52, 0x10, 0x04, 0x12, 0x25, 0x0a, 0x21, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x43, 0x4f, 0x4e, - 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x48, 0x41, - 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x2a, 0x53, 0x0a, 0x09, 0x45, - 0x72, 0x72, 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x4e, 0x4b, 0x4e, - 0x4f, 0x57, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x54, - 0x4c, 0x53, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, - 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x4c, 0x53, 0x5f, 0x4b, 0x45, - 0x59, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, - 0x32, 0xdb, 0x1c, 0x0a, 0x06, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x43, - 0x68, 0x65, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4c, 0x6f, 0x67, - 0x45, 0x6e, 0x74, 0x72, 0x79, 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, - 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x08, 0x47, 0x75, 0x69, 0x52, 0x65, - 0x61, 0x64, 0x79, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x47, 0x75, 0x69, 0x52, 0x65, 0x61, 0x64, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x65, 0x12, 0x36, 0x0a, 0x04, 0x51, 0x75, 0x69, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x07, 0x52, - 0x65, 0x73, 0x74, 0x61, 0x72, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x22, 0x4a, 0x0a, 0x0c, 0x55, 0x73, 0x65, 0x72, 0x42, 0x61, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x22, 0x0a, 0x0c, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x4d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x22, 0x4d, 0x0a, 0x15, + 0x55, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x43, 0x68, 0x61, 0x6e, 0x67, 0x65, 0x64, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1c, 0x0a, + 0x09, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x09, 0x75, 0x73, 0x65, 0x64, 0x42, 0x79, 0x74, 0x65, 0x73, 0x22, 0x32, 0x0a, 0x14, 0x49, + 0x6d, 0x61, 0x70, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x46, 0x61, 0x69, 0x6c, 0x65, 0x64, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x22, + 0x2a, 0x0a, 0x10, 0x53, 0x79, 0x6e, 0x63, 0x53, 0x74, 0x61, 0x72, 0x74, 0x65, 0x64, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x2b, 0x0a, 0x11, 0x53, + 0x79, 0x6e, 0x63, 0x46, 0x69, 0x6e, 0x69, 0x73, 0x68, 0x65, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x16, 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x22, 0x87, 0x01, 0x0a, 0x11, 0x53, 0x79, 0x6e, + 0x63, 0x50, 0x72, 0x6f, 0x67, 0x72, 0x65, 0x73, 0x73, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, + 0x0a, 0x06, 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x75, 0x73, 0x65, 0x72, 0x49, 0x44, 0x12, 0x1a, 0x0a, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x70, 0x72, 0x6f, 0x67, 0x72, 0x65, + 0x73, 0x73, 0x12, 0x1c, 0x0a, 0x09, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x4d, 0x73, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x65, 0x6c, 0x61, 0x70, 0x73, 0x65, 0x64, 0x4d, 0x73, + 0x12, 0x20, 0x0a, 0x0b, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, 0x4d, 0x73, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0b, 0x72, 0x65, 0x6d, 0x61, 0x69, 0x6e, 0x69, 0x6e, 0x67, + 0x4d, 0x73, 0x22, 0x38, 0x0a, 0x11, 0x47, 0x65, 0x6e, 0x65, 0x72, 0x69, 0x63, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x0f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x43, 0x6f, 0x64, 0x65, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x2a, 0x71, 0x0a, 0x08, + 0x4c, 0x6f, 0x67, 0x4c, 0x65, 0x76, 0x65, 0x6c, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, + 0x50, 0x41, 0x4e, 0x49, 0x43, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x46, + 0x41, 0x54, 0x41, 0x4c, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x45, 0x52, + 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x47, 0x5f, 0x57, 0x41, 0x52, + 0x4e, 0x10, 0x03, 0x12, 0x0c, 0x0a, 0x08, 0x4c, 0x4f, 0x47, 0x5f, 0x49, 0x4e, 0x46, 0x4f, 0x10, + 0x04, 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x44, 0x45, 0x42, 0x55, 0x47, 0x10, 0x05, + 0x12, 0x0d, 0x0a, 0x09, 0x4c, 0x4f, 0x47, 0x5f, 0x54, 0x52, 0x41, 0x43, 0x45, 0x10, 0x06, 0x2a, + 0x36, 0x0a, 0x09, 0x55, 0x73, 0x65, 0x72, 0x53, 0x74, 0x61, 0x74, 0x65, 0x12, 0x0e, 0x0a, 0x0a, + 0x53, 0x49, 0x47, 0x4e, 0x45, 0x44, 0x5f, 0x4f, 0x55, 0x54, 0x10, 0x00, 0x12, 0x0a, 0x0a, 0x06, + 0x4c, 0x4f, 0x43, 0x4b, 0x45, 0x44, 0x10, 0x01, 0x12, 0x0d, 0x0a, 0x09, 0x43, 0x4f, 0x4e, 0x4e, + 0x45, 0x43, 0x54, 0x45, 0x44, 0x10, 0x02, 0x2a, 0xa2, 0x01, 0x0a, 0x0e, 0x4c, 0x6f, 0x67, 0x69, + 0x6e, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x55, 0x53, + 0x45, 0x52, 0x4e, 0x41, 0x4d, 0x45, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x5f, + 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x0d, 0x0a, 0x09, 0x46, 0x52, 0x45, 0x45, 0x5f, + 0x55, 0x53, 0x45, 0x52, 0x10, 0x01, 0x12, 0x14, 0x0a, 0x10, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, + 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x0d, 0x0a, 0x09, + 0x54, 0x46, 0x41, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x0d, 0x0a, 0x09, 0x54, + 0x46, 0x41, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x04, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x57, + 0x4f, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, 0x4f, 0x52, 0x44, 0x53, 0x5f, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x10, 0x05, 0x12, 0x17, 0x0a, 0x13, 0x54, 0x57, 0x4f, 0x5f, 0x50, 0x41, 0x53, 0x53, 0x57, + 0x4f, 0x52, 0x44, 0x53, 0x5f, 0x41, 0x42, 0x4f, 0x52, 0x54, 0x10, 0x06, 0x2a, 0x5b, 0x0a, 0x0f, + 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x4d, 0x41, 0x4e, 0x55, 0x41, 0x4c, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x16, 0x0a, 0x12, 0x55, 0x50, 0x44, 0x41, + 0x54, 0x45, 0x5f, 0x46, 0x4f, 0x52, 0x43, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, + 0x12, 0x17, 0x0a, 0x13, 0x55, 0x50, 0x44, 0x41, 0x54, 0x45, 0x5f, 0x53, 0x49, 0x4c, 0x45, 0x4e, + 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0x6b, 0x0a, 0x12, 0x44, 0x69, 0x73, + 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, + 0x20, 0x0a, 0x1c, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x5f, 0x55, 0x4e, + 0x41, 0x56, 0x41, 0x49, 0x4c, 0x41, 0x42, 0x4c, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, + 0x00, 0x12, 0x1e, 0x0a, 0x1a, 0x43, 0x41, 0x4e, 0x54, 0x5f, 0x4d, 0x4f, 0x56, 0x45, 0x5f, 0x44, + 0x49, 0x53, 0x4b, 0x5f, 0x43, 0x41, 0x43, 0x48, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, + 0x01, 0x12, 0x13, 0x0a, 0x0f, 0x44, 0x49, 0x53, 0x4b, 0x5f, 0x46, 0x55, 0x4c, 0x4c, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x2a, 0xdd, 0x01, 0x0a, 0x1b, 0x4d, 0x61, 0x69, 0x6c, 0x53, + 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x45, 0x72, 0x72, + 0x6f, 0x72, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1b, 0x0a, 0x17, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x50, + 0x4f, 0x52, 0x54, 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, + 0x52, 0x10, 0x00, 0x12, 0x1b, 0x0a, 0x17, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, + 0x5f, 0x53, 0x54, 0x41, 0x52, 0x54, 0x55, 0x50, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, + 0x12, 0x1a, 0x0a, 0x16, 0x49, 0x4d, 0x41, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x43, 0x48, + 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x12, 0x1a, 0x0a, 0x16, + 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, + 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x03, 0x12, 0x25, 0x0a, 0x21, 0x49, 0x4d, 0x41, 0x50, + 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, + 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x04, 0x12, + 0x25, 0x0a, 0x21, 0x53, 0x4d, 0x54, 0x50, 0x5f, 0x43, 0x4f, 0x4e, 0x4e, 0x45, 0x43, 0x54, 0x49, + 0x4f, 0x4e, 0x5f, 0x4d, 0x4f, 0x44, 0x45, 0x5f, 0x43, 0x48, 0x41, 0x4e, 0x47, 0x45, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x05, 0x2a, 0x53, 0x0a, 0x09, 0x45, 0x72, 0x72, 0x6f, 0x72, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x11, 0x0a, 0x0d, 0x55, 0x4e, 0x4b, 0x4e, 0x4f, 0x57, 0x4e, 0x5f, 0x45, + 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x45, + 0x52, 0x54, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, + 0x01, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x4c, 0x53, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x45, 0x58, 0x50, + 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x32, 0xdb, 0x1c, 0x0a, 0x06, + 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, + 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x3f, 0x0a, 0x0b, 0x41, 0x64, 0x64, 0x4c, 0x6f, 0x67, 0x45, 0x6e, 0x74, 0x72, 0x79, + 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x4c, 0x6f, 0x67, 0x45, 0x6e, + 0x74, 0x72, 0x79, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x3a, 0x0a, 0x08, 0x47, 0x75, 0x69, 0x52, 0x65, 0x61, 0x64, 0x79, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x47, 0x75, + 0x69, 0x52, 0x65, 0x61, 0x64, 0x79, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x36, + 0x0a, 0x04, 0x51, 0x75, 0x69, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x53, 0x68, 0x6f, 0x77, 0x4f, 0x6e, - 0x53, 0x74, 0x61, 0x72, 0x74, 0x75, 0x70, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, - 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x6e, 0x12, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x4f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, - 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x49, - 0x73, 0x42, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, - 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x43, 0x0a, 0x0d, 0x49, 0x73, 0x42, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, - 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x49, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x6c, - 0x6c, 0x4d, 0x61, 0x69, 0x6c, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, - 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x46, 0x0a, 0x10, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x4d, 0x61, 0x69, 0x6c, 0x56, 0x69, 0x73, - 0x69, 0x62, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, - 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x54, 0x72, 0x69, 0x67, - 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, - 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x4c, 0x6f, 0x67, - 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x0b, 0x4c, - 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, - 0x12, 0x4c, 0x0a, 0x14, 0x52, 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, - 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, - 0x0a, 0x16, 0x44, 0x65, 0x70, 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x63, 0x65, - 0x6e, 0x73, 0x65, 0x73, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x47, - 0x0a, 0x0f, 0x4c, 0x61, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, - 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x6f, - 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, - 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, - 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, - 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3b, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x6f, - 0x72, 0x74, 0x42, 0x75, 0x67, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x70, - 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4d, 0x0a, 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x54, - 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0d, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x75, - 0x6e, 0x63, 0x68, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x11, 0x53, - 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, - 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x33, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, - 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x4c, - 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x46, 0x41, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, - 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x50, 0x61, 0x73, - 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, - 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, - 0x12, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, - 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x3f, 0x0a, 0x0d, 0x49, 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x07, 0x52, 0x65, 0x73, 0x74, 0x61, 0x72, + 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x4c, 0x0a, 0x16, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, - 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, - 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x49, 0x0a, 0x13, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0d, 0x44, 0x69, - 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x48, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, - 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0f, 0x53, - 0x65, 0x74, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0c, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, - 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x53, 0x68, 0x6f, 0x77, 0x4f, 0x6e, 0x53, 0x74, 0x61, 0x72, 0x74, + 0x75, 0x70, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, - 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x44, 0x0a, 0x12, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, - 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, + 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, + 0x75, 0x74, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, + 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, + 0x0a, 0x0d, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x73, 0x74, 0x61, 0x72, 0x74, 0x4f, 0x6e, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x49, 0x73, 0x42, 0x65, 0x74, 0x61, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x43, 0x0a, 0x0d, 0x49, + 0x73, 0x42, 0x65, 0x74, 0x61, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, - 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x15, - 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, - 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, - 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x16, 0x2e, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x49, 0x0a, 0x13, 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x6c, 0x6c, 0x4d, 0x61, 0x69, 0x6c, + 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x46, 0x0a, 0x10, 0x49, + 0x73, 0x41, 0x6c, 0x6c, 0x4d, 0x61, 0x69, 0x6c, 0x56, 0x69, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, + 0x73, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x61, 0x74, 0x68, + 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, + 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4c, 0x0a, 0x14, 0x52, + 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x50, 0x61, 0x67, 0x65, 0x4c, + 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x16, 0x44, 0x65, 0x70, + 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x4c, + 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x47, 0x0a, 0x0f, 0x4c, 0x61, 0x6e, + 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, + 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, + 0x0a, 0x0f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x49, 0x73, 0x50, 0x6f, 0x72, - 0x74, 0x46, 0x72, 0x65, 0x65, 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, - 0x0a, 0x12, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, - 0x61, 0x69, 0x6e, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, - 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, - 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, - 0x68, 0x61, 0x69, 0x6e, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x75, - 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x43, 0x75, 0x72, 0x72, 0x65, + 0x6e, 0x74, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, - 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, - 0x73, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x0a, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x55, 0x73, - 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x6c, 0x75, 0x65, 0x12, 0x3b, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, + 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, + 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x4d, 0x0a, 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x42, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x6f, 0x75, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, - 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x51, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x66, 0x69, - 0x67, 0x75, 0x72, 0x65, 0x55, 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, - 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, - 0x72, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x75, - 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, - 0x72, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, - 0x74, 0x6f, 0x70, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, + 0x45, 0x0a, 0x0d, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x72, + 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x36, - 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x50, 0x72, 0x6f, - 0x74, 0x6f, 0x6e, 0x4d, 0x61, 0x69, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2d, 0x62, - 0x72, 0x69, 0x64, 0x67, 0x65, 0x2f, 0x76, 0x33, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, - 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, + 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x33, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, + 0x46, 0x41, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, + 0x0a, 0x0f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, + 0x73, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, + 0x0a, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x67, 0x72, + 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0b, + 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0d, 0x49, + 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4c, 0x0a, 0x16, + 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x13, 0x49, 0x73, + 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, + 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, + 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x48, 0x0a, 0x10, + 0x53, 0x65, 0x74, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, + 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x49, 0x73, 0x44, + 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, + 0x0c, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x44, 0x0a, 0x12, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, + 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x4d, 0x61, + 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, + 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, + 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x40, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x49, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x72, 0x65, 0x65, + 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x12, 0x41, 0x76, 0x61, + 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, + 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, + 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, + 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, + 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, + 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, + 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x0a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, + 0x65, 0x72, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, + 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, + 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x4c, 0x6f, + 0x67, 0x6f, 0x75, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, + 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, + 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x12, 0x51, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x55, + 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x2e, 0x67, + 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x41, 0x70, 0x70, + 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, + 0x74, 0x1a, 0x11, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x74, 0x6f, 0x70, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, + 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x4d, 0x61, + 0x69, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, + 0x2f, 0x76, 0x33, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x72, 0x70, + 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4758,7 +4993,7 @@ func file_bridge_proto_rawDescGZIP() []byte { } var file_bridge_proto_enumTypes = make([]protoimpl.EnumInfo, 7) -var file_bridge_proto_msgTypes = make([]protoimpl.MessageInfo, 60) +var file_bridge_proto_msgTypes = make([]protoimpl.MessageInfo, 63) var file_bridge_proto_goTypes = []interface{}{ (LogLevel)(0), // 0: grpc.LogLevel (UserState)(0), // 1: grpc.UserState @@ -4826,11 +5061,14 @@ var file_bridge_proto_goTypes = []interface{}{ (*UserBadEvent)(nil), // 63: grpc.UserBadEvent (*UsedBytesChangedEvent)(nil), // 64: grpc.UsedBytesChangedEvent (*ImapLoginFailedEvent)(nil), // 65: grpc.ImapLoginFailedEvent - (*GenericErrorEvent)(nil), // 66: grpc.GenericErrorEvent - (*wrapperspb.StringValue)(nil), // 67: google.protobuf.StringValue - (*emptypb.Empty)(nil), // 68: google.protobuf.Empty - (*wrapperspb.BoolValue)(nil), // 69: google.protobuf.BoolValue - (*wrapperspb.Int32Value)(nil), // 70: google.protobuf.Int32Value + (*SyncStartedEvent)(nil), // 66: grpc.SyncStartedEvent + (*SyncFinishedEvent)(nil), // 67: grpc.SyncFinishedEvent + (*SyncProgressEvent)(nil), // 68: grpc.SyncProgressEvent + (*GenericErrorEvent)(nil), // 69: grpc.GenericErrorEvent + (*wrapperspb.StringValue)(nil), // 70: google.protobuf.StringValue + (*emptypb.Empty)(nil), // 71: google.protobuf.Empty + (*wrapperspb.BoolValue)(nil), // 72: google.protobuf.BoolValue + (*wrapperspb.Int32Value)(nil), // 73: google.protobuf.Int32Value } var file_bridge_proto_depIdxs = []int32{ 0, // 0: grpc.AddLogEntryRequest.level:type_name -> grpc.LogLevel @@ -4844,7 +5082,7 @@ var file_bridge_proto_depIdxs = []int32{ 50, // 8: grpc.StreamEvent.keychain:type_name -> grpc.KeychainEvent 54, // 9: grpc.StreamEvent.mail:type_name -> grpc.MailEvent 59, // 10: grpc.StreamEvent.user:type_name -> grpc.UserEvent - 66, // 11: grpc.StreamEvent.genericError:type_name -> grpc.GenericErrorEvent + 69, // 11: grpc.StreamEvent.genericError:type_name -> grpc.GenericErrorEvent 21, // 12: grpc.AppEvent.internetStatus:type_name -> grpc.InternetStatusEvent 22, // 13: grpc.AppEvent.toggleAutostartFinished:type_name -> grpc.ToggleAutostartFinishedEvent 23, // 14: grpc.AppEvent.resetFinished:type_name -> grpc.ResetFinishedEvent @@ -4889,118 +5127,121 @@ var file_bridge_proto_depIdxs = []int32{ 63, // 53: grpc.UserEvent.userBadEvent:type_name -> grpc.UserBadEvent 64, // 54: grpc.UserEvent.usedBytesChangedEvent:type_name -> grpc.UsedBytesChangedEvent 65, // 55: grpc.UserEvent.imapLoginFailedEvent:type_name -> grpc.ImapLoginFailedEvent - 6, // 56: grpc.GenericErrorEvent.code:type_name -> grpc.ErrorCode - 67, // 57: grpc.Bridge.CheckTokens:input_type -> google.protobuf.StringValue - 7, // 58: grpc.Bridge.AddLogEntry:input_type -> grpc.AddLogEntryRequest - 68, // 59: grpc.Bridge.GuiReady:input_type -> google.protobuf.Empty - 68, // 60: grpc.Bridge.Quit:input_type -> google.protobuf.Empty - 68, // 61: grpc.Bridge.Restart:input_type -> google.protobuf.Empty - 68, // 62: grpc.Bridge.ShowOnStartup:input_type -> google.protobuf.Empty - 69, // 63: grpc.Bridge.SetIsAutostartOn:input_type -> google.protobuf.BoolValue - 68, // 64: grpc.Bridge.IsAutostartOn:input_type -> google.protobuf.Empty - 69, // 65: grpc.Bridge.SetIsBetaEnabled:input_type -> google.protobuf.BoolValue - 68, // 66: grpc.Bridge.IsBetaEnabled:input_type -> google.protobuf.Empty - 69, // 67: grpc.Bridge.SetIsAllMailVisible:input_type -> google.protobuf.BoolValue - 68, // 68: grpc.Bridge.IsAllMailVisible:input_type -> google.protobuf.Empty - 68, // 69: grpc.Bridge.TriggerReset:input_type -> google.protobuf.Empty - 68, // 70: grpc.Bridge.Version:input_type -> google.protobuf.Empty - 68, // 71: grpc.Bridge.LogsPath:input_type -> google.protobuf.Empty - 68, // 72: grpc.Bridge.LicensePath:input_type -> google.protobuf.Empty - 68, // 73: grpc.Bridge.ReleaseNotesPageLink:input_type -> google.protobuf.Empty - 68, // 74: grpc.Bridge.DependencyLicensesLink:input_type -> google.protobuf.Empty - 68, // 75: grpc.Bridge.LandingPageLink:input_type -> google.protobuf.Empty - 67, // 76: grpc.Bridge.SetColorSchemeName:input_type -> google.protobuf.StringValue - 68, // 77: grpc.Bridge.ColorSchemeName:input_type -> google.protobuf.Empty - 68, // 78: grpc.Bridge.CurrentEmailClient:input_type -> google.protobuf.Empty - 9, // 79: grpc.Bridge.ReportBug:input_type -> grpc.ReportBugRequest - 67, // 80: grpc.Bridge.ExportTLSCertificates:input_type -> google.protobuf.StringValue - 67, // 81: grpc.Bridge.ForceLauncher:input_type -> google.protobuf.StringValue - 67, // 82: grpc.Bridge.SetMainExecutable:input_type -> google.protobuf.StringValue - 10, // 83: grpc.Bridge.Login:input_type -> grpc.LoginRequest - 10, // 84: grpc.Bridge.Login2FA:input_type -> grpc.LoginRequest - 10, // 85: grpc.Bridge.Login2Passwords:input_type -> grpc.LoginRequest - 11, // 86: grpc.Bridge.LoginAbort:input_type -> grpc.LoginAbortRequest - 68, // 87: grpc.Bridge.CheckUpdate:input_type -> google.protobuf.Empty - 68, // 88: grpc.Bridge.InstallUpdate:input_type -> google.protobuf.Empty - 69, // 89: grpc.Bridge.SetIsAutomaticUpdateOn:input_type -> google.protobuf.BoolValue - 68, // 90: grpc.Bridge.IsAutomaticUpdateOn:input_type -> google.protobuf.Empty - 68, // 91: grpc.Bridge.DiskCachePath:input_type -> google.protobuf.Empty - 67, // 92: grpc.Bridge.SetDiskCachePath:input_type -> google.protobuf.StringValue - 69, // 93: grpc.Bridge.SetIsDoHEnabled:input_type -> google.protobuf.BoolValue - 68, // 94: grpc.Bridge.IsDoHEnabled:input_type -> google.protobuf.Empty - 68, // 95: grpc.Bridge.MailServerSettings:input_type -> google.protobuf.Empty - 12, // 96: grpc.Bridge.SetMailServerSettings:input_type -> grpc.ImapSmtpSettings - 68, // 97: grpc.Bridge.Hostname:input_type -> google.protobuf.Empty - 70, // 98: grpc.Bridge.IsPortFree:input_type -> google.protobuf.Int32Value - 68, // 99: grpc.Bridge.AvailableKeychains:input_type -> google.protobuf.Empty - 67, // 100: grpc.Bridge.SetCurrentKeychain:input_type -> google.protobuf.StringValue - 68, // 101: grpc.Bridge.CurrentKeychain:input_type -> google.protobuf.Empty - 68, // 102: grpc.Bridge.GetUserList:input_type -> google.protobuf.Empty - 67, // 103: grpc.Bridge.GetUser:input_type -> google.protobuf.StringValue - 15, // 104: grpc.Bridge.SetUserSplitMode:input_type -> grpc.UserSplitModeRequest - 67, // 105: grpc.Bridge.LogoutUser:input_type -> google.protobuf.StringValue - 67, // 106: grpc.Bridge.RemoveUser:input_type -> google.protobuf.StringValue - 17, // 107: grpc.Bridge.ConfigureUserAppleMail:input_type -> grpc.ConfigureAppleMailRequest - 18, // 108: grpc.Bridge.RunEventStream:input_type -> grpc.EventStreamRequest - 68, // 109: grpc.Bridge.StopEventStream:input_type -> google.protobuf.Empty - 67, // 110: grpc.Bridge.CheckTokens:output_type -> google.protobuf.StringValue - 68, // 111: grpc.Bridge.AddLogEntry:output_type -> google.protobuf.Empty - 8, // 112: grpc.Bridge.GuiReady:output_type -> grpc.GuiReadyResponse - 68, // 113: grpc.Bridge.Quit:output_type -> google.protobuf.Empty - 68, // 114: grpc.Bridge.Restart:output_type -> google.protobuf.Empty - 69, // 115: grpc.Bridge.ShowOnStartup:output_type -> google.protobuf.BoolValue - 68, // 116: grpc.Bridge.SetIsAutostartOn:output_type -> google.protobuf.Empty - 69, // 117: grpc.Bridge.IsAutostartOn:output_type -> google.protobuf.BoolValue - 68, // 118: grpc.Bridge.SetIsBetaEnabled:output_type -> google.protobuf.Empty - 69, // 119: grpc.Bridge.IsBetaEnabled:output_type -> google.protobuf.BoolValue - 68, // 120: grpc.Bridge.SetIsAllMailVisible:output_type -> google.protobuf.Empty - 69, // 121: grpc.Bridge.IsAllMailVisible:output_type -> google.protobuf.BoolValue - 68, // 122: grpc.Bridge.TriggerReset:output_type -> google.protobuf.Empty - 67, // 123: grpc.Bridge.Version:output_type -> google.protobuf.StringValue - 67, // 124: grpc.Bridge.LogsPath:output_type -> google.protobuf.StringValue - 67, // 125: grpc.Bridge.LicensePath:output_type -> google.protobuf.StringValue - 67, // 126: grpc.Bridge.ReleaseNotesPageLink:output_type -> google.protobuf.StringValue - 67, // 127: grpc.Bridge.DependencyLicensesLink:output_type -> google.protobuf.StringValue - 67, // 128: grpc.Bridge.LandingPageLink:output_type -> google.protobuf.StringValue - 68, // 129: grpc.Bridge.SetColorSchemeName:output_type -> google.protobuf.Empty - 67, // 130: grpc.Bridge.ColorSchemeName:output_type -> google.protobuf.StringValue - 67, // 131: grpc.Bridge.CurrentEmailClient:output_type -> google.protobuf.StringValue - 68, // 132: grpc.Bridge.ReportBug:output_type -> google.protobuf.Empty - 68, // 133: grpc.Bridge.ExportTLSCertificates:output_type -> google.protobuf.Empty - 68, // 134: grpc.Bridge.ForceLauncher:output_type -> google.protobuf.Empty - 68, // 135: grpc.Bridge.SetMainExecutable:output_type -> google.protobuf.Empty - 68, // 136: grpc.Bridge.Login:output_type -> google.protobuf.Empty - 68, // 137: grpc.Bridge.Login2FA:output_type -> google.protobuf.Empty - 68, // 138: grpc.Bridge.Login2Passwords:output_type -> google.protobuf.Empty - 68, // 139: grpc.Bridge.LoginAbort:output_type -> google.protobuf.Empty - 68, // 140: grpc.Bridge.CheckUpdate:output_type -> google.protobuf.Empty - 68, // 141: grpc.Bridge.InstallUpdate:output_type -> google.protobuf.Empty - 68, // 142: grpc.Bridge.SetIsAutomaticUpdateOn:output_type -> google.protobuf.Empty - 69, // 143: grpc.Bridge.IsAutomaticUpdateOn:output_type -> google.protobuf.BoolValue - 67, // 144: grpc.Bridge.DiskCachePath:output_type -> google.protobuf.StringValue - 68, // 145: grpc.Bridge.SetDiskCachePath:output_type -> google.protobuf.Empty - 68, // 146: grpc.Bridge.SetIsDoHEnabled:output_type -> google.protobuf.Empty - 69, // 147: grpc.Bridge.IsDoHEnabled:output_type -> google.protobuf.BoolValue - 12, // 148: grpc.Bridge.MailServerSettings:output_type -> grpc.ImapSmtpSettings - 68, // 149: grpc.Bridge.SetMailServerSettings:output_type -> google.protobuf.Empty - 67, // 150: grpc.Bridge.Hostname:output_type -> google.protobuf.StringValue - 69, // 151: grpc.Bridge.IsPortFree:output_type -> google.protobuf.BoolValue - 13, // 152: grpc.Bridge.AvailableKeychains:output_type -> grpc.AvailableKeychainsResponse - 68, // 153: grpc.Bridge.SetCurrentKeychain:output_type -> google.protobuf.Empty - 67, // 154: grpc.Bridge.CurrentKeychain:output_type -> google.protobuf.StringValue - 16, // 155: grpc.Bridge.GetUserList:output_type -> grpc.UserListResponse - 14, // 156: grpc.Bridge.GetUser:output_type -> grpc.User - 68, // 157: grpc.Bridge.SetUserSplitMode:output_type -> google.protobuf.Empty - 68, // 158: grpc.Bridge.LogoutUser:output_type -> google.protobuf.Empty - 68, // 159: grpc.Bridge.RemoveUser:output_type -> google.protobuf.Empty - 68, // 160: grpc.Bridge.ConfigureUserAppleMail:output_type -> google.protobuf.Empty - 19, // 161: grpc.Bridge.RunEventStream:output_type -> grpc.StreamEvent - 68, // 162: grpc.Bridge.StopEventStream:output_type -> google.protobuf.Empty - 110, // [110:163] is the sub-list for method output_type - 57, // [57:110] is the sub-list for method input_type - 57, // [57:57] is the sub-list for extension type_name - 57, // [57:57] is the sub-list for extension extendee - 0, // [0:57] is the sub-list for field type_name + 66, // 56: grpc.UserEvent.syncStartedEvent:type_name -> grpc.SyncStartedEvent + 67, // 57: grpc.UserEvent.syncFinishedEvent:type_name -> grpc.SyncFinishedEvent + 68, // 58: grpc.UserEvent.syncProgressEvent:type_name -> grpc.SyncProgressEvent + 6, // 59: grpc.GenericErrorEvent.code:type_name -> grpc.ErrorCode + 70, // 60: grpc.Bridge.CheckTokens:input_type -> google.protobuf.StringValue + 7, // 61: grpc.Bridge.AddLogEntry:input_type -> grpc.AddLogEntryRequest + 71, // 62: grpc.Bridge.GuiReady:input_type -> google.protobuf.Empty + 71, // 63: grpc.Bridge.Quit:input_type -> google.protobuf.Empty + 71, // 64: grpc.Bridge.Restart:input_type -> google.protobuf.Empty + 71, // 65: grpc.Bridge.ShowOnStartup:input_type -> google.protobuf.Empty + 72, // 66: grpc.Bridge.SetIsAutostartOn:input_type -> google.protobuf.BoolValue + 71, // 67: grpc.Bridge.IsAutostartOn:input_type -> google.protobuf.Empty + 72, // 68: grpc.Bridge.SetIsBetaEnabled:input_type -> google.protobuf.BoolValue + 71, // 69: grpc.Bridge.IsBetaEnabled:input_type -> google.protobuf.Empty + 72, // 70: grpc.Bridge.SetIsAllMailVisible:input_type -> google.protobuf.BoolValue + 71, // 71: grpc.Bridge.IsAllMailVisible:input_type -> google.protobuf.Empty + 71, // 72: grpc.Bridge.TriggerReset:input_type -> google.protobuf.Empty + 71, // 73: grpc.Bridge.Version:input_type -> google.protobuf.Empty + 71, // 74: grpc.Bridge.LogsPath:input_type -> google.protobuf.Empty + 71, // 75: grpc.Bridge.LicensePath:input_type -> google.protobuf.Empty + 71, // 76: grpc.Bridge.ReleaseNotesPageLink:input_type -> google.protobuf.Empty + 71, // 77: grpc.Bridge.DependencyLicensesLink:input_type -> google.protobuf.Empty + 71, // 78: grpc.Bridge.LandingPageLink:input_type -> google.protobuf.Empty + 70, // 79: grpc.Bridge.SetColorSchemeName:input_type -> google.protobuf.StringValue + 71, // 80: grpc.Bridge.ColorSchemeName:input_type -> google.protobuf.Empty + 71, // 81: grpc.Bridge.CurrentEmailClient:input_type -> google.protobuf.Empty + 9, // 82: grpc.Bridge.ReportBug:input_type -> grpc.ReportBugRequest + 70, // 83: grpc.Bridge.ExportTLSCertificates:input_type -> google.protobuf.StringValue + 70, // 84: grpc.Bridge.ForceLauncher:input_type -> google.protobuf.StringValue + 70, // 85: grpc.Bridge.SetMainExecutable:input_type -> google.protobuf.StringValue + 10, // 86: grpc.Bridge.Login:input_type -> grpc.LoginRequest + 10, // 87: grpc.Bridge.Login2FA:input_type -> grpc.LoginRequest + 10, // 88: grpc.Bridge.Login2Passwords:input_type -> grpc.LoginRequest + 11, // 89: grpc.Bridge.LoginAbort:input_type -> grpc.LoginAbortRequest + 71, // 90: grpc.Bridge.CheckUpdate:input_type -> google.protobuf.Empty + 71, // 91: grpc.Bridge.InstallUpdate:input_type -> google.protobuf.Empty + 72, // 92: grpc.Bridge.SetIsAutomaticUpdateOn:input_type -> google.protobuf.BoolValue + 71, // 93: grpc.Bridge.IsAutomaticUpdateOn:input_type -> google.protobuf.Empty + 71, // 94: grpc.Bridge.DiskCachePath:input_type -> google.protobuf.Empty + 70, // 95: grpc.Bridge.SetDiskCachePath:input_type -> google.protobuf.StringValue + 72, // 96: grpc.Bridge.SetIsDoHEnabled:input_type -> google.protobuf.BoolValue + 71, // 97: grpc.Bridge.IsDoHEnabled:input_type -> google.protobuf.Empty + 71, // 98: grpc.Bridge.MailServerSettings:input_type -> google.protobuf.Empty + 12, // 99: grpc.Bridge.SetMailServerSettings:input_type -> grpc.ImapSmtpSettings + 71, // 100: grpc.Bridge.Hostname:input_type -> google.protobuf.Empty + 73, // 101: grpc.Bridge.IsPortFree:input_type -> google.protobuf.Int32Value + 71, // 102: grpc.Bridge.AvailableKeychains:input_type -> google.protobuf.Empty + 70, // 103: grpc.Bridge.SetCurrentKeychain:input_type -> google.protobuf.StringValue + 71, // 104: grpc.Bridge.CurrentKeychain:input_type -> google.protobuf.Empty + 71, // 105: grpc.Bridge.GetUserList:input_type -> google.protobuf.Empty + 70, // 106: grpc.Bridge.GetUser:input_type -> google.protobuf.StringValue + 15, // 107: grpc.Bridge.SetUserSplitMode:input_type -> grpc.UserSplitModeRequest + 70, // 108: grpc.Bridge.LogoutUser:input_type -> google.protobuf.StringValue + 70, // 109: grpc.Bridge.RemoveUser:input_type -> google.protobuf.StringValue + 17, // 110: grpc.Bridge.ConfigureUserAppleMail:input_type -> grpc.ConfigureAppleMailRequest + 18, // 111: grpc.Bridge.RunEventStream:input_type -> grpc.EventStreamRequest + 71, // 112: grpc.Bridge.StopEventStream:input_type -> google.protobuf.Empty + 70, // 113: grpc.Bridge.CheckTokens:output_type -> google.protobuf.StringValue + 71, // 114: grpc.Bridge.AddLogEntry:output_type -> google.protobuf.Empty + 8, // 115: grpc.Bridge.GuiReady:output_type -> grpc.GuiReadyResponse + 71, // 116: grpc.Bridge.Quit:output_type -> google.protobuf.Empty + 71, // 117: grpc.Bridge.Restart:output_type -> google.protobuf.Empty + 72, // 118: grpc.Bridge.ShowOnStartup:output_type -> google.protobuf.BoolValue + 71, // 119: grpc.Bridge.SetIsAutostartOn:output_type -> google.protobuf.Empty + 72, // 120: grpc.Bridge.IsAutostartOn:output_type -> google.protobuf.BoolValue + 71, // 121: grpc.Bridge.SetIsBetaEnabled:output_type -> google.protobuf.Empty + 72, // 122: grpc.Bridge.IsBetaEnabled:output_type -> google.protobuf.BoolValue + 71, // 123: grpc.Bridge.SetIsAllMailVisible:output_type -> google.protobuf.Empty + 72, // 124: grpc.Bridge.IsAllMailVisible:output_type -> google.protobuf.BoolValue + 71, // 125: grpc.Bridge.TriggerReset:output_type -> google.protobuf.Empty + 70, // 126: grpc.Bridge.Version:output_type -> google.protobuf.StringValue + 70, // 127: grpc.Bridge.LogsPath:output_type -> google.protobuf.StringValue + 70, // 128: grpc.Bridge.LicensePath:output_type -> google.protobuf.StringValue + 70, // 129: grpc.Bridge.ReleaseNotesPageLink:output_type -> google.protobuf.StringValue + 70, // 130: grpc.Bridge.DependencyLicensesLink:output_type -> google.protobuf.StringValue + 70, // 131: grpc.Bridge.LandingPageLink:output_type -> google.protobuf.StringValue + 71, // 132: grpc.Bridge.SetColorSchemeName:output_type -> google.protobuf.Empty + 70, // 133: grpc.Bridge.ColorSchemeName:output_type -> google.protobuf.StringValue + 70, // 134: grpc.Bridge.CurrentEmailClient:output_type -> google.protobuf.StringValue + 71, // 135: grpc.Bridge.ReportBug:output_type -> google.protobuf.Empty + 71, // 136: grpc.Bridge.ExportTLSCertificates:output_type -> google.protobuf.Empty + 71, // 137: grpc.Bridge.ForceLauncher:output_type -> google.protobuf.Empty + 71, // 138: grpc.Bridge.SetMainExecutable:output_type -> google.protobuf.Empty + 71, // 139: grpc.Bridge.Login:output_type -> google.protobuf.Empty + 71, // 140: grpc.Bridge.Login2FA:output_type -> google.protobuf.Empty + 71, // 141: grpc.Bridge.Login2Passwords:output_type -> google.protobuf.Empty + 71, // 142: grpc.Bridge.LoginAbort:output_type -> google.protobuf.Empty + 71, // 143: grpc.Bridge.CheckUpdate:output_type -> google.protobuf.Empty + 71, // 144: grpc.Bridge.InstallUpdate:output_type -> google.protobuf.Empty + 71, // 145: grpc.Bridge.SetIsAutomaticUpdateOn:output_type -> google.protobuf.Empty + 72, // 146: grpc.Bridge.IsAutomaticUpdateOn:output_type -> google.protobuf.BoolValue + 70, // 147: grpc.Bridge.DiskCachePath:output_type -> google.protobuf.StringValue + 71, // 148: grpc.Bridge.SetDiskCachePath:output_type -> google.protobuf.Empty + 71, // 149: grpc.Bridge.SetIsDoHEnabled:output_type -> google.protobuf.Empty + 72, // 150: grpc.Bridge.IsDoHEnabled:output_type -> google.protobuf.BoolValue + 12, // 151: grpc.Bridge.MailServerSettings:output_type -> grpc.ImapSmtpSettings + 71, // 152: grpc.Bridge.SetMailServerSettings:output_type -> google.protobuf.Empty + 70, // 153: grpc.Bridge.Hostname:output_type -> google.protobuf.StringValue + 72, // 154: grpc.Bridge.IsPortFree:output_type -> google.protobuf.BoolValue + 13, // 155: grpc.Bridge.AvailableKeychains:output_type -> grpc.AvailableKeychainsResponse + 71, // 156: grpc.Bridge.SetCurrentKeychain:output_type -> google.protobuf.Empty + 70, // 157: grpc.Bridge.CurrentKeychain:output_type -> google.protobuf.StringValue + 16, // 158: grpc.Bridge.GetUserList:output_type -> grpc.UserListResponse + 14, // 159: grpc.Bridge.GetUser:output_type -> grpc.User + 71, // 160: grpc.Bridge.SetUserSplitMode:output_type -> google.protobuf.Empty + 71, // 161: grpc.Bridge.LogoutUser:output_type -> google.protobuf.Empty + 71, // 162: grpc.Bridge.RemoveUser:output_type -> google.protobuf.Empty + 71, // 163: grpc.Bridge.ConfigureUserAppleMail:output_type -> google.protobuf.Empty + 19, // 164: grpc.Bridge.RunEventStream:output_type -> grpc.StreamEvent + 71, // 165: grpc.Bridge.StopEventStream:output_type -> google.protobuf.Empty + 113, // [113:166] is the sub-list for method output_type + 60, // [60:113] is the sub-list for method input_type + 60, // [60:60] is the sub-list for extension type_name + 60, // [60:60] is the sub-list for extension extendee + 0, // [0:60] is the sub-list for field type_name } func init() { file_bridge_proto_init() } @@ -5718,6 +5959,42 @@ func file_bridge_proto_init() { } } file_bridge_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SyncStartedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bridge_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SyncFinishedEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bridge_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*SyncProgressEvent); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_bridge_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*GenericErrorEvent); i { case 0: return &v.state @@ -5795,6 +6072,9 @@ func file_bridge_proto_init() { (*UserEvent_UserBadEvent)(nil), (*UserEvent_UsedBytesChangedEvent)(nil), (*UserEvent_ImapLoginFailedEvent)(nil), + (*UserEvent_SyncStartedEvent)(nil), + (*UserEvent_SyncFinishedEvent)(nil), + (*UserEvent_SyncProgressEvent)(nil), } type x struct{} out := protoimpl.TypeBuilder{ @@ -5802,7 +6082,7 @@ func file_bridge_proto_init() { GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_bridge_proto_rawDesc, NumEnums: 7, - NumMessages: 60, + NumMessages: 63, NumExtensions: 0, NumServices: 1, }, diff --git a/internal/frontend/grpc/bridge.proto b/internal/frontend/grpc/bridge.proto index fc9b9b53..b44271ad 100644 --- a/internal/frontend/grpc/bridge.proto +++ b/internal/frontend/grpc/bridge.proto @@ -449,6 +449,9 @@ message UserEvent { UserBadEvent userBadEvent = 4; UsedBytesChangedEvent usedBytesChangedEvent = 5; ImapLoginFailedEvent imapLoginFailedEvent = 6; + SyncStartedEvent syncStartedEvent = 7; + SyncFinishedEvent syncFinishedEvent = 8; + SyncProgressEvent syncProgressEvent = 9; } } @@ -478,6 +481,21 @@ message ImapLoginFailedEvent { string username = 1; } +message SyncStartedEvent { + string userID = 1; +} + +message SyncFinishedEvent { + string userID = 1; +} + +message SyncProgressEvent { + string userID = 1; + double progress = 2; + int64 elapsedMs = 3; + int64 remainingMs = 4; +} + //********************************************************** // Generic errors //********************************************************** diff --git a/internal/frontend/grpc/event_factory.go b/internal/frontend/grpc/event_factory.go index 056c107e..67d87fb4 100644 --- a/internal/frontend/grpc/event_factory.go +++ b/internal/frontend/grpc/event_factory.go @@ -185,6 +185,23 @@ func newIMAPLoginFailedEvent(username string) *StreamEvent { return userEvent(&UserEvent{Event: &UserEvent_ImapLoginFailedEvent{ImapLoginFailedEvent: &ImapLoginFailedEvent{Username: username}}}) } +func NewSyncStartedEvent(userID string) *StreamEvent { + return userEvent(&UserEvent{Event: &UserEvent_SyncStartedEvent{SyncStartedEvent: &SyncStartedEvent{UserID: userID}}}) +} + +func NewSyncFinishedEvent(userID string) *StreamEvent { + return userEvent(&UserEvent{Event: &UserEvent_SyncFinishedEvent{SyncFinishedEvent: &SyncFinishedEvent{UserID: userID}}}) +} + +func NewSyncProgressEvent(userID string, progress float64, elapsedMs, remainingMs int64) *StreamEvent { + return userEvent(&UserEvent{Event: &UserEvent_SyncProgressEvent{SyncProgressEvent: &SyncProgressEvent{ + UserID: userID, + Progress: progress, + ElapsedMs: elapsedMs, + RemainingMs: remainingMs, + }}}) +} + func NewGenericErrorEvent(errorCode ErrorCode) *StreamEvent { return genericErrorEvent(&GenericErrorEvent{Code: errorCode}) } diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index 732ef823..89c6b585 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -323,6 +323,15 @@ func (s *Service) watchEvents() { case events.UserBadEvent: _ = s.SendEvent(NewUserBadEvent(event.UserID, event.Error.Error())) + case events.SyncStarted: + _ = s.SendEvent(NewSyncStartedEvent(event.UserID)) + + case events.SyncFinished: + _ = s.SendEvent(NewSyncFinishedEvent(event.UserID)) + + case events.SyncProgress: + _ = s.SendEvent(NewSyncProgressEvent(event.UserID, event.Progress, event.Elapsed.Milliseconds(), event.Remaining.Milliseconds())) + case events.UpdateLatest: safe.RLock(func() { s.latest = event.Version From 265af2d299010967bbe372cad32b89b150ce9f04 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Wed, 22 Feb 2023 19:39:24 +0100 Subject: [PATCH 072/130] fix(GODT-2389): close bridge on exception and add max termination wait time. --- internal/frontend/bridge-gui/bridge-gui/main.cpp | 16 +++++++--------- .../bridgepp/bridgepp/Worker/Overseer.cpp | 3 ++- .../bridgepp/bridgepp/Worker/Overseer.h | 3 +++ 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 90b1ebe2..1b0338bb 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -117,8 +117,9 @@ QQmlComponent *createRootQmlComponent(QQmlApplicationEngine &engine) { rootComponent->loadUrl(QUrl(qrcQmlDir + "/Bridge.qml")); if (rootComponent->status() != QQmlComponent::Status::Ready) { - app().log().error(rootComponent->errorString()); - throw Exception("Could not load QML component"); + QString const &err =rootComponent->errorString(); + app().log().error(err); + throw Exception("Could not load QML component", err); } return rootComponent; } @@ -255,12 +256,8 @@ void closeBridgeApp() { app().grpc().quit(); // this will cause the grpc service and the bridge app to close. UPOverseer &overseer = app().bridgeOverseer(); - if (!overseer) { // The app was run in 'attach' mode and attached to an existing instance of Bridge. We're not monitoring it. - return; - } - - while (!overseer->isFinished()) { - QThread::msleep(20); + if (overseer) { // A null overseer means the app was run in 'attach' mode. We're not monitoring it. + overseer->wait(Overseer::maxTerminationWaitTimeMs); } } @@ -387,7 +384,7 @@ int main(int argc, char *argv[]) { QObject::disconnect(connection); app().grpc().stopEventStreamReader(); - if (!app().backend().waitForEventStreamReaderToFinish(5000)) { + if (!app().backend().waitForEventStreamReaderToFinish(Overseer::maxTerminationWaitTimeMs)) { log.warn("Event stream reader took too long to finish."); } @@ -413,6 +410,7 @@ int main(int argc, char *argv[]) { errStream << "reportID: " << QByteArray(uuid.bytes, 16).toHex() << " Captured exception :" << e.qwhat() << "\n"; if (hasDetails) errStream << "\nDetails:\n" << e.details() << "\n"; + closeBridgeApp(); return EXIT_FAILURE; } } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.cpp index ed4553bc..8a5da3b4 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.cpp @@ -84,7 +84,8 @@ void Overseer::releaseWorker() { if (thread_) { if (!thread_->isFinished()) { thread_->quit(); - thread_->wait(); + if (!thread_->wait(maxTerminationWaitTimeMs)) + thread_->terminate(); } thread_->deleteLater(); thread_ = nullptr; diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.h index 26943899..e4bdd47a 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Worker/Overseer.h @@ -46,6 +46,9 @@ public slots: void startWorker(bool autorelease) const; ///< Run the worker. void releaseWorker(); ///< Delete the worker and its thread. +public: // static data members + static qint64 const maxTerminationWaitTimeMs { 10000 }; ///< The maximum wait time for the termination of a thread + public: // data members. QThread *thread_ { nullptr }; ///< The thread. Worker *worker_ { nullptr }; ///< The worker. From 8534da98ea6da2f7841835d453684f310f1d2167 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Wed, 22 Feb 2023 20:29:16 +0100 Subject: [PATCH 073/130] chore: fix missing windows header for bridgelib. bridgelib was moved from bridge-gui to bridgepp project, and windows.h is not auto-included anymore (only Qt core is in the pre-compiled headers). --- internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp index f64c7206..8acf9e7f 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp @@ -47,6 +47,7 @@ void (*deleteCStringFunc)(char *) = nullptr; ///< A pointer to the deleteCString #if defined(Q_OS_WINDOWS) +#include typedef HINSTANCE LibHandle; #else typedef void *LibHandle; From e9f20aee7a4cc704e0c3d9bf29ad6bc9c40fea80 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Wed, 22 Feb 2023 13:39:59 +0100 Subject: [PATCH 074/130] fix(GODT-2387): Ensure vault can be unlocked after factory reset When performing a factory reset, we don't want to wipe all keychain entries. The only keychain entry should be the vault's passphrase, and we need this to be able to decrypt the vault at next startup (to avoid it being reported as corrupt). --- internal/app/bridge.go | 2 -- internal/app/vault.go | 36 ++++++------------------- internal/bridge/settings.go | 21 ++++----------- internal/bridge/types.go | 2 +- internal/locations/locations.go | 5 ++-- internal/vault/helper.go | 48 +++++++++++++++++++++++++++++++++ internal/vault/vault.go | 4 +++ 7 files changed, 68 insertions(+), 50 deletions(-) diff --git a/internal/app/bridge.go b/internal/app/bridge.go index ef42697d..6705227a 100644 --- a/internal/app/bridge.go +++ b/internal/app/bridge.go @@ -41,8 +41,6 @@ import ( "github.com/urfave/cli/v2" ) -const vaultSecretName = "bridge-vault-key" - // deleteOldGoIMAPFiles Set with `-ldflags -X app.deleteOldGoIMAPFiles=true` to enable cleanup of old imap cache data. var deleteOldGoIMAPFiles bool //nolint:gochecknoglobals diff --git a/internal/app/vault.go b/internal/app/vault.go index 895e320d..55b583b1 100644 --- a/internal/app/vault.go +++ b/internal/app/vault.go @@ -18,18 +18,15 @@ package app import ( - "encoding/base64" "fmt" "path" - "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/proton-bridge/v3/internal/certs" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/locations" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/ProtonMail/proton-bridge/v3/pkg/keychain" "github.com/sirupsen/logrus" - "golang.org/x/exp/slices" ) func WithVault(locations *locations.Locations, fn func(*vault.Vault, bool, bool) error) error { @@ -82,7 +79,7 @@ func newVault(locations *locations.Locations) (*vault.Vault, bool, bool, error) insecure bool ) - if key, err := getVaultKey(vaultDir); err != nil { + if key, err := loadVaultKey(vaultDir); err != nil { insecure = true // We store the insecure vault in a separate directory @@ -104,42 +101,25 @@ func newVault(locations *locations.Locations) (*vault.Vault, bool, bool, error) return vault, insecure, corrupt, nil } -func getVaultKey(vaultDir string) ([]byte, error) { +func loadVaultKey(vaultDir string) ([]byte, error) { helper, err := vault.GetHelper(vaultDir) if err != nil { return nil, fmt.Errorf("could not get keychain helper: %w", err) } - keychain, err := keychain.NewKeychain(helper, constants.KeyChainName) + kc, err := keychain.NewKeychain(helper, constants.KeyChainName) if err != nil { return nil, fmt.Errorf("could not create keychain: %w", err) } - secrets, err := keychain.List() + has, err := vault.HasVaultKey(kc) if err != nil { - return nil, fmt.Errorf("could not list keychain: %w", err) + return nil, fmt.Errorf("could not check for vault key: %w", err) } - if !slices.Contains(secrets, vaultSecretName) { - tok, err := crypto.RandomToken(32) - if err != nil { - return nil, fmt.Errorf("could not generate random token: %w", err) - } - - if err := keychain.Put(vaultSecretName, base64.StdEncoding.EncodeToString(tok)); err != nil { - return nil, fmt.Errorf("could not put keychain item: %w", err) - } + if has { + return vault.GetVaultKey(kc) } - _, keyEnc, err := keychain.Get(vaultSecretName) - if err != nil { - return nil, fmt.Errorf("could not get keychain item: %w", err) - } - - keyDec, err := base64.StdEncoding.DecodeString(keyEnc) - if err != nil { - return nil, fmt.Errorf("could not decode keychain item: %w", err) - } - - return keyDec, nil + return vault.NewVaultKey(kc) } diff --git a/internal/bridge/settings.go b/internal/bridge/settings.go index 667406b2..0ab4c5a0 100644 --- a/internal/bridge/settings.go +++ b/internal/bridge/settings.go @@ -25,11 +25,9 @@ import ( "path/filepath" "github.com/Masterminds/semver/v3" - "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/safe" "github.com/ProtonMail/proton-bridge/v3/internal/updater" "github.com/ProtonMail/proton-bridge/v3/internal/vault" - "github.com/ProtonMail/proton-bridge/v3/pkg/keychain" "github.com/sirupsen/logrus" ) @@ -310,6 +308,9 @@ func (bridge *Bridge) SetColorScheme(colorScheme string) error { return bridge.vault.SetColorScheme(colorScheme) } +// FactoryReset deletes all users, wipes the vault, and deletes all files. +// Note: it does not clear the keychain. The only entry in the keychain is the vault password, +// which we need at next startup to decrypt the vault. func (bridge *Bridge) FactoryReset(ctx context.Context) { // Delete all the users. safe.Lock(func() { @@ -326,22 +327,10 @@ func (bridge *Bridge) FactoryReset(ctx context.Context) { logrus.WithError(err).Error("Failed to reset vault") } - // Then delete all files. - if err := bridge.locator.Clear(); err != nil { + // Lastly, delete all files except the vault. + if err := bridge.locator.Clear(bridge.vault.Path()); err != nil { logrus.WithError(err).Error("Failed to clear data paths") } - - // Lastly clear the keychain. - vaultDir, err := bridge.locator.ProvideSettingsPath() - if err != nil { - logrus.WithError(err).Error("Failed to get vault dir") - } else if helper, err := vault.GetHelper(vaultDir); err != nil { - logrus.WithError(err).Error("Failed to get keychain helper") - } else if keychain, err := keychain.NewKeychain(helper, constants.KeyChainName); err != nil { - logrus.WithError(err).Error("Failed to get keychain") - } else if err := keychain.Clear(); err != nil { - logrus.WithError(err).Error("Failed to clear keychain") - } } func getPort(addr net.Addr) int { diff --git a/internal/bridge/types.go b/internal/bridge/types.go index 4c79defc..3e779817 100644 --- a/internal/bridge/types.go +++ b/internal/bridge/types.go @@ -30,7 +30,7 @@ type Locator interface { ProvideGluonDataPath() (string, error) GetLicenseFilePath() string GetDependencyLicensesLink() string - Clear() error + Clear(...string) error } type Identifier interface { diff --git a/internal/locations/locations.go b/internal/locations/locations.go index 197549a4..8a5c14d5 100644 --- a/internal/locations/locations.go +++ b/internal/locations/locations.go @@ -217,14 +217,13 @@ func (l *Locations) getUpdatesPath() string { } // Clear removes everything except the lock and update files. -func (l *Locations) Clear() error { +func (l *Locations) Clear(except ...string) error { return files.Remove( l.userConfig, l.userData, l.userCache, ).Except( - l.GetGuiLockFile(), - l.getUpdatesPath(), + append(except, l.GetGuiLockFile(), l.getUpdatesPath())..., ).Do() } diff --git a/internal/vault/helper.go b/internal/vault/helper.go index 721c5ab0..dfc64878 100644 --- a/internal/vault/helper.go +++ b/internal/vault/helper.go @@ -18,13 +18,21 @@ package vault import ( + "encoding/base64" "encoding/json" "errors" + "fmt" "io/fs" "os" "path/filepath" + + "github.com/ProtonMail/gopenpgp/v2/crypto" + "github.com/ProtonMail/proton-bridge/v3/pkg/keychain" + "golang.org/x/exp/slices" ) +const vaultSecretName = "bridge-vault-key" + type Keychain struct { Helper string } @@ -60,3 +68,43 @@ func SetHelper(vaultDir, helper string) error { return os.WriteFile(getKeychainPrefPath(vaultDir), b, 0o600) } + +func HasVaultKey(kc *keychain.Keychain) (bool, error) { + secrets, err := kc.List() + if err != nil { + return false, fmt.Errorf("could not list keychain: %w", err) + } + + return slices.Contains(secrets, vaultSecretName), nil +} + +func GetVaultKey(kc *keychain.Keychain) ([]byte, error) { + _, keyEnc, err := kc.Get(vaultSecretName) + if err != nil { + return nil, fmt.Errorf("could not get keychain item: %w", err) + } + + keyDec, err := base64.StdEncoding.DecodeString(keyEnc) + if err != nil { + return nil, fmt.Errorf("could not decode keychain item: %w", err) + } + + return keyDec, nil +} + +func SetVaultKey(kc *keychain.Keychain, key []byte) error { + return kc.Put(vaultSecretName, base64.StdEncoding.EncodeToString(key)) +} + +func NewVaultKey(kc *keychain.Keychain) ([]byte, error) { + tok, err := crypto.RandomToken(32) + if err != nil { + return nil, fmt.Errorf("could not generate random token: %w", err) + } + + if err := kc.Put(vaultSecretName, base64.StdEncoding.EncodeToString(tok)); err != nil { + return nil, fmt.Errorf("could not put keychain item: %w", err) + } + + return tok, nil +} diff --git a/internal/vault/vault.go b/internal/vault/vault.go index 09f3b50e..4e605e3a 100644 --- a/internal/vault/vault.go +++ b/internal/vault/vault.go @@ -191,6 +191,10 @@ func (vault *Vault) Reset(gluonDir string) error { }) } +func (vault *Vault) Path() string { + return vault.path +} + func (vault *Vault) Close() error { vault.refLock.Lock() defer vault.refLock.Unlock() From 671db7c516c68af1179d57a66169a9ef30ff2a12 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Thu, 23 Feb 2023 11:53:41 +0100 Subject: [PATCH 075/130] chore: Fix typo loggin back in --- .../bridge-gui/bridge-gui/qml/Notifications/Notifications.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml b/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml index c89c9443..c4d250cc 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml @@ -1111,7 +1111,7 @@ QtObject { type: Notification.NotificationType.Danger group: Notifications.Group.Connection | Notifications.Group.Dialogs - property var bugReportMsg: "Reporting an issue:\n\n\"%1\"\n\nError: %2\n\nThe issue persists even after loggin back in." + property var bugReportMsg: "Reporting an issue:\n\n\"%1\"\n\nError: %2\n\nThe issue persists even after logging back in." property var errorMessage: "" Connections { From 00256fafe8614600c0ea847673d6e1ca0f6861b3 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Thu, 23 Feb 2023 12:09:40 +0100 Subject: [PATCH 076/130] fix(GODT-2394): Bump Gluon for golang.org/x/text DoS risk This also fixes a harmless error related to multiple deletions in the store. --- COPYING_NOTES.md | 2 ++ go.mod | 38 ++++++++++++---------- go.sum | 85 ++++++++++++++++++++++++++---------------------- 3 files changed, 69 insertions(+), 56 deletions(-) diff --git a/COPYING_NOTES.md b/COPYING_NOTES.md index ce628759..ede8163c 100644 --- a/COPYING_NOTES.md +++ b/COPYING_NOTES.md @@ -89,6 +89,7 @@ Proton Mail Bridge includes the following 3rd party software: * [go-windows](https://github.com/elastic/go-windows) available under [license](https://github.com/elastic/go-windows/blob/master/LICENSE) * [go-textwrapper](https://github.com/emersion/go-textwrapper) available under [license](https://github.com/emersion/go-textwrapper/blob/master/LICENSE) * [go-vcard](https://github.com/emersion/go-vcard) available under [license](https://github.com/emersion/go-vcard/blob/master/LICENSE) +* [fgprof](https://github.com/felixge/fgprof) available under [license](https://github.com/felixge/fgprof/blob/master/LICENSE) * [go-shlex](https://github.com/flynn-archive/go-shlex) available under [license](https://github.com/flynn-archive/go-shlex/blob/master/LICENSE) * [sse](https://github.com/gin-contrib/sse) available under [license](https://github.com/gin-contrib/sse/blob/master/LICENSE) * [gin](https://github.com/gin-gonic/gin) available under [license](https://github.com/gin-gonic/gin/blob/master/LICENSE) @@ -98,6 +99,7 @@ Proton Mail Bridge includes the following 3rd party software: * [validator](https://github.com/go-playground/validator/v10) available under [license](https://github.com/go-playground/validator/v10/blob/master/LICENSE) * [uuid](https://github.com/gofrs/uuid) available under [license](https://github.com/gofrs/uuid/blob/master/LICENSE) * [protobuf](https://github.com/golang/protobuf) available under [license](https://github.com/golang/protobuf/blob/master/LICENSE) +* [pprof](https://github.com/google/pprof) available under [license](https://github.com/google/pprof/blob/master/LICENSE) * [errwrap](https://github.com/hashicorp/errwrap) available under [license](https://github.com/hashicorp/errwrap/blob/master/LICENSE) * [go-immutable-radix](https://github.com/hashicorp/go-immutable-radix) available under [license](https://github.com/hashicorp/go-immutable-radix/blob/master/LICENSE) * [go-memdb](https://github.com/hashicorp/go-memdb) available under [license](https://github.com/hashicorp/go-memdb/blob/master/LICENSE) diff --git a/go.mod b/go.mod index e7c698ff..c4fea1c1 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.15.0 + github.com/ProtonMail/gluon v0.15.1-0.20230223111926-1b870f5c0988 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 github.com/ProtonMail/go-rfc5322 v0.11.0 @@ -13,12 +13,12 @@ require ( github.com/PuerkitoBio/goquery v1.8.0 github.com/abiosoft/ishell v2.0.0+incompatible github.com/allan-simon/go-singleinstance v0.0.0-20210120080615-d0997106ab37 - github.com/bradenaw/juniper v0.8.0 + github.com/bradenaw/juniper v0.10.2 github.com/cucumber/godog v0.12.5 github.com/cucumber/messages-go/v16 v16.0.1 github.com/docker/docker-credential-helpers v0.6.3 github.com/elastic/go-sysinfo v1.8.1 - github.com/emersion/go-imap v1.2.1-0.20220429085312-746087b7a317 + github.com/emersion/go-imap v1.2.1 github.com/emersion/go-imap-id v0.0.0-20190926060100-f94a56b9ecde github.com/emersion/go-message v0.16.0 github.com/emersion/go-sasl v0.0.0-20220912192320-0145f2c60ead @@ -37,24 +37,24 @@ require ( github.com/miekg/dns v1.1.50 github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 github.com/pkg/errors v0.9.1 - github.com/pkg/profile v1.6.0 + github.com/pkg/profile v1.7.0 github.com/sirupsen/logrus v1.9.0 - github.com/stretchr/testify v1.8.0 + github.com/stretchr/testify v1.8.1 github.com/urfave/cli/v2 v2.20.3 github.com/vmihailenco/msgpack/v5 v5.3.5 - go.uber.org/goleak v1.2.0 - golang.org/x/exp v0.0.0-20221023144134-a1e5550cf13e - golang.org/x/net v0.1.0 - golang.org/x/sys v0.1.0 - golang.org/x/text v0.4.0 + go.uber.org/goleak v1.2.1 + golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb + golang.org/x/net v0.2.0 + golang.org/x/sys v0.5.0 + golang.org/x/text v0.7.0 google.golang.org/grpc v1.50.1 google.golang.org/protobuf v1.28.1 howett.net/plist v1.0.0 ) require ( - ariga.io/atlas v0.7.0 // indirect - entgo.io/ent v0.11.2 // indirect + ariga.io/atlas v0.9.1-0.20230119145809-92243f7c55cb // indirect + entgo.io/ent v0.11.8 // indirect github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf // indirect github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895 // indirect github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f // indirect @@ -74,6 +74,7 @@ require ( github.com/elastic/go-windows v1.0.1 // indirect github.com/emersion/go-textwrapper v0.0.0-20200911093747-65d896831594 // indirect github.com/emersion/go-vcard v0.0.0-20220507122617-d4056df0ec4a // indirect + github.com/felixge/fgprof v0.9.3 // indirect github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/gin-gonic/gin v1.8.1 // indirect @@ -83,18 +84,19 @@ require ( github.com/go-playground/validator/v10 v10.11.1 // indirect github.com/gofrs/uuid v4.3.0+incompatible // indirect github.com/golang/protobuf v1.5.2 // indirect + github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-immutable-radix v1.3.1 // indirect github.com/hashicorp/go-memdb v1.3.3 // indirect github.com/hashicorp/golang-lru v0.5.4 // indirect - github.com/hashicorp/hcl/v2 v2.14.0 // indirect + github.com/hashicorp/hcl/v2 v2.16.1 // indirect github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect github.com/json-iterator/go v1.1.12 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.16 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect - github.com/mattn/go-sqlite3 v1.14.15 // indirect + github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect @@ -110,11 +112,11 @@ require ( github.com/ugorji/go/codec v1.2.7 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect - github.com/zclconf/go-cty v1.11.0 // indirect + github.com/zclconf/go-cty v1.12.1 // indirect golang.org/x/crypto v0.1.0 // indirect - golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect - golang.org/x/sync v0.0.0-20220907140024-f12130a52804 // indirect - golang.org/x/tools v0.1.13-0.20220804200503-81c7dc4e4efa // indirect + golang.org/x/mod v0.8.0 // indirect + golang.org/x/sync v0.1.0 // indirect + golang.org/x/tools v0.3.1-0.20221202221704-aa9f4b2f3d57 // indirect google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 83b3f40b..81a138cf 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -ariga.io/atlas v0.7.0 h1:daEFdUsyNm7EHyzcMfjWwq/fVv48fCfad+dIGyobY1k= -ariga.io/atlas v0.7.0/go.mod h1:ft47uSh5hWGDCmQC9DsztZg6Xk+KagM5Ts/mZYKb9JE= +ariga.io/atlas v0.9.1-0.20230119145809-92243f7c55cb h1:mbsFtavDqGdYwdDpP50LGOOZ2hgyGoJcZeOpbgKMyu4= +ariga.io/atlas v0.9.1-0.20230119145809-92243f7c55cb/go.mod h1:T230JFcENj4ZZzMkZrXFDSkv+2kXkUgpJ5FQQ5hMcKU= cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= @@ -13,8 +13,8 @@ cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqCl cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I= cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw= dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU= -entgo.io/ent v0.11.2 h1:UM2/BUhF2FfsxPHRxLjQbhqJNaDdVlOwNIAMLs2jyto= -entgo.io/ent v0.11.2/go.mod h1:YGHEQnmmIUgtD5b1ICD5vg74dS3npkNnmC5K+0J+IHU= +entgo.io/ent v0.11.8 h1:M/M0QL1CYCUSdqGRXUrXhFYSDRJPsOOrr+RLEej/gyQ= +entgo.io/ent v0.11.8/go.mod h1:ericBi6Q8l3wBH1wEIDfKxw7rcQEuRPyBfbIzjtxJ18= github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 h1:l6surSnJ3RP4qA1qmKJ+hQn3UjytosdoG27WGjrDlVs= github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557/go.mod h1:sTrmvD/TxuypdOERsDOS7SndZg0rzzcCi1b6wQMXUYM= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.15.0 h1:Hai69s25OFrubR3rSNsLtErZn+jtknGnZ3ATzlog7Ds= -github.com/ProtonMail/gluon v0.15.0/go.mod h1:HYHr7hG7LPWI1S50M8NfHRb1kYi5B+Yu4/N/H+y+JUY= +github.com/ProtonMail/gluon v0.15.1-0.20230223111926-1b870f5c0988 h1:HU5F+tpx6pdZ7f52oIfjmxfoR4bNkkQ+oG2frMPWHl4= +github.com/ProtonMail/gluon v0.15.1-0.20230223111926-1b870f5c0988/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= @@ -75,13 +75,16 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJmJgSg28kpZDP6UIiPt0e0Oz0kqKNGyRaWEPv84= -github.com/bradenaw/juniper v0.8.0 h1:sdanLNdJbLjcLj993VYIwUHlUVkLzvgiD/x9O7cvvxk= -github.com/bradenaw/juniper v0.8.0/go.mod h1:Z2B7aJlQ7xbfWsnMLROj5t/5FQ94/MkIdKC30J4WvzI= +github.com/bradenaw/juniper v0.10.2 h1:EY7r8SJJrigJ7lvWk6ews3K5RD4XTG9z+WSwHJKijP4= +github.com/bradenaw/juniper v0.10.2/go.mod h1:Z2B7aJlQ7xbfWsnMLROj5t/5FQ94/MkIdKC30J4WvzI= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/bwesterb/go-ristretto v1.2.1/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= +github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= +github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= @@ -120,8 +123,8 @@ github.com/elastic/go-sysinfo v1.8.1 h1:4Yhj+HdV6WjbCRgGdZpPJ8lZQlXZLKDAeIkmQ/VR github.com/elastic/go-sysinfo v1.8.1/go.mod h1:JfllUnzoQV/JRYymbH3dO1yggI3mV2oTKSXsDHM+uIM= github.com/elastic/go-windows v1.0.1 h1:AlYZOldA+UJ0/2nBuqWdo90GFCgG9xuyw9SYzGUtJm0= github.com/elastic/go-windows v1.0.1/go.mod h1:FoVvqWSun28vaDQPbj2Elfc0JahhPB7WQEGa3c814Ss= -github.com/emersion/go-imap v1.2.1-0.20220429085312-746087b7a317 h1:i0cBrdFLm8A/3hWEjn/BwdXLBplFJoZtu63p7bjrmaI= -github.com/emersion/go-imap v1.2.1-0.20220429085312-746087b7a317/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY= +github.com/emersion/go-imap v1.2.1 h1:+s9ZjMEjOB8NzZMVTM3cCenz2JrQIGGo5j1df19WjTA= +github.com/emersion/go-imap v1.2.1/go.mod h1:Qlx1FSx2FTxjnjWpIlVNEuX+ylerZQNFE5NsmKFSejY= github.com/emersion/go-imap-id v0.0.0-20190926060100-f94a56b9ecde h1:43mBoVwooyLm1+1YVf5nvn1pSFWhw7rOpcrp1Jg/qk0= github.com/emersion/go-imap-id v0.0.0-20190926060100-f94a56b9ecde/go.mod h1:sPwp0FFboaK/bxsrUz1lNrDMUCsZUsKC5YuM4uRVRVs= github.com/emersion/go-sasl v0.0.0-20200509203442-7bfe0ed36a21/go.mod h1:iL2twTeMvZnrg54ZoPDNfJaJaqy0xIQFuBdrLsmspwQ= @@ -136,6 +139,8 @@ github.com/emersion/go-vcard v0.0.0-20220507122617-d4056df0ec4a/go.mod h1:HMJKR5 github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.13.0 h1:8LOYc1KYPPmyKMuN8QV2DNRWNbLo6LZ0iLs8+mlH53w= github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= +github.com/felixge/fgprof v0.9.3 h1:VvyZxILNuCiUCSXtPtYmmtGvb65nqXh2QFWc0Wpf2/g= +github.com/felixge/fgprof v0.9.3/go.mod h1:RdbpDgzqYVh/T9fPELJyV7EYJuHB55UTEULNun8eiPw= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWTLOJKlh+lOBt6nUQgXAfB7oVIQt5cNreqSLI= github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= @@ -198,6 +203,8 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/ github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd h1:1FjCyPC+syAzJ5/2S8fqdZK1R22vvA0J7JZKcuOIQ7Y= +github.com/google/pprof v0.0.0-20211214055906-6f57359322fd/go.mod h1:KgnwoLYCZ8IQu3XUZ8Nc/bM9CCZFOyjUNOSygVozoDg= github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= @@ -239,12 +246,13 @@ github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ= -github.com/hashicorp/hcl/v2 v2.14.0 h1:jX6+Q38Ly9zaAJlAjnFVyeNSNCKKW8D0wvyg7vij5Wc= -github.com/hashicorp/hcl/v2 v2.14.0/go.mod h1:e4z5nxYlWNPdDSNYX+ph14EvWYMFm3eP0zIUqPc2jr0= +github.com/hashicorp/hcl/v2 v2.16.1 h1:BwuxEMD/tsYgbhIW7UuI3crjovf3MzuFWiVgiv57iHg= +github.com/hashicorp/hcl/v2 v2.16.1/go.mod h1:JRmR89jycNkrrqnMmvPDMd56n1rQJ2Q6KocSLCMCXng= github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/ianlancetaylor/demangle v0.0.0-20210905161508-09a460cdf81d/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w= github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba h1:QFQpJdgbON7I0jr2hYW7Bs+XV0qjc3d5tZoDnRFnqTg= github.com/jaytaylor/html2text v0.0.0-20211105163654-bc68cce691ba/go.mod h1:CVKlgaMiht+LXvHG173ujK6JUhZXKb2u/BQtjPDIvyk= @@ -265,8 +273,8 @@ github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxv github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= +github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= @@ -287,8 +295,8 @@ github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI= -github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= +github.com/mattn/go-sqlite3 v1.14.16 h1:yOQRA0RpS5PFz/oikGwBEqvAWhWg5ufRz4ETLjwpU1Y= +github.com/mattn/go-sqlite3 v1.14.16/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= github.com/miekg/dns v1.1.50 h1:DQUfb9uc6smULcREF09Uc+/Gd46YWqJd5DbpPE9xkcA= @@ -327,8 +335,8 @@ github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= -github.com/pkg/profile v1.6.0 h1:hUDfIISABYI59DyeB3OTay/HxSRwTQ8rB/H83k6r5dM= -github.com/pkg/profile v1.6.0/go.mod h1:qBsxPvzyUincmltOk6iyRVxHYg4adc0OFOv72ZdLa18= +github.com/pkg/profile v1.7.0 h1:hnbDkaNWPCLMO9wGLdBFTIZvzDrDfBM2072E1S9gJkA= +github.com/pkg/profile v1.7.0/go.mod h1:8Uer0jas47ZQMJ7VD+OHknK4YDY07LPUC6dEvqDjvNo= 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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= @@ -380,8 +388,9 @@ github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf h1:pvbZ0lM0XWPBqUKqFU8cma github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf/go.mod h1:RJID2RhlZKId02nZ62WenDCkgHFerpIOmW0iT7GKmXM= 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.4.0 h1:M2gUjqZET1qApGOWNSnZ49BAIMX4F/1plDv3+l31EJ4= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= +github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= +github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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= @@ -389,8 +398,9 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5 github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= -github.com/stretchr/testify v1.8.0 h1:pSgiaMZlXftHpm5L7V1+rVB+AZJydKsMxsQBIJw4PKk= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= +github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk= +github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= @@ -406,14 +416,14 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= -github.com/zclconf/go-cty v1.11.0 h1:726SxLdi2SDnjY+BStqB9J1hNp4+2WlzyXLuimibIe0= -github.com/zclconf/go-cty v1.11.0/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= +github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY= +github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= -go.uber.org/goleak v1.2.0 h1:xqgm/S+aQvhWFTtR0XK3Jvg7z8kGV8P4X14IzwN3Eqk= -go.uber.org/goleak v1.2.0/go.mod h1:XJYK+MuIchqpmGmUSAzotztawfKvYLUIgg7guXrwVUo= +go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= +go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= @@ -434,8 +444,8 @@ golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxT golang.org/x/exp v0.0.0-20190731235908-ec7cb31e5a56/go.mod h1:JhuoJpWY28nO4Vef9tZUw9qufEGTyX1+7lmHxV5q5G4= golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek= golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY= -golang.org/x/exp v0.0.0-20221023144134-a1e5550cf13e h1:SkwG94eNiiYJhbeDE018Grw09HIN/KB9NlRmZsrzfWs= -golang.org/x/exp v0.0.0-20221023144134-a1e5550cf13e/go.mod h1:cyybsKvd6eL0RnXn6p/Grxp8F5bW7iYuBgsNCOHpMYE= +golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb h1:PaBZQdo+iSDyHT053FjUCgZQ/9uqVwPOcl7KSWhKn6w= +golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb/go.mod h1:CxIveKay+FTh1D0yPZemJVgC/95VzuuOLq5Qi4xnoYc= golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js= golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= @@ -444,7 +454,6 @@ golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTk golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= -golang.org/x/lint v0.0.0-20190930215403-16217165b5de h1:5hukYrvBGR8/eNkX5mdUezrA6JiaEZDtJb9Ei+1LlBs= golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= @@ -454,8 +463,8 @@ 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.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s= -golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= +golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= +golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -476,8 +485,8 @@ golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.1.0 h1:hZ/3BUoy5aId7sCpA/Tc5lt8DkFgdVS2onTpJsZ/fl0= -golang.org/x/net v0.1.0/go.mod h1:Cx3nUiGt4eDBEyega/BKRp+/AlGL8hYe7U9odMt2Cco= +golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= +golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -487,8 +496,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.0.0-20220907140024-f12130a52804 h1:0SH2R3f1b1VmIMG7BXbEZCBUu2dKmHschSmjqGUrW8A= -golang.org/x/sync v0.0.0-20220907140024-f12130a52804/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= +golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -518,8 +527,8 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= -golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= +golang.org/x/sys v0.5.0/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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -528,8 +537,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5-0.20201125200606-c27b9fd57aec/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.4.0 h1:BrVqGRd7+k1DiOgtnFvAkoQEWQvBc25ouMJM6429SFg= -golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= +golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= @@ -553,8 +562,8 @@ golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= -golang.org/x/tools v0.1.13-0.20220804200503-81c7dc4e4efa h1:uKcci2q7Qtp6nMTC/AAvfNUAldFtJuHWV9/5QWiypts= -golang.org/x/tools v0.1.13-0.20220804200503-81c7dc4e4efa/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= +golang.org/x/tools v0.3.1-0.20221202221704-aa9f4b2f3d57 h1:/X0t/E4VxbZE7MLS7auvE7YICHeVvbIa9vkOVvYW/24= +golang.org/x/tools v0.3.1-0.20221202221704-aa9f4b2f3d57/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= From 065dcd4d47cf86d385cd76bbe848316e6c57dc87 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Thu, 23 Feb 2023 18:08:23 +0100 Subject: [PATCH 077/130] fix(GODT-2393): improved handling of unrecoverable error. Fix a bug introduced in 265af2d. In the top level exception handler, we may not have add the time to establish connection, so we should not try to use the gRPC service to quit bridge. --- .../bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp | 10 ++++++++++ .../bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h | 1 + 2 files changed, 11 insertions(+) diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp index 8e361031..39bd7d5e 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp @@ -185,6 +185,14 @@ void GRPCClient::connectToServer(QString const &configDir, GRPCConfig const &con } +//**************************************************************************************************************************************************** +/// \return true if the gRPC client is connected to the server. +//**************************************************************************************************************************************************** +bool GRPCClient::isConnected() const { + return stub_.get(); +} + + //**************************************************************************************************************************************************** /// \param[in] clientConfigPath The path to the gRPC client config path.- /// \param[in] serverToken The token obtained from the server config file. @@ -397,6 +405,8 @@ grpc::Status GRPCClient::setIsDoHEnabled(bool enabled) { //**************************************************************************************************************************************************** grpc::Status GRPCClient::quit() { // quitting will shut down the gRPC service, to we may get an 'Unavailable' response for the call + if (!this->isConnected()) + return Status::OK; // We're not even connected, we return OK. This maybe be an attempt to do 'a proper' shutdown after an unrecoverable error. return this->logGRPCCallStatus(stub_->Quit(this->clientContext().get(), empty, &empty), __FUNCTION__, { StatusCode::UNAVAILABLE }); } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h index 9bae4e14..aa69b165 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.h @@ -60,6 +60,7 @@ public: // member functions. GRPCClient &operator=(GRPCClient &&) = delete; ///< Disabled move assignment operator. void setLog(Log *log); ///< Set the log for the client. void connectToServer(QString const &configDir, GRPCConfig const &config, class ProcessMonitor *serverProcess); ///< Establish connection to the gRPC server. + bool isConnected() const; ///< Check whether the gRPC client is connected to the server. grpc::Status checkTokens(QString const &clientConfigPath, QString &outReturnedClientToken); ///< Performs a token check. grpc::Status addLogEntry(Log::Level level, QString const &package, QString const &message); ///< Performs the "AddLogEntry" gRPC call. From 3e878058e7495f458d7e636e68d6e23e896c9845 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Wed, 22 Feb 2023 13:30:45 +0100 Subject: [PATCH 078/130] fix(GODT-2390): Add reports for uncaught json and net.opErr Report to sentry if we see some uncaught network err, but don't force the user logout. If we catch an uncaught json parser error we report the error to sentry and let the user be logged out later. Finally this patch also prints the error type in UserBadEvent sentry report to further help diagnose issues. --- internal/bridge/user_events.go | 15 ++++++++++++++- internal/events/user.go | 11 +++++++++++ internal/user/user.go | 20 ++++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) diff --git a/internal/bridge/user_events.go b/internal/bridge/user_events.go index c0ee71bd..923bd8e5 100644 --- a/internal/bridge/user_events.go +++ b/internal/bridge/user_events.go @@ -56,6 +56,9 @@ func (bridge *Bridge) handleUserEvent(ctx context.Context, user *user.User, even case events.UserBadEvent: bridge.handleUserBadEvent(ctx, user, event.Error) + + case events.UncategorizedEventError: + bridge.handleUncategorizedErrorEvent(event) } return nil @@ -139,7 +142,8 @@ func (bridge *Bridge) handleUserDeauth(ctx context.Context, user *user.User) { func (bridge *Bridge) handleUserBadEvent(ctx context.Context, user *user.User, err error) { safe.Lock(func() { if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle event", reporter.Context{ - "error": err, + "error_type": fmt.Sprintf("%T", err), + "error": err, }); rerr != nil { logrus.WithError(rerr).Error("Failed to report failed event handling") } @@ -147,3 +151,12 @@ func (bridge *Bridge) handleUserBadEvent(ctx context.Context, user *user.User, e bridge.logoutUser(ctx, user, true, false) }, bridge.usersLock) } + +func (bridge *Bridge) handleUncategorizedErrorEvent(event events.UncategorizedEventError) { + if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle due to uncategorized error", reporter.Context{ + "error_type": fmt.Sprintf("%T", event.Error), + "error": event.Error, + }); rerr != nil { + logrus.WithError(rerr).Error("Failed to report failed event handling") + } +} diff --git a/internal/events/user.go b/internal/events/user.go index a2a03188..d94bb5b7 100644 --- a/internal/events/user.go +++ b/internal/events/user.go @@ -179,3 +179,14 @@ type IMAPLoginFailed struct { func (event IMAPLoginFailed) String() string { return fmt.Sprintf("IMAPLoginFailed: Username: %s", event.Username) } + +type UncategorizedEventError struct { + eventBase + + UserID string + Error error +} + +func (event UncategorizedEventError) String() string { + return fmt.Sprintf("UncategorizedEventError: UserID: %s, Source:%T, Error: %s", event.UserID, event.Error, event.Error) +} diff --git a/internal/user/user.go b/internal/user/user.go index 65580dcf..7c58bff7 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -20,9 +20,11 @@ package user import ( "context" "crypto/subtle" + "encoding/json" "errors" "fmt" "io" + "net" "strings" "sync/atomic" "time" @@ -649,6 +651,24 @@ func (user *User) doEventPoll(ctx context.Context) error { return fmt.Errorf("failed to handle event due to network issue: %w", err) } + // Catch all for uncategorized net errors that may slip through. + if netErr := new(net.OpError); errors.As(err, &netErr) { + user.eventCh.Enqueue(events.UncategorizedEventError{ + UserID: user.ID(), + Error: err, + }) + + return fmt.Errorf("failed to handle event due to network issues (uncategorized): %w", err) + } + + // In case a json decode error slips through. + if jsonErr := new(json.UnmarshalTypeError); errors.As(err, &jsonErr) { + user.eventCh.Enqueue(events.UncategorizedEventError{ + UserID: user.ID(), + Error: err, + }) + } + // If the error is a server-side issue, return error to retry later. if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status >= 500 { return fmt.Errorf("failed to handle event due to server error: %w", err) From f8bfbaf36168e5268b7609076b9517e034656bf1 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Fri, 24 Feb 2023 12:45:13 +0100 Subject: [PATCH 079/130] fix(GODT-2390): Missing changes from pervious commit Always reports error type to sentry. Add error checks for get event as well. --- internal/bridge/user_events.go | 18 ++++++++++++++++-- internal/user/user.go | 27 +++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/internal/bridge/user_events.go b/internal/bridge/user_events.go index 923bd8e5..4422b27f 100644 --- a/internal/bridge/user_events.go +++ b/internal/bridge/user_events.go @@ -19,6 +19,7 @@ package bridge import ( "context" + "errors" "fmt" "github.com/ProtonMail/gluon/reporter" @@ -142,7 +143,7 @@ func (bridge *Bridge) handleUserDeauth(ctx context.Context, user *user.User) { func (bridge *Bridge) handleUserBadEvent(ctx context.Context, user *user.User, err error) { safe.Lock(func() { if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle event", reporter.Context{ - "error_type": fmt.Sprintf("%T", err), + "error_type": fmt.Sprintf("%T", getUnwrappedError(err)), "error": err, }); rerr != nil { logrus.WithError(rerr).Error("Failed to report failed event handling") @@ -154,9 +155,22 @@ func (bridge *Bridge) handleUserBadEvent(ctx context.Context, user *user.User, e func (bridge *Bridge) handleUncategorizedErrorEvent(event events.UncategorizedEventError) { if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle due to uncategorized error", reporter.Context{ - "error_type": fmt.Sprintf("%T", event.Error), + "error_type": fmt.Sprintf("%T", getUnwrappedError(event.Error)), "error": event.Error, }); rerr != nil { logrus.WithError(rerr).Error("Failed to report failed event handling") } } + +func getUnwrappedError(err error) error { + for { + unwrapped := errors.Unwrap(err) + if unwrapped == nil { + break + } + + err = unwrapped + } + + return err +} diff --git a/internal/user/user.go b/internal/user/user.go index 7c58bff7..359836ff 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -630,6 +630,33 @@ func (user *User) doEventPoll(ctx context.Context) error { event, err := user.client.GetEvent(ctx, user.vault.EventID()) if err != nil { + if netErr := new(proton.NetError); errors.As(err, &netErr) { + return fmt.Errorf("failed to get event due to network issue: %w", err) + } + + // Catch all for uncategorized net errors that may slip through. + if netErr := new(net.OpError); errors.As(err, &netErr) { + user.eventCh.Enqueue(events.UncategorizedEventError{ + UserID: user.ID(), + Error: err, + }) + + return fmt.Errorf("failed to get event due to network issues (uncategorized): %w", err) + } + + // In case a json decode error slips through. + if jsonErr := new(json.UnmarshalTypeError); errors.As(err, &jsonErr) { + user.eventCh.Enqueue(events.UncategorizedEventError{ + UserID: user.ID(), + Error: err, + }) + } + + // If the error is a server-side issue, return error to retry later. + if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status >= 500 { + return fmt.Errorf("failed to get event due to server error: %w", err) + } + return fmt.Errorf("failed to get event: %w", err) } From 51cbb915139cddaab804445398ce108c59a3a613 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Fri, 24 Feb 2023 15:20:59 +0100 Subject: [PATCH 080/130] Revert GODT-2373 (bridgelib). --- .../bridge-gui-tester/CMakeLists.txt | 44 - .../bridge-gui-tester/GRPCServerWorker.cpp | 4 +- .../bridge-gui-tester/Tabs/SettingsTab.cpp | 3 +- .../bridge-gui/bridge-gui-tester/main.cpp | 3 - .../bridge-gui/bridge-gui/CMakeLists.txt | 46 +- .../bridge-gui/bridge-gui/DeployDarwin.cmake | 3 - .../bridge-gui/bridge-gui/DeployLinux.cmake | 3 - .../bridge-gui/bridge-gui/DeployWindows.cmake | 3 - .../bridge-gui/bridge-gui/LogUtils.cpp | 4 +- .../bridge-gui/bridge-gui/QMLBackend.cpp | 25 +- .../bridge-gui/bridge-gui/QMLBackend.h | 5 +- .../bridge-gui/bridge-gui/SentryUtils.cpp | 15 +- .../frontend/bridge-gui/bridge-gui/main.cpp | 12 +- .../bridge-gui/bridge-gui/qml/Bridge.qml | 2 +- .../bridge-gui/bridge-gui/qml/SetupGuide.qml | 4 +- .../bridge-gui/bridgepp/CMakeLists.txt | 1 - .../bridgepp/bridgepp/BridgeLib.cpp | 226 ----- .../bridge-gui/bridgepp/bridgepp/BridgeLib.h | 36 - .../bridgepp/bridgepp/BridgeUtils.cpp | 115 +++ .../bridgepp/bridgepp/BridgeUtils.h | 5 + .../bridgepp/bridgepp/GRPC/GRPCClient.cpp | 9 + .../bridgepp/bridgepp/GRPC/bridge.grpc.pb.cc | 220 +++-- .../bridgepp/bridgepp/GRPC/bridge.grpc.pb.h | 901 ++++++++++-------- .../bridgepp/bridgepp/GRPC/bridge.pb.cc | 148 +-- internal/frontend/grpc/bridge.pb.go | 536 +++++------ internal/frontend/grpc/bridge.proto | 1 + internal/frontend/grpc/bridge_grpc.pb.go | 36 + internal/frontend/grpc/service_methods.go | 6 + pkg/bridgelib/bridgelib.go | 116 --- pkg/bridgelib/bridgelib_test.go | 38 - 30 files changed, 1210 insertions(+), 1360 deletions(-) delete mode 100644 internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp delete mode 100644 internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.h delete mode 100644 pkg/bridgelib/bridgelib.go delete mode 100644 pkg/bridgelib/bridgelib_test.go diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/CMakeLists.txt b/internal/frontend/bridge-gui/bridge-gui-tester/CMakeLists.txt index 63cd2f94..812dcbc9 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridge-gui-tester/CMakeLists.txt @@ -49,48 +49,6 @@ qt_standard_project_setup() message(STATUS "Using Qt ${Qt6_VERSION}") -#***************************************************************************************************************************************************** -# bridgelib -#***************************************************************************************************************************************************** -find_program(GO_BIN "go") -if (NOT GO_BIN) - message(FATAL_ERROR "Could not location go compiler") -endif() -message(STATUS "go compiler is ${GO_BIN}") - -if (APPLE) # set some env variable for go compiler on macOS. Note the CGO_ENABLED=1 is required when cross-compiling. - if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64") - set(GO_BIN "MACOSX_DEPLOYMENT_TARGET=11.0" "GOARCH=arm64" "CGO_CFLAGS=\"-mmacosx-version-min=11.0\"" CGO_ENABLED=1 ${GO_BIN}) - else () - set(GO_BIN "MACOSX_DEPLOYMENT_TARGET=10.15" "GOARCH=amd64" "CGO_CFLAGS=\"-mmacosx-version-min=10.15\"" CGO_ENABLED=1 ${GO_BIN}) - endif() -endif() - -file(REAL_PATH "pkg/bridgelib" BRIDGELIB_DIR BASE_DIRECTORY "${BRIDGE_REPO_ROOT}") -message(STATUS "bridgelib folder is ${BRIDGELIB_DIR}") - -set(BRIDGELIB_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) -set(BRIDGELIB_BASE_NAME "bridgelib") -if (UNIX AND NOT APPLE) - set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.so") -endif() -if (APPLE) - set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.dylib") -endif() -if (WIN32) - set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.dll") -endif() - -set(BRIDGELIB_OUTPUT_PATH "${BRIDGELIB_OUTPUT_DIR}/${BRIDGELIB_LIB_FILE}") - -add_custom_target( - bridgelib - COMMAND ${GO_BIN} build -o ${BRIDGELIB_OUTPUT_PATH} --buildmode c-shared - WORKING_DIRECTORY ${BRIDGELIB_DIR} - COMMENT "Compile bridgelib library" -) - - #***************************************************************************************************************************************************** # Source files and output #***************************************************************************************************************************************************** @@ -114,8 +72,6 @@ add_executable(bridge-gui-tester UserTable.cpp UserTable.h ) -add_dependencies(bridge-gui-tester bridgelib) - target_precompile_headers(bridge-gui-tester PRIVATE Pch.h) target_include_directories(bridge-gui-tester PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_compile_definitions(bridge-gui-tester PRIVATE BRIDGE_APP_VERSION=\"${BRIDGE_APP_VERSION}\") diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/GRPCServerWorker.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/GRPCServerWorker.cpp index 90045444..118e190b 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/GRPCServerWorker.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/GRPCServerWorker.cpp @@ -19,8 +19,8 @@ #include "GRPCServerWorker.h" #include "Cert.h" #include "GRPCService.h" -#include #include +#include #include #include @@ -81,7 +81,7 @@ void GRPCServerWorker::run() { config.port = port; QString err; - if (!config.save(grpcServerConfigPath(bridgelib::userConfigDir()), &err)) { + if (!config.save(grpcServerConfigPath(bridgepp::userConfigDir()), &err)) { throw Exception(QString("Could not save gRPC server config. %1").arg(err)); } diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/SettingsTab.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/SettingsTab.cpp index c7fe3fbd..e22d1055 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/SettingsTab.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/Tabs/SettingsTab.cpp @@ -18,7 +18,6 @@ #include "SettingsTab.h" #include "GRPCService.h" -#include #include #include @@ -439,7 +438,7 @@ void SettingsTab::resetUI() { this->setClientPlatform("Unknown"); ui_.editVersion->setText(BRIDGE_APP_VERSION); - ui_.comboOS->setCurrentText(bridgelib::goos()); + ui_.comboOS->setCurrentText(bridgepp::goos()); ui_.editCurrentEmailClient->setText("Thunderbird/102.0.3"); ui_.checkShowOnStartup->setChecked(true); ui_.checkShowSplashScreen->setChecked(false); diff --git a/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp b/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp index 6b941491..be65fdfb 100644 --- a/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui-tester/main.cpp @@ -19,7 +19,6 @@ #include "MainWindow.h" #include "AppController.h" #include "GRPCServerWorker.h" -#include #include #include @@ -55,8 +54,6 @@ int main(int argc, char **argv) { QApplication::setOrganizationDomain("proton.ch"); QApplication::setQuitOnLastWindowClosed(true); - bridgelib::loadLibrary(); - Log &log = app().log(); log.setEchoInConsole(true); log.setLevel(Log::Level::Debug); diff --git a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt index 3b7b8e9e..58591bdf 100644 --- a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt @@ -85,49 +85,6 @@ message(STATUS "Using Qt ${Qt6_VERSION}") #***************************************************************************************************************************************************** find_package(sentry CONFIG REQUIRED) - -#***************************************************************************************************************************************************** -# bridgelib -#***************************************************************************************************************************************************** -find_program(GO_BIN "go") -if (NOT GO_BIN) - message(FATAL_ERROR "Could not location go compiler") -endif() -message(STATUS "go compiler is ${GO_BIN}") - -if (APPLE) # set some env variable for go compiler on macOS. Note the CGO_ENABLED=1 is required when cross-compiling. - if (CMAKE_OSX_ARCHITECTURES STREQUAL "arm64") - set(GO_BIN "MACOSX_DEPLOYMENT_TARGET=11.0" "GOARCH=arm64" "CGO_CFLAGS=\"-mmacosx-version-min=11.0\"" CGO_ENABLED=1 ${GO_BIN}) - else () - set(GO_BIN "MACOSX_DEPLOYMENT_TARGET=10.15" "GOARCH=amd64" "CGO_CFLAGS=\"-mmacosx-version-min=10.15\"" CGO_ENABLED=1 ${GO_BIN}) - endif() -endif() - -file(REAL_PATH "pkg/bridgelib" BRIDGELIB_DIR BASE_DIRECTORY "${BRIDGE_REPO_ROOT}") -message(STATUS "bridgelib folder is ${BRIDGELIB_DIR}") - -set(BRIDGELIB_OUTPUT_DIR ${CMAKE_CURRENT_BINARY_DIR}) -set(BRIDGELIB_BASE_NAME "bridgelib") -if (UNIX AND NOT APPLE) - set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.so") -endif() -if (APPLE) - set(BRIDGELIB_OUTPUT_DIR ${BRIDGELIB_OUTPUT_DIR}/${CMAKE_PROJECT_NAME}.app/Contents/MacOS) - set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.dylib") -endif() -if (WIN32) - set(BRIDGELIB_LIB_FILE "${BRIDGELIB_BASE_NAME}.dll") -endif() - -set(BRIDGELIB_OUTPUT_PATH "${BRIDGELIB_OUTPUT_DIR}/${BRIDGELIB_LIB_FILE}") - -add_custom_target( - bridgelib - COMMAND ${GO_BIN} build -o ${BRIDGELIB_OUTPUT_PATH} --buildmode c-shared - WORKING_DIRECTORY ${BRIDGELIB_DIR} - COMMENT "Compile bridgelib library" -) - #***************************************************************************************************************************************************** # Source files and output #***************************************************************************************************************************************************** @@ -152,6 +109,7 @@ add_executable(bridge-gui Resources.qrc AppController.cpp AppController.h BridgeApp.cpp BridgeApp.h + BuildConfig.h CommandLine.cpp CommandLine.h EventStreamWorker.cpp EventStreamWorker.h LogUtils.cpp LogUtils.h @@ -167,8 +125,6 @@ if (APPLE) target_sources(bridge-gui PRIVATE MacOS/SecondInstance.mm MacOS/SecondInstance.h) endif(APPLE) -add_dependencies(bridge-gui bridgelib) - if (WIN32) # on Windows, we add a (non-Qt) resource file that contains the application icon and version information. string(TIMESTAMP BRIDGE_BUILD_YEAR "%Y") set(REGEX_NUMBER "[0123456789]") # CMake matches does not support \d. diff --git a/internal/frontend/bridge-gui/bridge-gui/DeployDarwin.cmake b/internal/frontend/bridge-gui/bridge-gui/DeployDarwin.cmake index 761105cb..ce32255b 100644 --- a/internal/frontend/bridge-gui/bridge-gui/DeployDarwin.cmake +++ b/internal/frontend/bridge-gui/bridge-gui/DeployDarwin.cmake @@ -46,9 +46,6 @@ install(DIRECTORY "${QT_DIR}/lib/QtQuickDialogs2Utils.framework" # PLUGINS install(FILES "${QT_DIR}/plugins/imageformats/libqsvg.dylib" DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/PlugIns/imageformats") -# BRIDGELIB -install(FILES "${BRIDGELIB_OUTPUT_DIR}/${BRIDGELIB_LIB_FILE}" - DESTINATION "${CMAKE_INSTALL_PREFIX}/bridge-gui.app/Contents/MacOS") # crash handler utils ## Build diff --git a/internal/frontend/bridge-gui/bridge-gui/DeployLinux.cmake b/internal/frontend/bridge-gui/bridge-gui/DeployLinux.cmake index 603c9629..10e1ea16 100644 --- a/internal/frontend/bridge-gui/bridge-gui/DeployLinux.cmake +++ b/internal/frontend/bridge-gui/bridge-gui/DeployLinux.cmake @@ -43,9 +43,6 @@ macro( AppendQt6Lib LIB_NAME) AppendLib("${LIB_NAME}" "${QT_DIR}/lib/") endmacro() -# bridgelib -install(FILES ${BRIDGELIB_OUTPUT_PATH} DESTINATION ${CMAKE_INSTALL_PREFIX}) - #Qt6 AppendQt6Lib("libQt6QuickControls2.so.6") AppendQt6Lib("libQt6Quick.so.6") diff --git a/internal/frontend/bridge-gui/bridge-gui/DeployWindows.cmake b/internal/frontend/bridge-gui/bridge-gui/DeployWindows.cmake index 735f9943..85573307 100644 --- a/internal/frontend/bridge-gui/bridge-gui/DeployWindows.cmake +++ b/internal/frontend/bridge-gui/bridge-gui/DeployWindows.cmake @@ -47,9 +47,6 @@ endmacro() # Force plugins to be installed near the exe. install(SCRIPT ${deploy_script}) -# bridgelib -install(FILES ${BRIDGELIB_OUTPUT_PATH} DESTINATION ${CMAKE_INSTALL_PREFIX}) - # Vcpkg DLLs AppendVCPKGLib("abseil_dll.dll") AppendVCPKGLib("cares.dll") diff --git a/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp index 95be99a1..35c1c150 100644 --- a/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp @@ -18,7 +18,7 @@ #include "LogUtils.h" #include "BuildConfig.h" -#include +#include using namespace bridgepp; @@ -28,7 +28,7 @@ using namespace bridgepp; /// \return user logs directory used by bridge. //**************************************************************************************************************************************************** QString userLogsDir() { - QString const path = QDir(bridgelib::userDataDir()).absoluteFilePath("logs"); + QString const path = QDir(bridgepp::userDataDir()).absoluteFilePath("logs"); QDir().mkpath(path); return path; } diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp index f11727ea..c959a3a4 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp @@ -19,7 +19,7 @@ #include "QMLBackend.h" #include "BuildConfig.h" #include "EventStreamWorker.h" -#include +#include #include #include #include @@ -57,7 +57,7 @@ void QMLBackend::init(GRPCConfig const &serviceConfig) { app().grpc().setLog(&log); this->connectGrpcEvents(); - app().grpc().connectToServer(bridgelib::userConfigDir(), serviceConfig, app().bridgeMonitor()); + app().grpc().connectToServer(bridgepp::userConfigDir(), serviceConfig, app().bridgeMonitor()); app().log().info("Connected to backend via gRPC service."); QString bridgeVer; @@ -74,6 +74,7 @@ void QMLBackend::init(GRPCConfig const &serviceConfig) { }); // Grab from bridge the value that will not change during the execution of this app (or that will only change locally). + app().grpc().goos(goos_); app().grpc().logsPath(logsPath_); app().grpc().licensePath(licensePath_); bool sslForIMAP = false, sslForSMTP = false; @@ -151,16 +152,6 @@ bool QMLBackend::areSameFileOrFolder(QUrl const &lhs, QUrl const &rhs) const { } -//**************************************************************************************************************************************************** -// -//**************************************************************************************************************************************************** -QString QMLBackend::goOS() { - HANDLE_EXCEPTION_RETURN_QSTRING( - return bridgelib::goos(); - ) -} - - //**************************************************************************************************************************************************** /// \return The value for the 'showOnStartup' property. //**************************************************************************************************************************************************** @@ -186,6 +177,16 @@ void QMLBackend::setShowSplashScreen(bool show) { } +//**************************************************************************************************************************************************** +/// \return The value for the 'GOOS' property. +//**************************************************************************************************************************************************** +QString QMLBackend::goos() const { + HANDLE_EXCEPTION_RETURN_QSTRING( + return goos_; + ) +} + + //**************************************************************************************************************************************************** /// \return The value for the 'showSplashScreen' property. //**************************************************************************************************************************************************** diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h index db3c5adb..d5ff668b 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h @@ -50,11 +50,11 @@ public: // member functions. Q_INVOKABLE bool isPortFree(int port) const; ///< Check if a given network port is available. Q_INVOKABLE QString nativePath(QUrl const &url) const; ///< Retrieve the native path of a local URL. Q_INVOKABLE bool areSameFileOrFolder(QUrl const &lhs, QUrl const &rhs) const; ///< Check if two local URL point to the same file. - Q_INVOKABLE QString goOS(); ///< Return the OS string from golang's runtime.GOOS. public: // Qt/QML properties. Note that the NOTIFY-er signal is required even for read-only properties (QML warning otherwise) Q_PROPERTY(bool showOnStartup READ showOnStartup NOTIFY showOnStartupChanged) Q_PROPERTY(bool showSplashScreen READ showSplashScreen WRITE setShowSplashScreen NOTIFY showSplashScreenChanged) + Q_PROPERTY(QString goos READ goos NOTIFY goosChanged) Q_PROPERTY(QUrl logsPath READ logsPath NOTIFY logsPathChanged) Q_PROPERTY(QUrl licensePath READ licensePath NOTIFY licensePathChanged) Q_PROPERTY(QUrl releaseNotesLink READ releaseNotesLink NOTIFY releaseNotesLinkChanged) @@ -86,6 +86,7 @@ public: // Qt/QML properties. Note that the NOTIFY-er signal is required even fo bool showOnStartup() const; ///< Getter for the 'showOnStartup' property. void setShowSplashScreen(bool show); ///< Setter for the 'showSplashScreen' property. bool showSplashScreen() const; ///< Getter for the 'showSplashScreen' property. + QString goos() const; ///< Getter for the 'GOOS' property. QUrl logsPath() const; ///< Getter for the 'logsPath' property. QUrl licensePath() const; ///< Getter for the 'licensePath' property. QUrl releaseNotesLink() const;///< Getter for the 'releaseNotesLink' property. @@ -119,6 +120,7 @@ public: // Qt/QML properties. Note that the NOTIFY-er signal is required even fo signals: // Signal used by the Qt property system. Many of them are unused but required to avoid warning from the QML engine. void showSplashScreenChanged(bool value); /// eventStreamOverseer_; ///< The event stream overseer. bool showSplashScreen_ { false }; ///< The cached version of show splash screen. Retrieved on startup from bridge, and potentially modified locally. + QString goos_; ///< The cached version of the GOOS variable. QUrl logsPath_; ///< The logs path. Retrieved from bridge on startup. QUrl licensePath_; ///< The license path. Retrieved from bridge on startup. int imapPort_ { 0 }; ///< The cached value for the IMAP port. diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index c5924833..3fe152f0 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -17,7 +17,6 @@ #include "SentryUtils.h" #include "BuildConfig.h" -#include #include @@ -27,18 +26,6 @@ using namespace bridgepp; static constexpr const char *LoggerName = "bridge-gui"; -//**************************************************************************************************************************************************** -/// \brief Get the path of the sentry cache folder. -/// -/// \return sentry cache directory used by bridge. -//**************************************************************************************************************************************************** -QString sentryCacheDir() { - QString const path = QDir(bridgelib::userDataDir()).absoluteFilePath("sentry_cache"); - QDir().mkpath(path); - return path; -} - - //**************************************************************************************************************************************************** /// \brief Get a hash of the computer's host name //**************************************************************************************************************************************************** @@ -88,7 +75,7 @@ void initSentry() { // //**************************************************************************************************************************************************** void setSentryReportScope() { - sentry_set_tag("OS", bridgelib::goos().toUtf8()); + sentry_set_tag("OS", bridgepp::goos().toUtf8()); sentry_set_tag("Client", PROJECT_FULL_NAME); sentry_set_tag("Version", PROJECT_REVISION); sentry_set_tag("HostArch", QSysInfo::currentCpuArchitecture().toUtf8()); diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 1b0338bb..03cd64d1 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -23,7 +23,6 @@ #include "QMLBackend.h" #include "SentryUtils.h" #include "BuildConfig.h" -#include #include #include #include @@ -158,7 +157,7 @@ QUrl getApiUrl() { url.setPort(1042); // override with what can be found in the prefs.json file. - QFile prefFile(QString("%1/%2").arg(bridgelib::userConfigDir(), "prefs.json")); + QFile prefFile(QString("%1/%2").arg(bridgepp::userConfigDir(), "prefs.json")); if (prefFile.exists()) { prefFile.open(QIODevice::ReadOnly | QIODevice::Text); QByteArray data = prefFile.readAll(); @@ -186,7 +185,7 @@ QUrl getApiUrl() { /// \return true if an instance of bridge is already running. //**************************************************************************************************************************************************** bool isBridgeRunning() { - QLockFile lockFile(QDir(bridgelib::userCacheDir()).absoluteFilePath(bridgeLock)); + QLockFile lockFile(QDir(bridgepp::userCacheDir()).absoluteFilePath(bridgeLock)); return (!lockFile.tryLock()) && (lockFile.error() == QLockFile::LockFailedError); } @@ -198,7 +197,7 @@ void focusOtherInstance() { try { FocusGRPCClient client; GRPCConfig sc; - QString const path = FocusGRPCClient::grpcFocusServerConfigPath(bridgelib::userConfigDir()); + QString const path = FocusGRPCClient::grpcFocusServerConfigPath(bridgepp::userConfigDir()); QFile file(path); if (file.exists()) { if (!sc.load(path)) { @@ -277,8 +276,7 @@ int main(int argc, char *argv[]) { BridgeApp guiApp(argc, argv); try { - bridgelib::loadLibrary(); - QString const& configDir = bridgelib::userConfigDir(); + QString const& configDir = bridgepp::userConfigDir(); // Init sentry. initSentry(); @@ -290,7 +288,7 @@ int main(int argc, char *argv[]) { Log &log = initLog(); - QLockFile lock(bridgelib::userCacheDir() + "/" + bridgeGUILock); + QLockFile lock(bridgepp::userCacheDir() + "/" + bridgeGUILock); if (!checkSingleInstance(lock)) { focusOtherInstance(); return EXIT_FAILURE; diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/Bridge.qml b/internal/frontend/bridge-gui/bridge-gui/qml/Bridge.qml index 1c990a00..8d116b3a 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/Bridge.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/Bridge.qml @@ -231,7 +231,7 @@ QtObject { } function getTrayIconPath() { - var color = Backend.goOS() == "darwin" ? "mono" : "color" + var color = Backend.goos == "darwin" ? "mono" : "color" var level = "norm" if (_systrayfilter.topmost) { diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/SetupGuide.qml b/internal/frontend/bridge-gui/bridge-gui/qml/SetupGuide.qml index 33ade9e6..f0d4e6b5 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/SetupGuide.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/SetupGuide.qml @@ -45,7 +45,7 @@ Item { property string link: "https://proton.me/support/protonmail-bridge-clients-apple-mail" Component.onCompleted : { - if (Backend.goOS() == "darwin") { + if (Backend.goos == "darwin") { append({ "name" : "Apple Mail", "iconSource" : "/qml/icons/ic-apple-mail.svg", @@ -59,7 +59,7 @@ Item { "link" : "https://proton.me/support/protonmail-bridge-clients-macos-outlook-2019" }) } - if (Backend.goOS() == "windows") { + if (Backend.goos == "windows") { append({ "name" : "Microsoft Outlook", "iconSource" : "/qml/icons/ic-microsoft-outlook.svg", diff --git a/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt b/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt index 363c3bd2..3b3ed991 100644 --- a/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt @@ -135,7 +135,6 @@ add_custom_command( add_library(bridgepp - bridgepp/BridgeLib.cpp bridgepp/BridgeLib.h bridgepp/BridgeUtils.cpp bridgepp/BridgeUtils.h bridgepp/Exception/Exception.h bridgepp/Exception/Exception.cpp bridgepp/GRPC/GRPCClient.cpp bridgepp/GRPC/GRPCClient.h diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp deleted file mode 100644 index 8acf9e7f..00000000 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.cpp +++ /dev/null @@ -1,226 +0,0 @@ -// Copyright (c) 2023 Proton AG -// -// This file is part of Proton Mail Bridge. -// -// Proton Mail Bridge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Proton Mail Bridge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Proton Mail Bridge. If not, see . - - -#include "BridgeLib.h" -#include -#include - - -using namespace bridgepp; - -#ifdef __cplusplus -extern "C" { -#endif - - -typedef char *(*FuncReturningCString)(); - - -#ifdef __cplusplus -} -#endif - - -namespace { - - -FuncReturningCString goosFunc = nullptr; ///< A pointer to the dynamically loaded GoOS function. -FuncReturningCString userCacheDirFunc = nullptr; ///< A pointer to the dynamically loaded UserCache function. -FuncReturningCString userConfigDirFunc = nullptr; ///< A pointer to the dynamically loaded UserConfig function. -FuncReturningCString userDataDirFunc = nullptr; ///< A pointer to the dynamically loaded UserData function. -void (*deleteCStringFunc)(char *) = nullptr; ///< A pointer to the deleteCString function. - - -#if defined(Q_OS_WINDOWS) -#include -typedef HINSTANCE LibHandle; -#else -typedef void *LibHandle; -#endif - - -LibHandle loadDynamicLibrary(QString const &path); ///< Load a dynamic library. -void *getFuncPointer(LibHandle lib, QString const &funcName); ///< Retrieve a function pointer from a dynamic library. - - -//**************************************************************************************************************************************************** -/// \return The path to the bridgelib library file. -//**************************************************************************************************************************************************** -QString bridgelibPath() { - QString const path = QDir(QCoreApplication::applicationDirPath()).absoluteFilePath("bridgelib."); - switch (os()) { - case OS::Windows: - return path + "dll"; - case OS::MacOS: - return path + "dylib"; - case OS::Linux: - default: - return path + "so"; - } -} - - -#if defined(Q_OS_WINDOWS) - - -//**************************************************************************************************************************************************** -/// \param[in] path The path of the library file. -/// \return A pointer to the library object -//**************************************************************************************************************************************************** -LibHandle loadDynamicLibrary(QString const &path) { - if (!QFileInfo::exists(path)) { - throw Exception(QString("The dynamic library file bridgelib.dylib could not be found at '%1'.").arg(path)); - } - - LibHandle handle = LoadLibrary(reinterpret_cast(path.toStdWString().c_str())); - if (!handle) { - throw Exception(QString("The bridgelib dynamic library file '%1' could not be opened.").arg(path)); - } - - return handle; -} - - -//**************************************************************************************************************************************************** -/// \param[in] lib A handle to the library -/// \param[in] funcName The name of the function. -/// \return A pointer to the function -//**************************************************************************************************************************************************** -void *getFuncPointer(LibHandle lib, QString const &funcName) { - void *pointer = reinterpret_cast(GetProcAddress(lib, funcName.toLocal8Bit())); - if (!pointer) - throw Exception(QString("Could not locate function %1 in bridgelib dynamic library").arg(funcName)); - - return pointer; -} - -#else - - -#include - - -//**************************************************************************************************************************************************** -/// \param[in] path The path of the library file. -/// \return A pointer to the library object -//**************************************************************************************************************************************************** -void *loadDynamicLibrary(QString const &path) { - if (!QFileInfo::exists(path)) { - throw Exception(QString("The dynamic library file bridgelib.dylib could not be found at '%1'.").arg(path)); - } - - void *lib = dlopen(path.toLocal8Bit().data(), RTLD_LAZY); - if (!lib) { - throw Exception(QString("The bridgelib dynamic library file '%1' could not be opened.").arg(path)); - } - - return lib; -} - - -//**************************************************************************************************************************************************** -/// \param[in] lib A handle to the library -/// \param[in] funcName The name of the function. -/// \return A pointer to the function -//**************************************************************************************************************************************************** -void *getFuncPointer(LibHandle lib, QString const &funcName) { - void *pointer = dlsym(lib, funcName.toLocal8Bit()); - if (!pointer) { - throw Exception(QString("Could not locate function %1 in bridgelib dynamic library").arg(funcName)); - } - - return pointer; -} - - -#endif // defined(Q_OS_WINDOWS) - - -} - - -namespace bridgelib { - - -//**************************************************************************************************************************************************** -// -//**************************************************************************************************************************************************** -void loadLibrary() { - try { - LibHandle lib = loadDynamicLibrary(bridgelibPath()); - goosFunc = reinterpret_cast(getFuncPointer(lib, "GoOS")); - userCacheDirFunc = reinterpret_cast(getFuncPointer(lib, "UserCacheDir")); - userConfigDirFunc = reinterpret_cast(getFuncPointer(lib, "UserConfigDir")); - userDataDirFunc = reinterpret_cast(getFuncPointer(lib, "UserDataDir")); - deleteCStringFunc = reinterpret_cast(getFuncPointer(lib, "DeleteCString")); - - } catch (Exception const &e) { - throw Exception("Error loading the bridgelib dynamic library file.", e.qwhat()); - } -} - - -//**************************************************************************************************************************************************** -/// \brief Converts a C-style string returned by a go library function to a QString, and release the memory allocated for the C-style string. -/// \param[in] cString The C-style string, in UTF-8 format. -/// \return A QString. -//**************************************************************************************************************************************************** -QString goToQString(char *const cString) { - if (!cString) { - return QString(); - } - QString const result = QString::fromUtf8(cString); - deleteCStringFunc(cString); - - return result; -} - - -//**************************************************************************************************************************************************** -/// \return The value of the Go runtime.GOOS constant. -//**************************************************************************************************************************************************** -QString goos() { - return goToQString(goosFunc()); -} - - -//**************************************************************************************************************************************************** -/// \return The path to the user cache folder. -//**************************************************************************************************************************************************** -QString userCacheDir() { - return goToQString(userCacheDirFunc()); -} - - -//**************************************************************************************************************************************************** -/// \return The path to the user cache folder. -//**************************************************************************************************************************************************** -QString userConfigDir() { - return goToQString(userConfigDirFunc()); -} - - -//**************************************************************************************************************************************************** -/// \return The path to the user data folder. -//**************************************************************************************************************************************************** -QString userDataDir() { - return goToQString(userDataDirFunc()); -} - - -} \ No newline at end of file diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.h deleted file mode 100644 index 2c24b39e..00000000 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeLib.h +++ /dev/null @@ -1,36 +0,0 @@ -// Copyright (c) 2023 Proton AG -// -// This file is part of Proton Mail Bridge. -// -// Proton Mail Bridge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Proton Mail Bridge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Proton Mail Bridge. If not, see . - - -#ifndef BRIDGE_GUI_BRIDGELIB_H -#define BRIDGE_GUI_BRIDGELIB_H - - -namespace bridgelib { - - -void loadLibrary(); -QString goos(); -QString userCacheDir(); -QString userConfigDir(); -QString userDataDir(); - - -} // namespace bridgelib - - -#endif //BRIDGE_GUI_BRIDGELIB_H diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp index a2f323bf..195c8ffe 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp @@ -65,6 +65,121 @@ std::mt19937_64 &rng() { } // anonymous namespace +//**************************************************************************************************************************************************** +/// \return user configuration directory used by bridge (based on Golang OS/File's UserConfigDir). +//**************************************************************************************************************************************************** +QString userConfigDir() { + QString dir; +#ifdef Q_OS_WIN + dir = qgetenv ("AppData"); + if (dir.isEmpty()) + throw Exception("%AppData% is not defined."); +#elif defined(Q_OS_IOS) || defined(Q_OS_DARWIN) + dir = qgetenv("HOME"); + if (dir.isEmpty()) { + throw Exception("$HOME is not defined."); + } + dir += "/Library/Application Support"; +#else + dir = qgetenv ("XDG_CONFIG_HOME"); + if (dir.isEmpty()) + { + dir = qgetenv ("HOME"); + if (dir.isEmpty()) + throw Exception("neither $XDG_CONFIG_HOME nor $HOME are defined"); + dir += "/.config"; + } +#endif + QString const folder = QDir(dir).absoluteFilePath(configFolder); + QDir().mkpath(folder); + + return folder; +} + + +//**************************************************************************************************************************************************** +/// \return user cache directory used by bridge (based on Golang OS/File's UserCacheDir). +//**************************************************************************************************************************************************** +QString userCacheDir() { + QString dir; + +#ifdef Q_OS_WIN + dir = qgetenv ("LocalAppData"); + if (dir.isEmpty()) + throw Exception("%LocalAppData% is not defined."); +#elif defined(Q_OS_IOS) || defined(Q_OS_DARWIN) + dir = qgetenv("HOME"); + if (dir.isEmpty()) { + throw Exception("$HOME is not defined."); + } + dir += "/Library/Caches"; +#else + dir = qgetenv ("XDG_CACHE_HOME"); + if (dir.isEmpty()) + { + dir = qgetenv ("HOME"); + if (dir.isEmpty()) + throw Exception("neither $XDG_CACHE_HOME nor $HOME are defined"); + dir += "/.cache"; + } +#endif + + QString const folder = QDir(dir).absoluteFilePath(configFolder); + QDir().mkpath(folder); + + return folder; +} + + +//**************************************************************************************************************************************************** +/// \return user data directory used by bridge (based on Golang OS/File's UserDataDir). +//**************************************************************************************************************************************************** +QString userDataDir() { + QString folder; + +#ifdef Q_OS_LINUX + QString dir = qgetenv ("XDG_DATA_HOME"); + if (dir.isEmpty()) + { + dir = qgetenv ("HOME"); + if (dir.isEmpty()) + throw Exception("neither $XDG_DATA_HOME nor $HOME are defined"); + dir += "/.local/share"; + } + folder = QDir(dir).absoluteFilePath(configFolder); + QDir().mkpath(folder); +#else + folder = userConfigDir(); +#endif + + return folder; +} + + +//**************************************************************************************************************************************************** +/// \return sentry cache directory used by bridge. +//**************************************************************************************************************************************************** +QString sentryCacheDir() { + QString const path = QDir(userDataDir()).absoluteFilePath("sentry_cache"); + QDir().mkpath(path); + return path; +} + + +//**************************************************************************************************************************************************** +/// \return The value GOOS would return for the current platform. +//**************************************************************************************************************************************************** +QString goos() { +#if defined(Q_OS_DARWIN) + return "darwin"; +#elif defined(Q_OS_WINDOWS) + return "windows"; +#else + return "linux"; +#endif +} + + //**************************************************************************************************************************************************** /// Slow, but not biased. Not for use in crypto functions though, as the RNG use std::random_device as a seed. /// diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h index ba19fe12..629e1e01 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.h @@ -36,6 +36,11 @@ enum class OS { }; +QString userConfigDir(); ///< Get the path of the user configuration folder. +QString userCacheDir(); ///< Get the path of the user cache folder. +QString userDataDir(); ///< Get the path of the user data folder. +QString sentryCacheDir(); ///< Get the path of the sentry cache folder. +QString goos(); ///< return the value of Go's GOOS for the current platform ("darwin", "linux" and "windows" are supported). qint64 randN(qint64 n); ///< return a random integer in the half open range [0,n) QString randomFirstName(); ///< Get a random first name from a pre-determined list. QString randomLastName(); ///< Get a random first name from a pre-determined list. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp index 39bd7d5e..96620169 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp @@ -479,6 +479,15 @@ grpc::Status GRPCClient::logsPath(QUrl &outPath) { } +//**************************************************************************************************************************************************** +/// \param[out] outGoos The value for the property. +/// \return The status for the gRPC call. +//**************************************************************************************************************************************************** +grpc::Status GRPCClient::goos(QString &outGoos) { + return this->logGRPCCallStatus(this->getString(&Bridge::Stub::GoOs, outGoos), __FUNCTION__); +} + + //**************************************************************************************************************************************************** /// \param[out] outPath The value for the property. /// \return The status for the gRPC call. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.cc b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.cc index a6dad038..51b4968b 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.cc +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.cc @@ -34,6 +34,7 @@ static const char* Bridge_method_names[] = { "/grpc.Bridge/IsBetaEnabled", "/grpc.Bridge/SetIsAllMailVisible", "/grpc.Bridge/IsAllMailVisible", + "/grpc.Bridge/GoOs", "/grpc.Bridge/TriggerReset", "/grpc.Bridge/Version", "/grpc.Bridge/LogsPath", @@ -96,47 +97,48 @@ Bridge::Stub::Stub(const std::shared_ptr< ::grpc::ChannelInterface>& channel, co , rpcmethod_IsBetaEnabled_(Bridge_method_names[9], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) , rpcmethod_SetIsAllMailVisible_(Bridge_method_names[10], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) , rpcmethod_IsAllMailVisible_(Bridge_method_names[11], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_TriggerReset_(Bridge_method_names[12], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_Version_(Bridge_method_names[13], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_LogsPath_(Bridge_method_names[14], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_LicensePath_(Bridge_method_names[15], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ReleaseNotesPageLink_(Bridge_method_names[16], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_DependencyLicensesLink_(Bridge_method_names[17], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_LandingPageLink_(Bridge_method_names[18], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetColorSchemeName_(Bridge_method_names[19], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ColorSchemeName_(Bridge_method_names[20], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_CurrentEmailClient_(Bridge_method_names[21], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ReportBug_(Bridge_method_names[22], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ExportTLSCertificates_(Bridge_method_names[23], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ForceLauncher_(Bridge_method_names[24], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetMainExecutable_(Bridge_method_names[25], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_Login_(Bridge_method_names[26], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_Login2FA_(Bridge_method_names[27], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_Login2Passwords_(Bridge_method_names[28], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_LoginAbort_(Bridge_method_names[29], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_CheckUpdate_(Bridge_method_names[30], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_InstallUpdate_(Bridge_method_names[31], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetIsAutomaticUpdateOn_(Bridge_method_names[32], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_IsAutomaticUpdateOn_(Bridge_method_names[33], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_DiskCachePath_(Bridge_method_names[34], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetDiskCachePath_(Bridge_method_names[35], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetIsDoHEnabled_(Bridge_method_names[36], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_IsDoHEnabled_(Bridge_method_names[37], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_MailServerSettings_(Bridge_method_names[38], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetMailServerSettings_(Bridge_method_names[39], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_Hostname_(Bridge_method_names[40], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_IsPortFree_(Bridge_method_names[41], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_AvailableKeychains_(Bridge_method_names[42], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetCurrentKeychain_(Bridge_method_names[43], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_CurrentKeychain_(Bridge_method_names[44], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_GetUserList_(Bridge_method_names[45], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_GetUser_(Bridge_method_names[46], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_SetUserSplitMode_(Bridge_method_names[47], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_LogoutUser_(Bridge_method_names[48], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_RemoveUser_(Bridge_method_names[49], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_ConfigureUserAppleMail_(Bridge_method_names[50], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) - , rpcmethod_RunEventStream_(Bridge_method_names[51], options.suffix_for_stats(),::grpc::internal::RpcMethod::SERVER_STREAMING, channel) - , rpcmethod_StopEventStream_(Bridge_method_names[52], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_GoOs_(Bridge_method_names[12], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_TriggerReset_(Bridge_method_names[13], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Version_(Bridge_method_names[14], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_LogsPath_(Bridge_method_names[15], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_LicensePath_(Bridge_method_names[16], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ReleaseNotesPageLink_(Bridge_method_names[17], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_DependencyLicensesLink_(Bridge_method_names[18], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_LandingPageLink_(Bridge_method_names[19], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetColorSchemeName_(Bridge_method_names[20], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ColorSchemeName_(Bridge_method_names[21], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_CurrentEmailClient_(Bridge_method_names[22], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ReportBug_(Bridge_method_names[23], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ExportTLSCertificates_(Bridge_method_names[24], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ForceLauncher_(Bridge_method_names[25], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetMainExecutable_(Bridge_method_names[26], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Login_(Bridge_method_names[27], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Login2FA_(Bridge_method_names[28], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Login2Passwords_(Bridge_method_names[29], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_LoginAbort_(Bridge_method_names[30], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_CheckUpdate_(Bridge_method_names[31], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_InstallUpdate_(Bridge_method_names[32], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetIsAutomaticUpdateOn_(Bridge_method_names[33], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_IsAutomaticUpdateOn_(Bridge_method_names[34], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_DiskCachePath_(Bridge_method_names[35], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetDiskCachePath_(Bridge_method_names[36], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetIsDoHEnabled_(Bridge_method_names[37], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_IsDoHEnabled_(Bridge_method_names[38], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_MailServerSettings_(Bridge_method_names[39], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetMailServerSettings_(Bridge_method_names[40], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_Hostname_(Bridge_method_names[41], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_IsPortFree_(Bridge_method_names[42], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_AvailableKeychains_(Bridge_method_names[43], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetCurrentKeychain_(Bridge_method_names[44], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_CurrentKeychain_(Bridge_method_names[45], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_GetUserList_(Bridge_method_names[46], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_GetUser_(Bridge_method_names[47], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_SetUserSplitMode_(Bridge_method_names[48], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_LogoutUser_(Bridge_method_names[49], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_RemoveUser_(Bridge_method_names[50], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_ConfigureUserAppleMail_(Bridge_method_names[51], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) + , rpcmethod_RunEventStream_(Bridge_method_names[52], options.suffix_for_stats(),::grpc::internal::RpcMethod::SERVER_STREAMING, channel) + , rpcmethod_StopEventStream_(Bridge_method_names[53], options.suffix_for_stats(),::grpc::internal::RpcMethod::NORMAL_RPC, channel) {} ::grpc::Status Bridge::Stub::CheckTokens(::grpc::ClientContext* context, const ::google::protobuf::StringValue& request, ::google::protobuf::StringValue* response) { @@ -415,6 +417,29 @@ void Bridge::Stub::async::IsAllMailVisible(::grpc::ClientContext* context, const return result; } +::grpc::Status Bridge::Stub::GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::StringValue* response) { + return ::grpc::internal::BlockingUnaryCall< ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_GoOs_, context, request, response); +} + +void Bridge::Stub::async::GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, std::function f) { + ::grpc::internal::CallbackUnaryCall< ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GoOs_, context, request, response, std::move(f)); +} + +void Bridge::Stub::async::GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, ::grpc::ClientUnaryReactor* reactor) { + ::grpc::internal::ClientCallbackUnaryFactory::Create< ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(stub_->channel_.get(), stub_->rpcmethod_GoOs_, context, request, response, reactor); +} + +::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>* Bridge::Stub::PrepareAsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { + return ::grpc::internal::ClientAsyncResponseReaderHelper::Create< ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), cq, rpcmethod_GoOs_, context, request); +} + +::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>* Bridge::Stub::AsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { + auto* result = + this->PrepareAsyncGoOsRaw(context, request, cq); + result->StartCall(); + return result; +} + ::grpc::Status Bridge::Stub::TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::Empty* response) { return ::grpc::internal::BlockingUnaryCall< ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>(channel_.get(), rpcmethod_TriggerReset_, context, request, response); } @@ -1475,6 +1500,16 @@ Bridge::Service::Service() { AddMethod(new ::grpc::internal::RpcServiceMethod( Bridge_method_names[12], ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](Bridge::Service* service, + ::grpc::ServerContext* ctx, + const ::google::protobuf::Empty* req, + ::google::protobuf::StringValue* resp) { + return service->GoOs(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + Bridge_method_names[13], + ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, ::grpc::ServerContext* ctx, @@ -1482,16 +1517,6 @@ Bridge::Service::Service() { ::google::protobuf::Empty* resp) { return service->TriggerReset(ctx, req, resp); }, this))); - AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[13], - ::grpc::internal::RpcMethod::NORMAL_RPC, - new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( - [](Bridge::Service* service, - ::grpc::ServerContext* ctx, - const ::google::protobuf::Empty* req, - ::google::protobuf::StringValue* resp) { - return service->Version(ctx, req, resp); - }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( Bridge_method_names[14], ::grpc::internal::RpcMethod::NORMAL_RPC, @@ -1500,7 +1525,7 @@ Bridge::Service::Service() { ::grpc::ServerContext* ctx, const ::google::protobuf::Empty* req, ::google::protobuf::StringValue* resp) { - return service->LogsPath(ctx, req, resp); + return service->Version(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( Bridge_method_names[15], @@ -1510,7 +1535,7 @@ Bridge::Service::Service() { ::grpc::ServerContext* ctx, const ::google::protobuf::Empty* req, ::google::protobuf::StringValue* resp) { - return service->LicensePath(ctx, req, resp); + return service->LogsPath(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( Bridge_method_names[16], @@ -1520,7 +1545,7 @@ Bridge::Service::Service() { ::grpc::ServerContext* ctx, const ::google::protobuf::Empty* req, ::google::protobuf::StringValue* resp) { - return service->ReleaseNotesPageLink(ctx, req, resp); + return service->LicensePath(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( Bridge_method_names[17], @@ -1530,7 +1555,7 @@ Bridge::Service::Service() { ::grpc::ServerContext* ctx, const ::google::protobuf::Empty* req, ::google::protobuf::StringValue* resp) { - return service->DependencyLicensesLink(ctx, req, resp); + return service->ReleaseNotesPageLink(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( Bridge_method_names[18], @@ -1540,11 +1565,21 @@ Bridge::Service::Service() { ::grpc::ServerContext* ctx, const ::google::protobuf::Empty* req, ::google::protobuf::StringValue* resp) { - return service->LandingPageLink(ctx, req, resp); + return service->DependencyLicensesLink(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( Bridge_method_names[19], ::grpc::internal::RpcMethod::NORMAL_RPC, + new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( + [](Bridge::Service* service, + ::grpc::ServerContext* ctx, + const ::google::protobuf::Empty* req, + ::google::protobuf::StringValue* resp) { + return service->LandingPageLink(ctx, req, resp); + }, this))); + AddMethod(new ::grpc::internal::RpcServiceMethod( + Bridge_method_names[20], + ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, ::grpc::ServerContext* ctx, @@ -1553,7 +1588,7 @@ Bridge::Service::Service() { return service->SetColorSchemeName(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[20], + Bridge_method_names[21], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1563,7 +1598,7 @@ Bridge::Service::Service() { return service->ColorSchemeName(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[21], + Bridge_method_names[22], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1573,7 +1608,7 @@ Bridge::Service::Service() { return service->CurrentEmailClient(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[22], + Bridge_method_names[23], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::ReportBugRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1583,7 +1618,7 @@ Bridge::Service::Service() { return service->ReportBug(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[23], + Bridge_method_names[24], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1593,7 +1628,7 @@ Bridge::Service::Service() { return service->ExportTLSCertificates(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[24], + Bridge_method_names[25], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1603,7 +1638,7 @@ Bridge::Service::Service() { return service->ForceLauncher(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[25], + Bridge_method_names[26], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1613,7 +1648,7 @@ Bridge::Service::Service() { return service->SetMainExecutable(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[26], + Bridge_method_names[27], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::LoginRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1623,7 +1658,7 @@ Bridge::Service::Service() { return service->Login(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[27], + Bridge_method_names[28], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::LoginRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1633,7 +1668,7 @@ Bridge::Service::Service() { return service->Login2FA(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[28], + Bridge_method_names[29], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::LoginRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1643,7 +1678,7 @@ Bridge::Service::Service() { return service->Login2Passwords(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[29], + Bridge_method_names[30], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::LoginAbortRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1653,7 +1688,7 @@ Bridge::Service::Service() { return service->LoginAbort(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[30], + Bridge_method_names[31], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1663,7 +1698,7 @@ Bridge::Service::Service() { return service->CheckUpdate(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[31], + Bridge_method_names[32], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1673,7 +1708,7 @@ Bridge::Service::Service() { return service->InstallUpdate(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[32], + Bridge_method_names[33], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::BoolValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1683,7 +1718,7 @@ Bridge::Service::Service() { return service->SetIsAutomaticUpdateOn(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[33], + Bridge_method_names[34], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::BoolValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1693,7 +1728,7 @@ Bridge::Service::Service() { return service->IsAutomaticUpdateOn(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[34], + Bridge_method_names[35], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1703,7 +1738,7 @@ Bridge::Service::Service() { return service->DiskCachePath(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[35], + Bridge_method_names[36], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1713,7 +1748,7 @@ Bridge::Service::Service() { return service->SetDiskCachePath(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[36], + Bridge_method_names[37], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::BoolValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1723,7 +1758,7 @@ Bridge::Service::Service() { return service->SetIsDoHEnabled(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[37], + Bridge_method_names[38], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::BoolValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1733,7 +1768,7 @@ Bridge::Service::Service() { return service->IsDoHEnabled(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[38], + Bridge_method_names[39], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::grpc::ImapSmtpSettings, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1743,7 +1778,7 @@ Bridge::Service::Service() { return service->MailServerSettings(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[39], + Bridge_method_names[40], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::ImapSmtpSettings, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1753,7 +1788,7 @@ Bridge::Service::Service() { return service->SetMailServerSettings(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[40], + Bridge_method_names[41], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1763,7 +1798,7 @@ Bridge::Service::Service() { return service->Hostname(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[41], + Bridge_method_names[42], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Int32Value, ::google::protobuf::BoolValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1773,7 +1808,7 @@ Bridge::Service::Service() { return service->IsPortFree(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[42], + Bridge_method_names[43], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::grpc::AvailableKeychainsResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1783,7 +1818,7 @@ Bridge::Service::Service() { return service->AvailableKeychains(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[43], + Bridge_method_names[44], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1793,7 +1828,7 @@ Bridge::Service::Service() { return service->SetCurrentKeychain(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[44], + Bridge_method_names[45], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::StringValue, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1803,7 +1838,7 @@ Bridge::Service::Service() { return service->CurrentKeychain(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[45], + Bridge_method_names[46], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::grpc::UserListResponse, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1813,7 +1848,7 @@ Bridge::Service::Service() { return service->GetUserList(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[46], + Bridge_method_names[47], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::grpc::User, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1823,7 +1858,7 @@ Bridge::Service::Service() { return service->GetUser(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[47], + Bridge_method_names[48], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::UserSplitModeRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1833,7 +1868,7 @@ Bridge::Service::Service() { return service->SetUserSplitMode(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[48], + Bridge_method_names[49], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1843,7 +1878,7 @@ Bridge::Service::Service() { return service->LogoutUser(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[49], + Bridge_method_names[50], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::StringValue, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1853,7 +1888,7 @@ Bridge::Service::Service() { return service->RemoveUser(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[50], + Bridge_method_names[51], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::grpc::ConfigureAppleMailRequest, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1863,7 +1898,7 @@ Bridge::Service::Service() { return service->ConfigureUserAppleMail(ctx, req, resp); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[51], + Bridge_method_names[52], ::grpc::internal::RpcMethod::SERVER_STREAMING, new ::grpc::internal::ServerStreamingHandler< Bridge::Service, ::grpc::EventStreamRequest, ::grpc::StreamEvent>( [](Bridge::Service* service, @@ -1873,7 +1908,7 @@ Bridge::Service::Service() { return service->RunEventStream(ctx, req, writer); }, this))); AddMethod(new ::grpc::internal::RpcServiceMethod( - Bridge_method_names[52], + Bridge_method_names[53], ::grpc::internal::RpcMethod::NORMAL_RPC, new ::grpc::internal::RpcMethodHandler< Bridge::Service, ::google::protobuf::Empty, ::google::protobuf::Empty, ::grpc::protobuf::MessageLite, ::grpc::protobuf::MessageLite>( [](Bridge::Service* service, @@ -1971,6 +2006,13 @@ Bridge::Service::~Service() { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } +::grpc::Status Bridge::Service::GoOs(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { + (void) context; + (void) request; + (void) response; + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); +} + ::grpc::Status Bridge::Service::TriggerReset(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response) { (void) context; (void) request; diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.h index ce0dce4c..6bd65044 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.grpc.pb.h @@ -141,6 +141,13 @@ class Bridge final { std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::BoolValue>> PrepareAsyncIsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::BoolValue>>(PrepareAsyncIsAllMailVisibleRaw(context, request, cq)); } + virtual ::grpc::Status GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::StringValue* response) = 0; + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>> AsyncGoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>>(AsyncGoOsRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>> PrepareAsyncGoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>>(PrepareAsyncGoOsRaw(context, request, cq)); + } virtual ::grpc::Status TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::Empty* response) = 0; std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::Empty>> AsyncTriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::Empty>>(AsyncTriggerResetRaw(context, request, cq)); @@ -467,6 +474,8 @@ class Bridge final { virtual void SetIsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::BoolValue* request, ::google::protobuf::Empty* response, ::grpc::ClientUnaryReactor* reactor) = 0; virtual void IsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response, std::function) = 0; virtual void IsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response, ::grpc::ClientUnaryReactor* reactor) = 0; + virtual void GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, std::function) = 0; + virtual void GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, ::grpc::ClientUnaryReactor* reactor) = 0; virtual void TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, std::function) = 0; virtual void TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, ::grpc::ClientUnaryReactor* reactor) = 0; virtual void Version(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, std::function) = 0; @@ -586,6 +595,8 @@ class Bridge final { virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::Empty>* PrepareAsyncSetIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::BoolValue& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::BoolValue>* AsyncIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::BoolValue>* PrepareAsyncIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>* AsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; + virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>* PrepareAsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::Empty>* AsyncTriggerResetRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::Empty>* PrepareAsyncTriggerResetRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; virtual ::grpc::ClientAsyncResponseReaderInterface< ::google::protobuf::StringValue>* AsyncVersionRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) = 0; @@ -757,6 +768,13 @@ class Bridge final { std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::BoolValue>> PrepareAsyncIsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::BoolValue>>(PrepareAsyncIsAllMailVisibleRaw(context, request, cq)); } + ::grpc::Status GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::StringValue* response) override; + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>> AsyncGoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>>(AsyncGoOsRaw(context, request, cq)); + } + std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>> PrepareAsyncGoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { + return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>>(PrepareAsyncGoOsRaw(context, request, cq)); + } ::grpc::Status TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::google::protobuf::Empty* response) override; std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>> AsyncTriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) { return std::unique_ptr< ::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>>(AsyncTriggerResetRaw(context, request, cq)); @@ -1073,6 +1091,8 @@ class Bridge final { void SetIsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::BoolValue* request, ::google::protobuf::Empty* response, ::grpc::ClientUnaryReactor* reactor) override; void IsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response, std::function) override; void IsAllMailVisible(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response, ::grpc::ClientUnaryReactor* reactor) override; + void GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, std::function) override; + void GoOs(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, ::grpc::ClientUnaryReactor* reactor) override; void TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, std::function) override; void TriggerReset(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response, ::grpc::ClientUnaryReactor* reactor) override; void Version(::grpc::ClientContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response, std::function) override; @@ -1189,6 +1209,8 @@ class Bridge final { ::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>* PrepareAsyncSetIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::BoolValue& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::google::protobuf::BoolValue>* AsyncIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::google::protobuf::BoolValue>* PrepareAsyncIsAllMailVisibleRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>* AsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; + ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>* PrepareAsyncGoOsRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>* AsyncTriggerResetRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::google::protobuf::Empty>* PrepareAsyncTriggerResetRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; ::grpc::ClientAsyncResponseReader< ::google::protobuf::StringValue>* AsyncVersionRaw(::grpc::ClientContext* context, const ::google::protobuf::Empty& request, ::grpc::CompletionQueue* cq) override; @@ -1284,6 +1306,7 @@ class Bridge final { const ::grpc::internal::RpcMethod rpcmethod_IsBetaEnabled_; const ::grpc::internal::RpcMethod rpcmethod_SetIsAllMailVisible_; const ::grpc::internal::RpcMethod rpcmethod_IsAllMailVisible_; + const ::grpc::internal::RpcMethod rpcmethod_GoOs_; const ::grpc::internal::RpcMethod rpcmethod_TriggerReset_; const ::grpc::internal::RpcMethod rpcmethod_Version_; const ::grpc::internal::RpcMethod rpcmethod_LogsPath_; @@ -1345,6 +1368,7 @@ class Bridge final { virtual ::grpc::Status IsBetaEnabled(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response); virtual ::grpc::Status SetIsAllMailVisible(::grpc::ServerContext* context, const ::google::protobuf::BoolValue* request, ::google::protobuf::Empty* response); virtual ::grpc::Status IsAllMailVisible(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response); + virtual ::grpc::Status GoOs(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response); virtual ::grpc::Status TriggerReset(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response); virtual ::grpc::Status Version(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response); virtual ::grpc::Status LogsPath(::grpc::ServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response); @@ -1637,12 +1661,32 @@ class Bridge final { } }; template + class WithAsyncMethod_GoOs : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithAsyncMethod_GoOs() { + ::grpc::Service::MarkMethodAsync(12); + } + ~WithAsyncMethod_GoOs() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestGoOs(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(12, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template class WithAsyncMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_TriggerReset() { - ::grpc::Service::MarkMethodAsync(12); + ::grpc::Service::MarkMethodAsync(13); } ~WithAsyncMethod_TriggerReset() override { BaseClassMustBeDerivedFromService(this); @@ -1653,7 +1697,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestTriggerReset(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(12, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(13, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1662,7 +1706,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_Version() { - ::grpc::Service::MarkMethodAsync(13); + ::grpc::Service::MarkMethodAsync(14); } ~WithAsyncMethod_Version() override { BaseClassMustBeDerivedFromService(this); @@ -1673,7 +1717,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestVersion(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(13, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(14, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1682,7 +1726,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_LogsPath() { - ::grpc::Service::MarkMethodAsync(14); + ::grpc::Service::MarkMethodAsync(15); } ~WithAsyncMethod_LogsPath() override { BaseClassMustBeDerivedFromService(this); @@ -1693,7 +1737,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogsPath(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(14, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(15, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1702,7 +1746,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_LicensePath() { - ::grpc::Service::MarkMethodAsync(15); + ::grpc::Service::MarkMethodAsync(16); } ~WithAsyncMethod_LicensePath() override { BaseClassMustBeDerivedFromService(this); @@ -1713,7 +1757,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLicensePath(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(15, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(16, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1722,7 +1766,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodAsync(16); + ::grpc::Service::MarkMethodAsync(17); } ~WithAsyncMethod_ReleaseNotesPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -1733,7 +1777,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestReleaseNotesPageLink(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(16, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(17, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1742,7 +1786,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodAsync(17); + ::grpc::Service::MarkMethodAsync(18); } ~WithAsyncMethod_DependencyLicensesLink() override { BaseClassMustBeDerivedFromService(this); @@ -1753,7 +1797,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestDependencyLicensesLink(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(17, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(18, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1762,7 +1806,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_LandingPageLink() { - ::grpc::Service::MarkMethodAsync(18); + ::grpc::Service::MarkMethodAsync(19); } ~WithAsyncMethod_LandingPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -1773,7 +1817,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLandingPageLink(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(18, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(19, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1782,7 +1826,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodAsync(19); + ::grpc::Service::MarkMethodAsync(20); } ~WithAsyncMethod_SetColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -1793,7 +1837,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetColorSchemeName(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(19, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(20, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1802,7 +1846,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodAsync(20); + ::grpc::Service::MarkMethodAsync(21); } ~WithAsyncMethod_ColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -1813,7 +1857,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestColorSchemeName(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(20, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(21, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1822,7 +1866,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodAsync(21); + ::grpc::Service::MarkMethodAsync(22); } ~WithAsyncMethod_CurrentEmailClient() override { BaseClassMustBeDerivedFromService(this); @@ -1833,7 +1877,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCurrentEmailClient(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(21, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(22, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1842,7 +1886,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ReportBug() { - ::grpc::Service::MarkMethodAsync(22); + ::grpc::Service::MarkMethodAsync(23); } ~WithAsyncMethod_ReportBug() override { BaseClassMustBeDerivedFromService(this); @@ -1853,7 +1897,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestReportBug(::grpc::ServerContext* context, ::grpc::ReportBugRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(22, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(23, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1862,7 +1906,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodAsync(23); + ::grpc::Service::MarkMethodAsync(24); } ~WithAsyncMethod_ExportTLSCertificates() override { BaseClassMustBeDerivedFromService(this); @@ -1873,7 +1917,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestExportTLSCertificates(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(23, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(24, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1882,7 +1926,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ForceLauncher() { - ::grpc::Service::MarkMethodAsync(24); + ::grpc::Service::MarkMethodAsync(25); } ~WithAsyncMethod_ForceLauncher() override { BaseClassMustBeDerivedFromService(this); @@ -1893,7 +1937,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestForceLauncher(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(24, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(25, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1902,7 +1946,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodAsync(25); + ::grpc::Service::MarkMethodAsync(26); } ~WithAsyncMethod_SetMainExecutable() override { BaseClassMustBeDerivedFromService(this); @@ -1913,7 +1957,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetMainExecutable(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(25, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(26, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1922,7 +1966,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_Login() { - ::grpc::Service::MarkMethodAsync(26); + ::grpc::Service::MarkMethodAsync(27); } ~WithAsyncMethod_Login() override { BaseClassMustBeDerivedFromService(this); @@ -1933,7 +1977,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin(::grpc::ServerContext* context, ::grpc::LoginRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(26, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(27, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1942,7 +1986,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_Login2FA() { - ::grpc::Service::MarkMethodAsync(27); + ::grpc::Service::MarkMethodAsync(28); } ~WithAsyncMethod_Login2FA() override { BaseClassMustBeDerivedFromService(this); @@ -1953,7 +1997,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin2FA(::grpc::ServerContext* context, ::grpc::LoginRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(27, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(28, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1962,7 +2006,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_Login2Passwords() { - ::grpc::Service::MarkMethodAsync(28); + ::grpc::Service::MarkMethodAsync(29); } ~WithAsyncMethod_Login2Passwords() override { BaseClassMustBeDerivedFromService(this); @@ -1973,7 +2017,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin2Passwords(::grpc::ServerContext* context, ::grpc::LoginRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(28, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(29, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -1982,7 +2026,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_LoginAbort() { - ::grpc::Service::MarkMethodAsync(29); + ::grpc::Service::MarkMethodAsync(30); } ~WithAsyncMethod_LoginAbort() override { BaseClassMustBeDerivedFromService(this); @@ -1993,7 +2037,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLoginAbort(::grpc::ServerContext* context, ::grpc::LoginAbortRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(29, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(30, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2002,7 +2046,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_CheckUpdate() { - ::grpc::Service::MarkMethodAsync(30); + ::grpc::Service::MarkMethodAsync(31); } ~WithAsyncMethod_CheckUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -2013,7 +2057,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCheckUpdate(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(30, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(31, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2022,7 +2066,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_InstallUpdate() { - ::grpc::Service::MarkMethodAsync(31); + ::grpc::Service::MarkMethodAsync(32); } ~WithAsyncMethod_InstallUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -2033,7 +2077,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestInstallUpdate(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(31, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(32, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2042,7 +2086,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodAsync(32); + ::grpc::Service::MarkMethodAsync(33); } ~WithAsyncMethod_SetIsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -2053,7 +2097,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetIsAutomaticUpdateOn(::grpc::ServerContext* context, ::google::protobuf::BoolValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(32, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(33, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2062,7 +2106,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodAsync(33); + ::grpc::Service::MarkMethodAsync(34); } ~WithAsyncMethod_IsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -2073,7 +2117,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsAutomaticUpdateOn(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::BoolValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(33, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(34, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2082,7 +2126,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_DiskCachePath() { - ::grpc::Service::MarkMethodAsync(34); + ::grpc::Service::MarkMethodAsync(35); } ~WithAsyncMethod_DiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -2093,7 +2137,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestDiskCachePath(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(34, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(35, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2102,7 +2146,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodAsync(35); + ::grpc::Service::MarkMethodAsync(36); } ~WithAsyncMethod_SetDiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -2113,7 +2157,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetDiskCachePath(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(35, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(36, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2122,7 +2166,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodAsync(36); + ::grpc::Service::MarkMethodAsync(37); } ~WithAsyncMethod_SetIsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -2133,7 +2177,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetIsDoHEnabled(::grpc::ServerContext* context, ::google::protobuf::BoolValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(36, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(37, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2142,7 +2186,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodAsync(37); + ::grpc::Service::MarkMethodAsync(38); } ~WithAsyncMethod_IsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -2153,7 +2197,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsDoHEnabled(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::BoolValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(37, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(38, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2162,7 +2206,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_MailServerSettings() { - ::grpc::Service::MarkMethodAsync(38); + ::grpc::Service::MarkMethodAsync(39); } ~WithAsyncMethod_MailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -2173,7 +2217,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestMailServerSettings(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ImapSmtpSettings>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(38, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(39, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2182,7 +2226,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodAsync(39); + ::grpc::Service::MarkMethodAsync(40); } ~WithAsyncMethod_SetMailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -2193,7 +2237,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetMailServerSettings(::grpc::ServerContext* context, ::grpc::ImapSmtpSettings* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(39, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(40, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2202,7 +2246,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_Hostname() { - ::grpc::Service::MarkMethodAsync(40); + ::grpc::Service::MarkMethodAsync(41); } ~WithAsyncMethod_Hostname() override { BaseClassMustBeDerivedFromService(this); @@ -2213,7 +2257,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestHostname(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(40, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(41, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2222,7 +2266,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_IsPortFree() { - ::grpc::Service::MarkMethodAsync(41); + ::grpc::Service::MarkMethodAsync(42); } ~WithAsyncMethod_IsPortFree() override { BaseClassMustBeDerivedFromService(this); @@ -2233,7 +2277,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsPortFree(::grpc::ServerContext* context, ::google::protobuf::Int32Value* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::BoolValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(41, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(42, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2242,7 +2286,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodAsync(42); + ::grpc::Service::MarkMethodAsync(43); } ~WithAsyncMethod_AvailableKeychains() override { BaseClassMustBeDerivedFromService(this); @@ -2253,7 +2297,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestAvailableKeychains(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::grpc::AvailableKeychainsResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(42, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(43, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2262,7 +2306,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodAsync(43); + ::grpc::Service::MarkMethodAsync(44); } ~WithAsyncMethod_SetCurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -2273,7 +2317,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetCurrentKeychain(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(43, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(44, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2282,7 +2326,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodAsync(44); + ::grpc::Service::MarkMethodAsync(45); } ~WithAsyncMethod_CurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -2293,7 +2337,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCurrentKeychain(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::StringValue>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(44, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(45, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2302,7 +2346,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_GetUserList() { - ::grpc::Service::MarkMethodAsync(45); + ::grpc::Service::MarkMethodAsync(46); } ~WithAsyncMethod_GetUserList() override { BaseClassMustBeDerivedFromService(this); @@ -2313,7 +2357,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestGetUserList(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::grpc::UserListResponse>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(45, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(46, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2322,7 +2366,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_GetUser() { - ::grpc::Service::MarkMethodAsync(46); + ::grpc::Service::MarkMethodAsync(47); } ~WithAsyncMethod_GetUser() override { BaseClassMustBeDerivedFromService(this); @@ -2333,7 +2377,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestGetUser(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::grpc::User>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(46, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(47, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2342,7 +2386,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodAsync(47); + ::grpc::Service::MarkMethodAsync(48); } ~WithAsyncMethod_SetUserSplitMode() override { BaseClassMustBeDerivedFromService(this); @@ -2353,7 +2397,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetUserSplitMode(::grpc::ServerContext* context, ::grpc::UserSplitModeRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(47, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(48, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2362,7 +2406,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_LogoutUser() { - ::grpc::Service::MarkMethodAsync(48); + ::grpc::Service::MarkMethodAsync(49); } ~WithAsyncMethod_LogoutUser() override { BaseClassMustBeDerivedFromService(this); @@ -2373,7 +2417,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogoutUser(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(48, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(49, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2382,7 +2426,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_RemoveUser() { - ::grpc::Service::MarkMethodAsync(49); + ::grpc::Service::MarkMethodAsync(50); } ~WithAsyncMethod_RemoveUser() override { BaseClassMustBeDerivedFromService(this); @@ -2393,7 +2437,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestRemoveUser(::grpc::ServerContext* context, ::google::protobuf::StringValue* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(49, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(50, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2402,7 +2446,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodAsync(50); + ::grpc::Service::MarkMethodAsync(51); } ~WithAsyncMethod_ConfigureUserAppleMail() override { BaseClassMustBeDerivedFromService(this); @@ -2413,7 +2457,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestConfigureUserAppleMail(::grpc::ServerContext* context, ::grpc::ConfigureAppleMailRequest* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(50, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(51, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -2422,7 +2466,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_RunEventStream() { - ::grpc::Service::MarkMethodAsync(51); + ::grpc::Service::MarkMethodAsync(52); } ~WithAsyncMethod_RunEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -2433,7 +2477,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestRunEventStream(::grpc::ServerContext* context, ::grpc::EventStreamRequest* request, ::grpc::ServerAsyncWriter< ::grpc::StreamEvent>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncServerStreaming(51, context, request, writer, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncServerStreaming(52, context, request, writer, new_call_cq, notification_cq, tag); } }; template @@ -2442,7 +2486,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithAsyncMethod_StopEventStream() { - ::grpc::Service::MarkMethodAsync(52); + ::grpc::Service::MarkMethodAsync(53); } ~WithAsyncMethod_StopEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -2453,10 +2497,10 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestStopEventStream(::grpc::ServerContext* context, ::google::protobuf::Empty* request, ::grpc::ServerAsyncResponseWriter< ::google::protobuf::Empty>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(52, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(53, context, request, response, new_call_cq, notification_cq, tag); } }; - typedef WithAsyncMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > AsyncService; + typedef WithAsyncMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > AsyncService; template class WithCallbackMethod_CheckTokens : public BaseClass { private: @@ -2782,18 +2826,45 @@ class Bridge final { ::grpc::CallbackServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::BoolValue* /*response*/) { return nullptr; } }; template + class WithCallbackMethod_GoOs : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithCallbackMethod_GoOs() { + ::grpc::Service::MarkMethodCallback(12, + new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( + [this]( + ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->GoOs(context, request, response); }));} + void SetMessageAllocatorFor_GoOs( + ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(12); + static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) + ->SetMessageAllocator(allocator); + } + ~WithCallbackMethod_GoOs() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* GoOs( + ::grpc::CallbackServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) { return nullptr; } + }; + template class WithCallbackMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_TriggerReset() { - ::grpc::Service::MarkMethodCallback(12, + ::grpc::Service::MarkMethodCallback(13, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response) { return this->TriggerReset(context, request, response); }));} void SetMessageAllocatorFor_TriggerReset( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(12); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(13); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -2814,13 +2885,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_Version() { - ::grpc::Service::MarkMethodCallback(13, + ::grpc::Service::MarkMethodCallback(14, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->Version(context, request, response); }));} void SetMessageAllocatorFor_Version( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(13); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(14); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -2841,13 +2912,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_LogsPath() { - ::grpc::Service::MarkMethodCallback(14, + ::grpc::Service::MarkMethodCallback(15, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->LogsPath(context, request, response); }));} void SetMessageAllocatorFor_LogsPath( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(14); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(15); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -2868,13 +2939,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_LicensePath() { - ::grpc::Service::MarkMethodCallback(15, + ::grpc::Service::MarkMethodCallback(16, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->LicensePath(context, request, response); }));} void SetMessageAllocatorFor_LicensePath( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(15); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(16); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -2895,13 +2966,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodCallback(16, + ::grpc::Service::MarkMethodCallback(17, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->ReleaseNotesPageLink(context, request, response); }));} void SetMessageAllocatorFor_ReleaseNotesPageLink( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(16); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(17); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -2922,13 +2993,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodCallback(17, + ::grpc::Service::MarkMethodCallback(18, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->DependencyLicensesLink(context, request, response); }));} void SetMessageAllocatorFor_DependencyLicensesLink( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(17); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(18); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -2949,13 +3020,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_LandingPageLink() { - ::grpc::Service::MarkMethodCallback(18, + ::grpc::Service::MarkMethodCallback(19, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->LandingPageLink(context, request, response); }));} void SetMessageAllocatorFor_LandingPageLink( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(18); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(19); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -2976,13 +3047,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodCallback(19, + ::grpc::Service::MarkMethodCallback(20, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->SetColorSchemeName(context, request, response); }));} void SetMessageAllocatorFor_SetColorSchemeName( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(19); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(20); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3003,13 +3074,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodCallback(20, + ::grpc::Service::MarkMethodCallback(21, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->ColorSchemeName(context, request, response); }));} void SetMessageAllocatorFor_ColorSchemeName( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(20); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(21); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3030,13 +3101,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodCallback(21, + ::grpc::Service::MarkMethodCallback(22, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->CurrentEmailClient(context, request, response); }));} void SetMessageAllocatorFor_CurrentEmailClient( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(21); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(22); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3057,13 +3128,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ReportBug() { - ::grpc::Service::MarkMethodCallback(22, + ::grpc::Service::MarkMethodCallback(23, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ReportBugRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ReportBugRequest* request, ::google::protobuf::Empty* response) { return this->ReportBug(context, request, response); }));} void SetMessageAllocatorFor_ReportBug( ::grpc::MessageAllocator< ::grpc::ReportBugRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(22); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(23); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::ReportBugRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3084,13 +3155,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodCallback(23, + ::grpc::Service::MarkMethodCallback(24, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->ExportTLSCertificates(context, request, response); }));} void SetMessageAllocatorFor_ExportTLSCertificates( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(23); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(24); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3111,13 +3182,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ForceLauncher() { - ::grpc::Service::MarkMethodCallback(24, + ::grpc::Service::MarkMethodCallback(25, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->ForceLauncher(context, request, response); }));} void SetMessageAllocatorFor_ForceLauncher( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(24); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(25); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3138,13 +3209,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodCallback(25, + ::grpc::Service::MarkMethodCallback(26, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->SetMainExecutable(context, request, response); }));} void SetMessageAllocatorFor_SetMainExecutable( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(25); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(26); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3165,13 +3236,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_Login() { - ::grpc::Service::MarkMethodCallback(26, + ::grpc::Service::MarkMethodCallback(27, new ::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::LoginRequest* request, ::google::protobuf::Empty* response) { return this->Login(context, request, response); }));} void SetMessageAllocatorFor_Login( ::grpc::MessageAllocator< ::grpc::LoginRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(26); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(27); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3192,13 +3263,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_Login2FA() { - ::grpc::Service::MarkMethodCallback(27, + ::grpc::Service::MarkMethodCallback(28, new ::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::LoginRequest* request, ::google::protobuf::Empty* response) { return this->Login2FA(context, request, response); }));} void SetMessageAllocatorFor_Login2FA( ::grpc::MessageAllocator< ::grpc::LoginRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(27); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(28); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3219,13 +3290,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_Login2Passwords() { - ::grpc::Service::MarkMethodCallback(28, + ::grpc::Service::MarkMethodCallback(29, new ::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::LoginRequest* request, ::google::protobuf::Empty* response) { return this->Login2Passwords(context, request, response); }));} void SetMessageAllocatorFor_Login2Passwords( ::grpc::MessageAllocator< ::grpc::LoginRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(28); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(29); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3246,13 +3317,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_LoginAbort() { - ::grpc::Service::MarkMethodCallback(29, + ::grpc::Service::MarkMethodCallback(30, new ::grpc::internal::CallbackUnaryHandler< ::grpc::LoginAbortRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::LoginAbortRequest* request, ::google::protobuf::Empty* response) { return this->LoginAbort(context, request, response); }));} void SetMessageAllocatorFor_LoginAbort( ::grpc::MessageAllocator< ::grpc::LoginAbortRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(29); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(30); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::LoginAbortRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3273,13 +3344,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_CheckUpdate() { - ::grpc::Service::MarkMethodCallback(30, + ::grpc::Service::MarkMethodCallback(31, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response) { return this->CheckUpdate(context, request, response); }));} void SetMessageAllocatorFor_CheckUpdate( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(30); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(31); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3300,13 +3371,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_InstallUpdate() { - ::grpc::Service::MarkMethodCallback(31, + ::grpc::Service::MarkMethodCallback(32, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response) { return this->InstallUpdate(context, request, response); }));} void SetMessageAllocatorFor_InstallUpdate( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(31); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(32); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3327,13 +3398,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodCallback(32, + ::grpc::Service::MarkMethodCallback(33, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::BoolValue* request, ::google::protobuf::Empty* response) { return this->SetIsAutomaticUpdateOn(context, request, response); }));} void SetMessageAllocatorFor_SetIsAutomaticUpdateOn( ::grpc::MessageAllocator< ::google::protobuf::BoolValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(32); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(33); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3354,13 +3425,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodCallback(33, + ::grpc::Service::MarkMethodCallback(34, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response) { return this->IsAutomaticUpdateOn(context, request, response); }));} void SetMessageAllocatorFor_IsAutomaticUpdateOn( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::BoolValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(33); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(34); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3381,13 +3452,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_DiskCachePath() { - ::grpc::Service::MarkMethodCallback(34, + ::grpc::Service::MarkMethodCallback(35, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->DiskCachePath(context, request, response); }));} void SetMessageAllocatorFor_DiskCachePath( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(34); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(35); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3408,13 +3479,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodCallback(35, + ::grpc::Service::MarkMethodCallback(36, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->SetDiskCachePath(context, request, response); }));} void SetMessageAllocatorFor_SetDiskCachePath( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(35); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(36); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3435,13 +3506,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodCallback(36, + ::grpc::Service::MarkMethodCallback(37, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::BoolValue* request, ::google::protobuf::Empty* response) { return this->SetIsDoHEnabled(context, request, response); }));} void SetMessageAllocatorFor_SetIsDoHEnabled( ::grpc::MessageAllocator< ::google::protobuf::BoolValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(36); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(37); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3462,13 +3533,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodCallback(37, + ::grpc::Service::MarkMethodCallback(38, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::BoolValue* response) { return this->IsDoHEnabled(context, request, response); }));} void SetMessageAllocatorFor_IsDoHEnabled( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::BoolValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(37); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(38); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3489,13 +3560,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_MailServerSettings() { - ::grpc::Service::MarkMethodCallback(38, + ::grpc::Service::MarkMethodCallback(39, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::ImapSmtpSettings>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::grpc::ImapSmtpSettings* response) { return this->MailServerSettings(context, request, response); }));} void SetMessageAllocatorFor_MailServerSettings( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::grpc::ImapSmtpSettings>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(38); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(39); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::ImapSmtpSettings>*>(handler) ->SetMessageAllocator(allocator); } @@ -3516,13 +3587,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodCallback(39, + ::grpc::Service::MarkMethodCallback(40, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ImapSmtpSettings, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ImapSmtpSettings* request, ::google::protobuf::Empty* response) { return this->SetMailServerSettings(context, request, response); }));} void SetMessageAllocatorFor_SetMailServerSettings( ::grpc::MessageAllocator< ::grpc::ImapSmtpSettings, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(39); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(40); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::ImapSmtpSettings, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3543,13 +3614,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_Hostname() { - ::grpc::Service::MarkMethodCallback(40, + ::grpc::Service::MarkMethodCallback(41, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->Hostname(context, request, response); }));} void SetMessageAllocatorFor_Hostname( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(40); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(41); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3570,13 +3641,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_IsPortFree() { - ::grpc::Service::MarkMethodCallback(41, + ::grpc::Service::MarkMethodCallback(42, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Int32Value, ::google::protobuf::BoolValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Int32Value* request, ::google::protobuf::BoolValue* response) { return this->IsPortFree(context, request, response); }));} void SetMessageAllocatorFor_IsPortFree( ::grpc::MessageAllocator< ::google::protobuf::Int32Value, ::google::protobuf::BoolValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(41); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(42); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Int32Value, ::google::protobuf::BoolValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3597,13 +3668,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodCallback(42, + ::grpc::Service::MarkMethodCallback(43, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::AvailableKeychainsResponse>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::grpc::AvailableKeychainsResponse* response) { return this->AvailableKeychains(context, request, response); }));} void SetMessageAllocatorFor_AvailableKeychains( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::grpc::AvailableKeychainsResponse>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(42); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(43); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::AvailableKeychainsResponse>*>(handler) ->SetMessageAllocator(allocator); } @@ -3624,13 +3695,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodCallback(43, + ::grpc::Service::MarkMethodCallback(44, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->SetCurrentKeychain(context, request, response); }));} void SetMessageAllocatorFor_SetCurrentKeychain( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(43); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(44); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3651,13 +3722,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodCallback(44, + ::grpc::Service::MarkMethodCallback(45, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::StringValue* response) { return this->CurrentKeychain(context, request, response); }));} void SetMessageAllocatorFor_CurrentKeychain( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::StringValue>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(44); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(45); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>*>(handler) ->SetMessageAllocator(allocator); } @@ -3678,13 +3749,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_GetUserList() { - ::grpc::Service::MarkMethodCallback(45, + ::grpc::Service::MarkMethodCallback(46, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::UserListResponse>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::grpc::UserListResponse* response) { return this->GetUserList(context, request, response); }));} void SetMessageAllocatorFor_GetUserList( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::grpc::UserListResponse>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(45); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(46); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::grpc::UserListResponse>*>(handler) ->SetMessageAllocator(allocator); } @@ -3705,13 +3776,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_GetUser() { - ::grpc::Service::MarkMethodCallback(46, + ::grpc::Service::MarkMethodCallback(47, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::grpc::User>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::grpc::User* response) { return this->GetUser(context, request, response); }));} void SetMessageAllocatorFor_GetUser( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::grpc::User>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(46); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(47); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::grpc::User>*>(handler) ->SetMessageAllocator(allocator); } @@ -3732,13 +3803,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodCallback(47, + ::grpc::Service::MarkMethodCallback(48, new ::grpc::internal::CallbackUnaryHandler< ::grpc::UserSplitModeRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::UserSplitModeRequest* request, ::google::protobuf::Empty* response) { return this->SetUserSplitMode(context, request, response); }));} void SetMessageAllocatorFor_SetUserSplitMode( ::grpc::MessageAllocator< ::grpc::UserSplitModeRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(47); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(48); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::UserSplitModeRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3759,13 +3830,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_LogoutUser() { - ::grpc::Service::MarkMethodCallback(48, + ::grpc::Service::MarkMethodCallback(49, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->LogoutUser(context, request, response); }));} void SetMessageAllocatorFor_LogoutUser( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(48); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(49); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3786,13 +3857,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_RemoveUser() { - ::grpc::Service::MarkMethodCallback(49, + ::grpc::Service::MarkMethodCallback(50, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::StringValue* request, ::google::protobuf::Empty* response) { return this->RemoveUser(context, request, response); }));} void SetMessageAllocatorFor_RemoveUser( ::grpc::MessageAllocator< ::google::protobuf::StringValue, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(49); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(50); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3813,13 +3884,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodCallback(50, + ::grpc::Service::MarkMethodCallback(51, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ConfigureAppleMailRequest, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ConfigureAppleMailRequest* request, ::google::protobuf::Empty* response) { return this->ConfigureUserAppleMail(context, request, response); }));} void SetMessageAllocatorFor_ConfigureUserAppleMail( ::grpc::MessageAllocator< ::grpc::ConfigureAppleMailRequest, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(50); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(51); static_cast<::grpc::internal::CallbackUnaryHandler< ::grpc::ConfigureAppleMailRequest, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3840,7 +3911,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_RunEventStream() { - ::grpc::Service::MarkMethodCallback(51, + ::grpc::Service::MarkMethodCallback(52, new ::grpc::internal::CallbackServerStreamingHandler< ::grpc::EventStreamRequest, ::grpc::StreamEvent>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::EventStreamRequest* request) { return this->RunEventStream(context, request); })); @@ -3862,13 +3933,13 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithCallbackMethod_StopEventStream() { - ::grpc::Service::MarkMethodCallback(52, + ::grpc::Service::MarkMethodCallback(53, new ::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this]( ::grpc::CallbackServerContext* context, const ::google::protobuf::Empty* request, ::google::protobuf::Empty* response) { return this->StopEventStream(context, request, response); }));} void SetMessageAllocatorFor_StopEventStream( ::grpc::MessageAllocator< ::google::protobuf::Empty, ::google::protobuf::Empty>* allocator) { - ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(52); + ::grpc::internal::MethodHandler* const handler = ::grpc::Service::GetHandler(53); static_cast<::grpc::internal::CallbackUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>*>(handler) ->SetMessageAllocator(allocator); } @@ -3883,7 +3954,7 @@ class Bridge final { virtual ::grpc::ServerUnaryReactor* StopEventStream( ::grpc::CallbackServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::Empty* /*response*/) { return nullptr; } }; - typedef WithCallbackMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > CallbackService; + typedef WithCallbackMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > CallbackService; typedef CallbackService ExperimentalCallbackService; template class WithGenericMethod_CheckTokens : public BaseClass { @@ -4090,12 +4161,29 @@ class Bridge final { } }; template + class WithGenericMethod_GoOs : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithGenericMethod_GoOs() { + ::grpc::Service::MarkMethodGeneric(12); + } + ~WithGenericMethod_GoOs() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + }; + template class WithGenericMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_TriggerReset() { - ::grpc::Service::MarkMethodGeneric(12); + ::grpc::Service::MarkMethodGeneric(13); } ~WithGenericMethod_TriggerReset() override { BaseClassMustBeDerivedFromService(this); @@ -4112,7 +4200,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_Version() { - ::grpc::Service::MarkMethodGeneric(13); + ::grpc::Service::MarkMethodGeneric(14); } ~WithGenericMethod_Version() override { BaseClassMustBeDerivedFromService(this); @@ -4129,7 +4217,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_LogsPath() { - ::grpc::Service::MarkMethodGeneric(14); + ::grpc::Service::MarkMethodGeneric(15); } ~WithGenericMethod_LogsPath() override { BaseClassMustBeDerivedFromService(this); @@ -4146,7 +4234,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_LicensePath() { - ::grpc::Service::MarkMethodGeneric(15); + ::grpc::Service::MarkMethodGeneric(16); } ~WithGenericMethod_LicensePath() override { BaseClassMustBeDerivedFromService(this); @@ -4163,7 +4251,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodGeneric(16); + ::grpc::Service::MarkMethodGeneric(17); } ~WithGenericMethod_ReleaseNotesPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -4180,7 +4268,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodGeneric(17); + ::grpc::Service::MarkMethodGeneric(18); } ~WithGenericMethod_DependencyLicensesLink() override { BaseClassMustBeDerivedFromService(this); @@ -4197,7 +4285,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_LandingPageLink() { - ::grpc::Service::MarkMethodGeneric(18); + ::grpc::Service::MarkMethodGeneric(19); } ~WithGenericMethod_LandingPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -4214,7 +4302,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodGeneric(19); + ::grpc::Service::MarkMethodGeneric(20); } ~WithGenericMethod_SetColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -4231,7 +4319,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodGeneric(20); + ::grpc::Service::MarkMethodGeneric(21); } ~WithGenericMethod_ColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -4248,7 +4336,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodGeneric(21); + ::grpc::Service::MarkMethodGeneric(22); } ~WithGenericMethod_CurrentEmailClient() override { BaseClassMustBeDerivedFromService(this); @@ -4265,7 +4353,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ReportBug() { - ::grpc::Service::MarkMethodGeneric(22); + ::grpc::Service::MarkMethodGeneric(23); } ~WithGenericMethod_ReportBug() override { BaseClassMustBeDerivedFromService(this); @@ -4282,7 +4370,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodGeneric(23); + ::grpc::Service::MarkMethodGeneric(24); } ~WithGenericMethod_ExportTLSCertificates() override { BaseClassMustBeDerivedFromService(this); @@ -4299,7 +4387,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ForceLauncher() { - ::grpc::Service::MarkMethodGeneric(24); + ::grpc::Service::MarkMethodGeneric(25); } ~WithGenericMethod_ForceLauncher() override { BaseClassMustBeDerivedFromService(this); @@ -4316,7 +4404,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodGeneric(25); + ::grpc::Service::MarkMethodGeneric(26); } ~WithGenericMethod_SetMainExecutable() override { BaseClassMustBeDerivedFromService(this); @@ -4333,7 +4421,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_Login() { - ::grpc::Service::MarkMethodGeneric(26); + ::grpc::Service::MarkMethodGeneric(27); } ~WithGenericMethod_Login() override { BaseClassMustBeDerivedFromService(this); @@ -4350,7 +4438,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_Login2FA() { - ::grpc::Service::MarkMethodGeneric(27); + ::grpc::Service::MarkMethodGeneric(28); } ~WithGenericMethod_Login2FA() override { BaseClassMustBeDerivedFromService(this); @@ -4367,7 +4455,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_Login2Passwords() { - ::grpc::Service::MarkMethodGeneric(28); + ::grpc::Service::MarkMethodGeneric(29); } ~WithGenericMethod_Login2Passwords() override { BaseClassMustBeDerivedFromService(this); @@ -4384,7 +4472,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_LoginAbort() { - ::grpc::Service::MarkMethodGeneric(29); + ::grpc::Service::MarkMethodGeneric(30); } ~WithGenericMethod_LoginAbort() override { BaseClassMustBeDerivedFromService(this); @@ -4401,7 +4489,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_CheckUpdate() { - ::grpc::Service::MarkMethodGeneric(30); + ::grpc::Service::MarkMethodGeneric(31); } ~WithGenericMethod_CheckUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -4418,7 +4506,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_InstallUpdate() { - ::grpc::Service::MarkMethodGeneric(31); + ::grpc::Service::MarkMethodGeneric(32); } ~WithGenericMethod_InstallUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -4435,7 +4523,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodGeneric(32); + ::grpc::Service::MarkMethodGeneric(33); } ~WithGenericMethod_SetIsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -4452,7 +4540,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodGeneric(33); + ::grpc::Service::MarkMethodGeneric(34); } ~WithGenericMethod_IsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -4469,7 +4557,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_DiskCachePath() { - ::grpc::Service::MarkMethodGeneric(34); + ::grpc::Service::MarkMethodGeneric(35); } ~WithGenericMethod_DiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -4486,7 +4574,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodGeneric(35); + ::grpc::Service::MarkMethodGeneric(36); } ~WithGenericMethod_SetDiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -4503,7 +4591,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodGeneric(36); + ::grpc::Service::MarkMethodGeneric(37); } ~WithGenericMethod_SetIsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -4520,7 +4608,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodGeneric(37); + ::grpc::Service::MarkMethodGeneric(38); } ~WithGenericMethod_IsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -4537,7 +4625,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_MailServerSettings() { - ::grpc::Service::MarkMethodGeneric(38); + ::grpc::Service::MarkMethodGeneric(39); } ~WithGenericMethod_MailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -4554,7 +4642,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodGeneric(39); + ::grpc::Service::MarkMethodGeneric(40); } ~WithGenericMethod_SetMailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -4571,7 +4659,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_Hostname() { - ::grpc::Service::MarkMethodGeneric(40); + ::grpc::Service::MarkMethodGeneric(41); } ~WithGenericMethod_Hostname() override { BaseClassMustBeDerivedFromService(this); @@ -4588,7 +4676,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_IsPortFree() { - ::grpc::Service::MarkMethodGeneric(41); + ::grpc::Service::MarkMethodGeneric(42); } ~WithGenericMethod_IsPortFree() override { BaseClassMustBeDerivedFromService(this); @@ -4605,7 +4693,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodGeneric(42); + ::grpc::Service::MarkMethodGeneric(43); } ~WithGenericMethod_AvailableKeychains() override { BaseClassMustBeDerivedFromService(this); @@ -4622,7 +4710,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodGeneric(43); + ::grpc::Service::MarkMethodGeneric(44); } ~WithGenericMethod_SetCurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -4639,7 +4727,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodGeneric(44); + ::grpc::Service::MarkMethodGeneric(45); } ~WithGenericMethod_CurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -4656,7 +4744,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_GetUserList() { - ::grpc::Service::MarkMethodGeneric(45); + ::grpc::Service::MarkMethodGeneric(46); } ~WithGenericMethod_GetUserList() override { BaseClassMustBeDerivedFromService(this); @@ -4673,7 +4761,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_GetUser() { - ::grpc::Service::MarkMethodGeneric(46); + ::grpc::Service::MarkMethodGeneric(47); } ~WithGenericMethod_GetUser() override { BaseClassMustBeDerivedFromService(this); @@ -4690,7 +4778,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodGeneric(47); + ::grpc::Service::MarkMethodGeneric(48); } ~WithGenericMethod_SetUserSplitMode() override { BaseClassMustBeDerivedFromService(this); @@ -4707,7 +4795,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_LogoutUser() { - ::grpc::Service::MarkMethodGeneric(48); + ::grpc::Service::MarkMethodGeneric(49); } ~WithGenericMethod_LogoutUser() override { BaseClassMustBeDerivedFromService(this); @@ -4724,7 +4812,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_RemoveUser() { - ::grpc::Service::MarkMethodGeneric(49); + ::grpc::Service::MarkMethodGeneric(50); } ~WithGenericMethod_RemoveUser() override { BaseClassMustBeDerivedFromService(this); @@ -4741,7 +4829,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodGeneric(50); + ::grpc::Service::MarkMethodGeneric(51); } ~WithGenericMethod_ConfigureUserAppleMail() override { BaseClassMustBeDerivedFromService(this); @@ -4758,7 +4846,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_RunEventStream() { - ::grpc::Service::MarkMethodGeneric(51); + ::grpc::Service::MarkMethodGeneric(52); } ~WithGenericMethod_RunEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -4775,7 +4863,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithGenericMethod_StopEventStream() { - ::grpc::Service::MarkMethodGeneric(52); + ::grpc::Service::MarkMethodGeneric(53); } ~WithGenericMethod_StopEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -5027,12 +5115,32 @@ class Bridge final { } }; template + class WithRawMethod_GoOs : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawMethod_GoOs() { + ::grpc::Service::MarkMethodRaw(12); + } + ~WithRawMethod_GoOs() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + void RequestGoOs(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { + ::grpc::Service::RequestAsyncUnary(12, context, request, response, new_call_cq, notification_cq, tag); + } + }; + template class WithRawMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_TriggerReset() { - ::grpc::Service::MarkMethodRaw(12); + ::grpc::Service::MarkMethodRaw(13); } ~WithRawMethod_TriggerReset() override { BaseClassMustBeDerivedFromService(this); @@ -5043,7 +5151,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestTriggerReset(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(12, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(13, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5052,7 +5160,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_Version() { - ::grpc::Service::MarkMethodRaw(13); + ::grpc::Service::MarkMethodRaw(14); } ~WithRawMethod_Version() override { BaseClassMustBeDerivedFromService(this); @@ -5063,7 +5171,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestVersion(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(13, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(14, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5072,7 +5180,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_LogsPath() { - ::grpc::Service::MarkMethodRaw(14); + ::grpc::Service::MarkMethodRaw(15); } ~WithRawMethod_LogsPath() override { BaseClassMustBeDerivedFromService(this); @@ -5083,7 +5191,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogsPath(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(14, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(15, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5092,7 +5200,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_LicensePath() { - ::grpc::Service::MarkMethodRaw(15); + ::grpc::Service::MarkMethodRaw(16); } ~WithRawMethod_LicensePath() override { BaseClassMustBeDerivedFromService(this); @@ -5103,7 +5211,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLicensePath(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(15, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(16, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5112,7 +5220,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodRaw(16); + ::grpc::Service::MarkMethodRaw(17); } ~WithRawMethod_ReleaseNotesPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -5123,7 +5231,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestReleaseNotesPageLink(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(16, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(17, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5132,7 +5240,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodRaw(17); + ::grpc::Service::MarkMethodRaw(18); } ~WithRawMethod_DependencyLicensesLink() override { BaseClassMustBeDerivedFromService(this); @@ -5143,7 +5251,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestDependencyLicensesLink(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(17, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(18, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5152,7 +5260,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_LandingPageLink() { - ::grpc::Service::MarkMethodRaw(18); + ::grpc::Service::MarkMethodRaw(19); } ~WithRawMethod_LandingPageLink() override { BaseClassMustBeDerivedFromService(this); @@ -5163,7 +5271,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLandingPageLink(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(18, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(19, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5172,7 +5280,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodRaw(19); + ::grpc::Service::MarkMethodRaw(20); } ~WithRawMethod_SetColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -5183,7 +5291,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetColorSchemeName(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(19, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(20, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5192,7 +5300,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodRaw(20); + ::grpc::Service::MarkMethodRaw(21); } ~WithRawMethod_ColorSchemeName() override { BaseClassMustBeDerivedFromService(this); @@ -5203,7 +5311,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestColorSchemeName(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(20, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(21, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5212,7 +5320,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodRaw(21); + ::grpc::Service::MarkMethodRaw(22); } ~WithRawMethod_CurrentEmailClient() override { BaseClassMustBeDerivedFromService(this); @@ -5223,7 +5331,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCurrentEmailClient(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(21, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(22, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5232,7 +5340,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ReportBug() { - ::grpc::Service::MarkMethodRaw(22); + ::grpc::Service::MarkMethodRaw(23); } ~WithRawMethod_ReportBug() override { BaseClassMustBeDerivedFromService(this); @@ -5243,7 +5351,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestReportBug(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(22, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(23, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5252,7 +5360,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodRaw(23); + ::grpc::Service::MarkMethodRaw(24); } ~WithRawMethod_ExportTLSCertificates() override { BaseClassMustBeDerivedFromService(this); @@ -5263,7 +5371,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestExportTLSCertificates(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(23, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(24, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5272,7 +5380,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ForceLauncher() { - ::grpc::Service::MarkMethodRaw(24); + ::grpc::Service::MarkMethodRaw(25); } ~WithRawMethod_ForceLauncher() override { BaseClassMustBeDerivedFromService(this); @@ -5283,7 +5391,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestForceLauncher(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(24, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(25, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5292,7 +5400,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodRaw(25); + ::grpc::Service::MarkMethodRaw(26); } ~WithRawMethod_SetMainExecutable() override { BaseClassMustBeDerivedFromService(this); @@ -5303,7 +5411,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetMainExecutable(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(25, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(26, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5312,7 +5420,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_Login() { - ::grpc::Service::MarkMethodRaw(26); + ::grpc::Service::MarkMethodRaw(27); } ~WithRawMethod_Login() override { BaseClassMustBeDerivedFromService(this); @@ -5323,7 +5431,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(26, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(27, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5332,7 +5440,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_Login2FA() { - ::grpc::Service::MarkMethodRaw(27); + ::grpc::Service::MarkMethodRaw(28); } ~WithRawMethod_Login2FA() override { BaseClassMustBeDerivedFromService(this); @@ -5343,7 +5451,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin2FA(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(27, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(28, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5352,7 +5460,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_Login2Passwords() { - ::grpc::Service::MarkMethodRaw(28); + ::grpc::Service::MarkMethodRaw(29); } ~WithRawMethod_Login2Passwords() override { BaseClassMustBeDerivedFromService(this); @@ -5363,7 +5471,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogin2Passwords(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(28, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(29, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5372,7 +5480,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_LoginAbort() { - ::grpc::Service::MarkMethodRaw(29); + ::grpc::Service::MarkMethodRaw(30); } ~WithRawMethod_LoginAbort() override { BaseClassMustBeDerivedFromService(this); @@ -5383,7 +5491,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLoginAbort(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(29, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(30, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5392,7 +5500,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_CheckUpdate() { - ::grpc::Service::MarkMethodRaw(30); + ::grpc::Service::MarkMethodRaw(31); } ~WithRawMethod_CheckUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -5403,7 +5511,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCheckUpdate(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(30, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(31, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5412,7 +5520,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_InstallUpdate() { - ::grpc::Service::MarkMethodRaw(31); + ::grpc::Service::MarkMethodRaw(32); } ~WithRawMethod_InstallUpdate() override { BaseClassMustBeDerivedFromService(this); @@ -5423,7 +5531,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestInstallUpdate(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(31, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(32, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5432,7 +5540,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodRaw(32); + ::grpc::Service::MarkMethodRaw(33); } ~WithRawMethod_SetIsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -5443,7 +5551,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetIsAutomaticUpdateOn(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(32, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(33, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5452,7 +5560,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodRaw(33); + ::grpc::Service::MarkMethodRaw(34); } ~WithRawMethod_IsAutomaticUpdateOn() override { BaseClassMustBeDerivedFromService(this); @@ -5463,7 +5571,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsAutomaticUpdateOn(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(33, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(34, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5472,7 +5580,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_DiskCachePath() { - ::grpc::Service::MarkMethodRaw(34); + ::grpc::Service::MarkMethodRaw(35); } ~WithRawMethod_DiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -5483,7 +5591,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestDiskCachePath(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(34, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(35, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5492,7 +5600,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodRaw(35); + ::grpc::Service::MarkMethodRaw(36); } ~WithRawMethod_SetDiskCachePath() override { BaseClassMustBeDerivedFromService(this); @@ -5503,7 +5611,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetDiskCachePath(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(35, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(36, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5512,7 +5620,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodRaw(36); + ::grpc::Service::MarkMethodRaw(37); } ~WithRawMethod_SetIsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -5523,7 +5631,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetIsDoHEnabled(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(36, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(37, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5532,7 +5640,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodRaw(37); + ::grpc::Service::MarkMethodRaw(38); } ~WithRawMethod_IsDoHEnabled() override { BaseClassMustBeDerivedFromService(this); @@ -5543,7 +5651,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsDoHEnabled(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(37, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(38, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5552,7 +5660,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_MailServerSettings() { - ::grpc::Service::MarkMethodRaw(38); + ::grpc::Service::MarkMethodRaw(39); } ~WithRawMethod_MailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -5563,7 +5671,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestMailServerSettings(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(38, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(39, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5572,7 +5680,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodRaw(39); + ::grpc::Service::MarkMethodRaw(40); } ~WithRawMethod_SetMailServerSettings() override { BaseClassMustBeDerivedFromService(this); @@ -5583,7 +5691,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetMailServerSettings(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(39, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(40, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5592,7 +5700,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_Hostname() { - ::grpc::Service::MarkMethodRaw(40); + ::grpc::Service::MarkMethodRaw(41); } ~WithRawMethod_Hostname() override { BaseClassMustBeDerivedFromService(this); @@ -5603,7 +5711,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestHostname(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(40, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(41, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5612,7 +5720,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_IsPortFree() { - ::grpc::Service::MarkMethodRaw(41); + ::grpc::Service::MarkMethodRaw(42); } ~WithRawMethod_IsPortFree() override { BaseClassMustBeDerivedFromService(this); @@ -5623,7 +5731,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestIsPortFree(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(41, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(42, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5632,7 +5740,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodRaw(42); + ::grpc::Service::MarkMethodRaw(43); } ~WithRawMethod_AvailableKeychains() override { BaseClassMustBeDerivedFromService(this); @@ -5643,7 +5751,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestAvailableKeychains(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(42, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(43, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5652,7 +5760,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodRaw(43); + ::grpc::Service::MarkMethodRaw(44); } ~WithRawMethod_SetCurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -5663,7 +5771,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetCurrentKeychain(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(43, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(44, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5672,7 +5780,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodRaw(44); + ::grpc::Service::MarkMethodRaw(45); } ~WithRawMethod_CurrentKeychain() override { BaseClassMustBeDerivedFromService(this); @@ -5683,7 +5791,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestCurrentKeychain(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(44, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(45, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5692,7 +5800,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_GetUserList() { - ::grpc::Service::MarkMethodRaw(45); + ::grpc::Service::MarkMethodRaw(46); } ~WithRawMethod_GetUserList() override { BaseClassMustBeDerivedFromService(this); @@ -5703,7 +5811,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestGetUserList(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(45, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(46, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5712,7 +5820,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_GetUser() { - ::grpc::Service::MarkMethodRaw(46); + ::grpc::Service::MarkMethodRaw(47); } ~WithRawMethod_GetUser() override { BaseClassMustBeDerivedFromService(this); @@ -5723,7 +5831,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestGetUser(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(46, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(47, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5732,7 +5840,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodRaw(47); + ::grpc::Service::MarkMethodRaw(48); } ~WithRawMethod_SetUserSplitMode() override { BaseClassMustBeDerivedFromService(this); @@ -5743,7 +5851,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestSetUserSplitMode(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(47, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(48, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5752,7 +5860,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_LogoutUser() { - ::grpc::Service::MarkMethodRaw(48); + ::grpc::Service::MarkMethodRaw(49); } ~WithRawMethod_LogoutUser() override { BaseClassMustBeDerivedFromService(this); @@ -5763,7 +5871,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestLogoutUser(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(48, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(49, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5772,7 +5880,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_RemoveUser() { - ::grpc::Service::MarkMethodRaw(49); + ::grpc::Service::MarkMethodRaw(50); } ~WithRawMethod_RemoveUser() override { BaseClassMustBeDerivedFromService(this); @@ -5783,7 +5891,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestRemoveUser(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(49, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(50, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5792,7 +5900,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodRaw(50); + ::grpc::Service::MarkMethodRaw(51); } ~WithRawMethod_ConfigureUserAppleMail() override { BaseClassMustBeDerivedFromService(this); @@ -5803,7 +5911,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestConfigureUserAppleMail(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(50, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(51, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -5812,7 +5920,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_RunEventStream() { - ::grpc::Service::MarkMethodRaw(51); + ::grpc::Service::MarkMethodRaw(52); } ~WithRawMethod_RunEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -5823,7 +5931,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestRunEventStream(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncWriter< ::grpc::ByteBuffer>* writer, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncServerStreaming(51, context, request, writer, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncServerStreaming(52, context, request, writer, new_call_cq, notification_cq, tag); } }; template @@ -5832,7 +5940,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawMethod_StopEventStream() { - ::grpc::Service::MarkMethodRaw(52); + ::grpc::Service::MarkMethodRaw(53); } ~WithRawMethod_StopEventStream() override { BaseClassMustBeDerivedFromService(this); @@ -5843,7 +5951,7 @@ class Bridge final { return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); } void RequestStopEventStream(::grpc::ServerContext* context, ::grpc::ByteBuffer* request, ::grpc::ServerAsyncResponseWriter< ::grpc::ByteBuffer>* response, ::grpc::CompletionQueue* new_call_cq, ::grpc::ServerCompletionQueue* notification_cq, void *tag) { - ::grpc::Service::RequestAsyncUnary(52, context, request, response, new_call_cq, notification_cq, tag); + ::grpc::Service::RequestAsyncUnary(53, context, request, response, new_call_cq, notification_cq, tag); } }; template @@ -6111,12 +6219,34 @@ class Bridge final { ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } }; template + class WithRawCallbackMethod_GoOs : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithRawCallbackMethod_GoOs() { + ::grpc::Service::MarkMethodRawCallback(12, + new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( + [this]( + ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->GoOs(context, request, response); })); + } + ~WithRawCallbackMethod_GoOs() override { + BaseClassMustBeDerivedFromService(this); + } + // disable synchronous version of this method + ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + virtual ::grpc::ServerUnaryReactor* GoOs( + ::grpc::CallbackServerContext* /*context*/, const ::grpc::ByteBuffer* /*request*/, ::grpc::ByteBuffer* /*response*/) { return nullptr; } + }; + template class WithRawCallbackMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_TriggerReset() { - ::grpc::Service::MarkMethodRawCallback(12, + ::grpc::Service::MarkMethodRawCallback(13, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->TriggerReset(context, request, response); })); @@ -6138,7 +6268,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_Version() { - ::grpc::Service::MarkMethodRawCallback(13, + ::grpc::Service::MarkMethodRawCallback(14, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Version(context, request, response); })); @@ -6160,7 +6290,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_LogsPath() { - ::grpc::Service::MarkMethodRawCallback(14, + ::grpc::Service::MarkMethodRawCallback(15, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->LogsPath(context, request, response); })); @@ -6182,7 +6312,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_LicensePath() { - ::grpc::Service::MarkMethodRawCallback(15, + ::grpc::Service::MarkMethodRawCallback(16, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->LicensePath(context, request, response); })); @@ -6204,7 +6334,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodRawCallback(16, + ::grpc::Service::MarkMethodRawCallback(17, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ReleaseNotesPageLink(context, request, response); })); @@ -6226,7 +6356,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodRawCallback(17, + ::grpc::Service::MarkMethodRawCallback(18, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->DependencyLicensesLink(context, request, response); })); @@ -6248,7 +6378,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_LandingPageLink() { - ::grpc::Service::MarkMethodRawCallback(18, + ::grpc::Service::MarkMethodRawCallback(19, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->LandingPageLink(context, request, response); })); @@ -6270,7 +6400,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodRawCallback(19, + ::grpc::Service::MarkMethodRawCallback(20, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetColorSchemeName(context, request, response); })); @@ -6292,7 +6422,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodRawCallback(20, + ::grpc::Service::MarkMethodRawCallback(21, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ColorSchemeName(context, request, response); })); @@ -6314,7 +6444,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodRawCallback(21, + ::grpc::Service::MarkMethodRawCallback(22, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->CurrentEmailClient(context, request, response); })); @@ -6336,7 +6466,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ReportBug() { - ::grpc::Service::MarkMethodRawCallback(22, + ::grpc::Service::MarkMethodRawCallback(23, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ReportBug(context, request, response); })); @@ -6358,7 +6488,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodRawCallback(23, + ::grpc::Service::MarkMethodRawCallback(24, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ExportTLSCertificates(context, request, response); })); @@ -6380,7 +6510,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ForceLauncher() { - ::grpc::Service::MarkMethodRawCallback(24, + ::grpc::Service::MarkMethodRawCallback(25, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ForceLauncher(context, request, response); })); @@ -6402,7 +6532,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodRawCallback(25, + ::grpc::Service::MarkMethodRawCallback(26, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetMainExecutable(context, request, response); })); @@ -6424,7 +6554,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_Login() { - ::grpc::Service::MarkMethodRawCallback(26, + ::grpc::Service::MarkMethodRawCallback(27, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Login(context, request, response); })); @@ -6446,7 +6576,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_Login2FA() { - ::grpc::Service::MarkMethodRawCallback(27, + ::grpc::Service::MarkMethodRawCallback(28, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Login2FA(context, request, response); })); @@ -6468,7 +6598,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_Login2Passwords() { - ::grpc::Service::MarkMethodRawCallback(28, + ::grpc::Service::MarkMethodRawCallback(29, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Login2Passwords(context, request, response); })); @@ -6490,7 +6620,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_LoginAbort() { - ::grpc::Service::MarkMethodRawCallback(29, + ::grpc::Service::MarkMethodRawCallback(30, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->LoginAbort(context, request, response); })); @@ -6512,7 +6642,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_CheckUpdate() { - ::grpc::Service::MarkMethodRawCallback(30, + ::grpc::Service::MarkMethodRawCallback(31, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->CheckUpdate(context, request, response); })); @@ -6534,7 +6664,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_InstallUpdate() { - ::grpc::Service::MarkMethodRawCallback(31, + ::grpc::Service::MarkMethodRawCallback(32, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->InstallUpdate(context, request, response); })); @@ -6556,7 +6686,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodRawCallback(32, + ::grpc::Service::MarkMethodRawCallback(33, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetIsAutomaticUpdateOn(context, request, response); })); @@ -6578,7 +6708,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodRawCallback(33, + ::grpc::Service::MarkMethodRawCallback(34, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->IsAutomaticUpdateOn(context, request, response); })); @@ -6600,7 +6730,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_DiskCachePath() { - ::grpc::Service::MarkMethodRawCallback(34, + ::grpc::Service::MarkMethodRawCallback(35, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->DiskCachePath(context, request, response); })); @@ -6622,7 +6752,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodRawCallback(35, + ::grpc::Service::MarkMethodRawCallback(36, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetDiskCachePath(context, request, response); })); @@ -6644,7 +6774,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodRawCallback(36, + ::grpc::Service::MarkMethodRawCallback(37, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetIsDoHEnabled(context, request, response); })); @@ -6666,7 +6796,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodRawCallback(37, + ::grpc::Service::MarkMethodRawCallback(38, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->IsDoHEnabled(context, request, response); })); @@ -6688,7 +6818,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_MailServerSettings() { - ::grpc::Service::MarkMethodRawCallback(38, + ::grpc::Service::MarkMethodRawCallback(39, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->MailServerSettings(context, request, response); })); @@ -6710,7 +6840,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodRawCallback(39, + ::grpc::Service::MarkMethodRawCallback(40, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetMailServerSettings(context, request, response); })); @@ -6732,7 +6862,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_Hostname() { - ::grpc::Service::MarkMethodRawCallback(40, + ::grpc::Service::MarkMethodRawCallback(41, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->Hostname(context, request, response); })); @@ -6754,7 +6884,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_IsPortFree() { - ::grpc::Service::MarkMethodRawCallback(41, + ::grpc::Service::MarkMethodRawCallback(42, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->IsPortFree(context, request, response); })); @@ -6776,7 +6906,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodRawCallback(42, + ::grpc::Service::MarkMethodRawCallback(43, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->AvailableKeychains(context, request, response); })); @@ -6798,7 +6928,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodRawCallback(43, + ::grpc::Service::MarkMethodRawCallback(44, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetCurrentKeychain(context, request, response); })); @@ -6820,7 +6950,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodRawCallback(44, + ::grpc::Service::MarkMethodRawCallback(45, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->CurrentKeychain(context, request, response); })); @@ -6842,7 +6972,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_GetUserList() { - ::grpc::Service::MarkMethodRawCallback(45, + ::grpc::Service::MarkMethodRawCallback(46, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->GetUserList(context, request, response); })); @@ -6864,7 +6994,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_GetUser() { - ::grpc::Service::MarkMethodRawCallback(46, + ::grpc::Service::MarkMethodRawCallback(47, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->GetUser(context, request, response); })); @@ -6886,7 +7016,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodRawCallback(47, + ::grpc::Service::MarkMethodRawCallback(48, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->SetUserSplitMode(context, request, response); })); @@ -6908,7 +7038,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_LogoutUser() { - ::grpc::Service::MarkMethodRawCallback(48, + ::grpc::Service::MarkMethodRawCallback(49, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->LogoutUser(context, request, response); })); @@ -6930,7 +7060,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_RemoveUser() { - ::grpc::Service::MarkMethodRawCallback(49, + ::grpc::Service::MarkMethodRawCallback(50, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->RemoveUser(context, request, response); })); @@ -6952,7 +7082,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodRawCallback(50, + ::grpc::Service::MarkMethodRawCallback(51, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->ConfigureUserAppleMail(context, request, response); })); @@ -6974,7 +7104,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_RunEventStream() { - ::grpc::Service::MarkMethodRawCallback(51, + ::grpc::Service::MarkMethodRawCallback(52, new ::grpc::internal::CallbackServerStreamingHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const::grpc::ByteBuffer* request) { return this->RunEventStream(context, request); })); @@ -6996,7 +7126,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithRawCallbackMethod_StopEventStream() { - ::grpc::Service::MarkMethodRawCallback(52, + ::grpc::Service::MarkMethodRawCallback(53, new ::grpc::internal::CallbackUnaryHandler< ::grpc::ByteBuffer, ::grpc::ByteBuffer>( [this]( ::grpc::CallbackServerContext* context, const ::grpc::ByteBuffer* request, ::grpc::ByteBuffer* response) { return this->StopEventStream(context, request, response); })); @@ -7337,12 +7467,39 @@ class Bridge final { virtual ::grpc::Status StreamedIsAllMailVisible(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::google::protobuf::Empty,::google::protobuf::BoolValue>* server_unary_streamer) = 0; }; template + class WithStreamedUnaryMethod_GoOs : public BaseClass { + private: + void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} + public: + WithStreamedUnaryMethod_GoOs() { + ::grpc::Service::MarkMethodStreamed(12, + new ::grpc::internal::StreamedUnaryHandler< + ::google::protobuf::Empty, ::google::protobuf::StringValue>( + [this](::grpc::ServerContext* context, + ::grpc::ServerUnaryStreamer< + ::google::protobuf::Empty, ::google::protobuf::StringValue>* streamer) { + return this->StreamedGoOs(context, + streamer); + })); + } + ~WithStreamedUnaryMethod_GoOs() override { + BaseClassMustBeDerivedFromService(this); + } + // disable regular version of this method + ::grpc::Status GoOs(::grpc::ServerContext* /*context*/, const ::google::protobuf::Empty* /*request*/, ::google::protobuf::StringValue* /*response*/) override { + abort(); + return ::grpc::Status(::grpc::StatusCode::UNIMPLEMENTED, ""); + } + // replace default version of method with streamed unary + virtual ::grpc::Status StreamedGoOs(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::google::protobuf::Empty,::google::protobuf::StringValue>* server_unary_streamer) = 0; + }; + template class WithStreamedUnaryMethod_TriggerReset : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_TriggerReset() { - ::grpc::Service::MarkMethodStreamed(12, + ::grpc::Service::MarkMethodStreamed(13, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7369,7 +7526,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_Version() { - ::grpc::Service::MarkMethodStreamed(13, + ::grpc::Service::MarkMethodStreamed(14, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7396,7 +7553,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_LogsPath() { - ::grpc::Service::MarkMethodStreamed(14, + ::grpc::Service::MarkMethodStreamed(15, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7423,7 +7580,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_LicensePath() { - ::grpc::Service::MarkMethodStreamed(15, + ::grpc::Service::MarkMethodStreamed(16, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7450,7 +7607,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ReleaseNotesPageLink() { - ::grpc::Service::MarkMethodStreamed(16, + ::grpc::Service::MarkMethodStreamed(17, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7477,7 +7634,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_DependencyLicensesLink() { - ::grpc::Service::MarkMethodStreamed(17, + ::grpc::Service::MarkMethodStreamed(18, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7504,7 +7661,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_LandingPageLink() { - ::grpc::Service::MarkMethodStreamed(18, + ::grpc::Service::MarkMethodStreamed(19, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7531,7 +7688,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetColorSchemeName() { - ::grpc::Service::MarkMethodStreamed(19, + ::grpc::Service::MarkMethodStreamed(20, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7558,7 +7715,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ColorSchemeName() { - ::grpc::Service::MarkMethodStreamed(20, + ::grpc::Service::MarkMethodStreamed(21, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7585,7 +7742,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_CurrentEmailClient() { - ::grpc::Service::MarkMethodStreamed(21, + ::grpc::Service::MarkMethodStreamed(22, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7612,7 +7769,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ReportBug() { - ::grpc::Service::MarkMethodStreamed(22, + ::grpc::Service::MarkMethodStreamed(23, new ::grpc::internal::StreamedUnaryHandler< ::grpc::ReportBugRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7639,7 +7796,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ExportTLSCertificates() { - ::grpc::Service::MarkMethodStreamed(23, + ::grpc::Service::MarkMethodStreamed(24, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7666,7 +7823,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ForceLauncher() { - ::grpc::Service::MarkMethodStreamed(24, + ::grpc::Service::MarkMethodStreamed(25, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7693,7 +7850,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetMainExecutable() { - ::grpc::Service::MarkMethodStreamed(25, + ::grpc::Service::MarkMethodStreamed(26, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7720,7 +7877,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_Login() { - ::grpc::Service::MarkMethodStreamed(26, + ::grpc::Service::MarkMethodStreamed(27, new ::grpc::internal::StreamedUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7747,7 +7904,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_Login2FA() { - ::grpc::Service::MarkMethodStreamed(27, + ::grpc::Service::MarkMethodStreamed(28, new ::grpc::internal::StreamedUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7774,7 +7931,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_Login2Passwords() { - ::grpc::Service::MarkMethodStreamed(28, + ::grpc::Service::MarkMethodStreamed(29, new ::grpc::internal::StreamedUnaryHandler< ::grpc::LoginRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7801,7 +7958,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_LoginAbort() { - ::grpc::Service::MarkMethodStreamed(29, + ::grpc::Service::MarkMethodStreamed(30, new ::grpc::internal::StreamedUnaryHandler< ::grpc::LoginAbortRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7828,7 +7985,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_CheckUpdate() { - ::grpc::Service::MarkMethodStreamed(30, + ::grpc::Service::MarkMethodStreamed(31, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7855,7 +8012,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_InstallUpdate() { - ::grpc::Service::MarkMethodStreamed(31, + ::grpc::Service::MarkMethodStreamed(32, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7882,7 +8039,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetIsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodStreamed(32, + ::grpc::Service::MarkMethodStreamed(33, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7909,7 +8066,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_IsAutomaticUpdateOn() { - ::grpc::Service::MarkMethodStreamed(33, + ::grpc::Service::MarkMethodStreamed(34, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>( [this](::grpc::ServerContext* context, @@ -7936,7 +8093,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_DiskCachePath() { - ::grpc::Service::MarkMethodStreamed(34, + ::grpc::Service::MarkMethodStreamed(35, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -7963,7 +8120,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetDiskCachePath() { - ::grpc::Service::MarkMethodStreamed(35, + ::grpc::Service::MarkMethodStreamed(36, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -7990,7 +8147,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetIsDoHEnabled() { - ::grpc::Service::MarkMethodStreamed(36, + ::grpc::Service::MarkMethodStreamed(37, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::BoolValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8017,7 +8174,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_IsDoHEnabled() { - ::grpc::Service::MarkMethodStreamed(37, + ::grpc::Service::MarkMethodStreamed(38, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::BoolValue>( [this](::grpc::ServerContext* context, @@ -8044,7 +8201,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_MailServerSettings() { - ::grpc::Service::MarkMethodStreamed(38, + ::grpc::Service::MarkMethodStreamed(39, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::grpc::ImapSmtpSettings>( [this](::grpc::ServerContext* context, @@ -8071,7 +8228,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetMailServerSettings() { - ::grpc::Service::MarkMethodStreamed(39, + ::grpc::Service::MarkMethodStreamed(40, new ::grpc::internal::StreamedUnaryHandler< ::grpc::ImapSmtpSettings, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8098,7 +8255,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_Hostname() { - ::grpc::Service::MarkMethodStreamed(40, + ::grpc::Service::MarkMethodStreamed(41, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -8125,7 +8282,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_IsPortFree() { - ::grpc::Service::MarkMethodStreamed(41, + ::grpc::Service::MarkMethodStreamed(42, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Int32Value, ::google::protobuf::BoolValue>( [this](::grpc::ServerContext* context, @@ -8152,7 +8309,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_AvailableKeychains() { - ::grpc::Service::MarkMethodStreamed(42, + ::grpc::Service::MarkMethodStreamed(43, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::grpc::AvailableKeychainsResponse>( [this](::grpc::ServerContext* context, @@ -8179,7 +8336,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetCurrentKeychain() { - ::grpc::Service::MarkMethodStreamed(43, + ::grpc::Service::MarkMethodStreamed(44, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8206,7 +8363,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_CurrentKeychain() { - ::grpc::Service::MarkMethodStreamed(44, + ::grpc::Service::MarkMethodStreamed(45, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::StringValue>( [this](::grpc::ServerContext* context, @@ -8233,7 +8390,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_GetUserList() { - ::grpc::Service::MarkMethodStreamed(45, + ::grpc::Service::MarkMethodStreamed(46, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::grpc::UserListResponse>( [this](::grpc::ServerContext* context, @@ -8260,7 +8417,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_GetUser() { - ::grpc::Service::MarkMethodStreamed(46, + ::grpc::Service::MarkMethodStreamed(47, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::grpc::User>( [this](::grpc::ServerContext* context, @@ -8287,7 +8444,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_SetUserSplitMode() { - ::grpc::Service::MarkMethodStreamed(47, + ::grpc::Service::MarkMethodStreamed(48, new ::grpc::internal::StreamedUnaryHandler< ::grpc::UserSplitModeRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8314,7 +8471,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_LogoutUser() { - ::grpc::Service::MarkMethodStreamed(48, + ::grpc::Service::MarkMethodStreamed(49, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8341,7 +8498,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_RemoveUser() { - ::grpc::Service::MarkMethodStreamed(49, + ::grpc::Service::MarkMethodStreamed(50, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::StringValue, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8368,7 +8525,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_ConfigureUserAppleMail() { - ::grpc::Service::MarkMethodStreamed(50, + ::grpc::Service::MarkMethodStreamed(51, new ::grpc::internal::StreamedUnaryHandler< ::grpc::ConfigureAppleMailRequest, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8395,7 +8552,7 @@ class Bridge final { void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithStreamedUnaryMethod_StopEventStream() { - ::grpc::Service::MarkMethodStreamed(52, + ::grpc::Service::MarkMethodStreamed(53, new ::grpc::internal::StreamedUnaryHandler< ::google::protobuf::Empty, ::google::protobuf::Empty>( [this](::grpc::ServerContext* context, @@ -8416,14 +8573,14 @@ class Bridge final { // replace default version of method with streamed unary virtual ::grpc::Status StreamedStopEventStream(::grpc::ServerContext* context, ::grpc::ServerUnaryStreamer< ::google::protobuf::Empty,::google::protobuf::Empty>* server_unary_streamer) = 0; }; - typedef WithStreamedUnaryMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > StreamedUnaryService; + typedef WithStreamedUnaryMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > StreamedUnaryService; template class WithSplitStreamingMethod_RunEventStream : public BaseClass { private: void BaseClassMustBeDerivedFromService(const Service* /*service*/) {} public: WithSplitStreamingMethod_RunEventStream() { - ::grpc::Service::MarkMethodStreamed(51, + ::grpc::Service::MarkMethodStreamed(52, new ::grpc::internal::SplitServerStreamingHandler< ::grpc::EventStreamRequest, ::grpc::StreamEvent>( [this](::grpc::ServerContext* context, @@ -8445,7 +8602,7 @@ class Bridge final { virtual ::grpc::Status StreamedRunEventStream(::grpc::ServerContext* context, ::grpc::ServerSplitStreamer< ::grpc::EventStreamRequest,::grpc::StreamEvent>* server_split_streamer) = 0; }; typedef WithSplitStreamingMethod_RunEventStream SplitStreamedService; - typedef WithStreamedUnaryMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > StreamedService; + typedef WithStreamedUnaryMethod_CheckTokens > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > StreamedService; }; } // namespace grpc diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc index d658ed53..143d8255 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/bridge.pb.cc @@ -1647,7 +1647,7 @@ const char descriptor_table_protodef_bridge_2eproto[] PROTOBUF_SECTION_VARIABLE( "ANGE_ERROR\020\004\022%\n!SMTP_CONNECTION_MODE_CHA" "NGE_ERROR\020\005*S\n\tErrorCode\022\021\n\rUNKNOWN_ERRO" "R\020\000\022\031\n\025TLS_CERT_EXPORT_ERROR\020\001\022\030\n\024TLS_KE" - "Y_EXPORT_ERROR\020\0022\333\034\n\006Bridge\022I\n\013CheckToke" + "Y_EXPORT_ERROR\020\0022\231\035\n\006Bridge\022I\n\013CheckToke" "ns\022\034.google.protobuf.StringValue\032\034.googl" "e.protobuf.StringValue\022\?\n\013AddLogEntry\022\030." "grpc.AddLogEntryRequest\032\026.google.protobu" @@ -1668,79 +1668,81 @@ const char descriptor_table_protodef_bridge_2eproto[] PROTOBUF_SECTION_VARIABLE( "oogle.protobuf.BoolValue\032\026.google.protob" "uf.Empty\022F\n\020IsAllMailVisible\022\026.google.pr" "otobuf.Empty\032\032.google.protobuf.BoolValue" - "\022>\n\014TriggerReset\022\026.google.protobuf.Empty" - "\032\026.google.protobuf.Empty\022\?\n\007Version\022\026.go" - "ogle.protobuf.Empty\032\034.google.protobuf.St" - "ringValue\022@\n\010LogsPath\022\026.google.protobuf." - "Empty\032\034.google.protobuf.StringValue\022C\n\013L" - "icensePath\022\026.google.protobuf.Empty\032\034.goo" - "gle.protobuf.StringValue\022L\n\024ReleaseNotes" - "PageLink\022\026.google.protobuf.Empty\032\034.googl" - "e.protobuf.StringValue\022N\n\026DependencyLice" - "nsesLink\022\026.google.protobuf.Empty\032\034.googl" - "e.protobuf.StringValue\022G\n\017LandingPageLin" - "k\022\026.google.protobuf.Empty\032\034.google.proto" - "buf.StringValue\022J\n\022SetColorSchemeName\022\034." - "google.protobuf.StringValue\032\026.google.pro" - "tobuf.Empty\022G\n\017ColorSchemeName\022\026.google." + "\022<\n\004GoOs\022\026.google.protobuf.Empty\032\034.googl" + "e.protobuf.StringValue\022>\n\014TriggerReset\022\026" + ".google.protobuf.Empty\032\026.google.protobuf" + ".Empty\022\?\n\007Version\022\026.google.protobuf.Empt" + "y\032\034.google.protobuf.StringValue\022@\n\010LogsP" + "ath\022\026.google.protobuf.Empty\032\034.google.pro" + "tobuf.StringValue\022C\n\013LicensePath\022\026.googl" + "e.protobuf.Empty\032\034.google.protobuf.Strin" + "gValue\022L\n\024ReleaseNotesPageLink\022\026.google." "protobuf.Empty\032\034.google.protobuf.StringV" - "alue\022J\n\022CurrentEmailClient\022\026.google.prot" - "obuf.Empty\032\034.google.protobuf.StringValue" - "\022;\n\tReportBug\022\026.grpc.ReportBugRequest\032\026." - "google.protobuf.Empty\022M\n\025ExportTLSCertif" - "icates\022\034.google.protobuf.StringValue\032\026.g" - "oogle.protobuf.Empty\022E\n\rForceLauncher\022\034." - "google.protobuf.StringValue\032\026.google.pro" - "tobuf.Empty\022I\n\021SetMainExecutable\022\034.googl" - "e.protobuf.StringValue\032\026.google.protobuf" - ".Empty\0223\n\005Login\022\022.grpc.LoginRequest\032\026.go" - "ogle.protobuf.Empty\0226\n\010Login2FA\022\022.grpc.L" - "oginRequest\032\026.google.protobuf.Empty\022=\n\017L" - "ogin2Passwords\022\022.grpc.LoginRequest\032\026.goo" - "gle.protobuf.Empty\022=\n\nLoginAbort\022\027.grpc." - "LoginAbortRequest\032\026.google.protobuf.Empt" - "y\022=\n\013CheckUpdate\022\026.google.protobuf.Empty" - "\032\026.google.protobuf.Empty\022\?\n\rInstallUpdat" - "e\022\026.google.protobuf.Empty\032\026.google.proto" - "buf.Empty\022L\n\026SetIsAutomaticUpdateOn\022\032.go" - "ogle.protobuf.BoolValue\032\026.google.protobu" - "f.Empty\022I\n\023IsAutomaticUpdateOn\022\026.google." - "protobuf.Empty\032\032.google.protobuf.BoolVal" - "ue\022E\n\rDiskCachePath\022\026.google.protobuf.Em" - "pty\032\034.google.protobuf.StringValue\022H\n\020Set" - "DiskCachePath\022\034.google.protobuf.StringVa" - "lue\032\026.google.protobuf.Empty\022E\n\017SetIsDoHE" - "nabled\022\032.google.protobuf.BoolValue\032\026.goo" - "gle.protobuf.Empty\022B\n\014IsDoHEnabled\022\026.goo" - "gle.protobuf.Empty\032\032.google.protobuf.Boo" - "lValue\022D\n\022MailServerSettings\022\026.google.pr" - "otobuf.Empty\032\026.grpc.ImapSmtpSettings\022G\n\025" - "SetMailServerSettings\022\026.grpc.ImapSmtpSet" - "tings\032\026.google.protobuf.Empty\022@\n\010Hostnam" - "e\022\026.google.protobuf.Empty\032\034.google.proto" - "buf.StringValue\022E\n\nIsPortFree\022\033.google.p" - "rotobuf.Int32Value\032\032.google.protobuf.Boo" - "lValue\022N\n\022AvailableKeychains\022\026.google.pr" - "otobuf.Empty\032 .grpc.AvailableKeychainsRe" - "sponse\022J\n\022SetCurrentKeychain\022\034.google.pr" + "alue\022N\n\026DependencyLicensesLink\022\026.google." + "protobuf.Empty\032\034.google.protobuf.StringV" + "alue\022G\n\017LandingPageLink\022\026.google.protobu" + "f.Empty\032\034.google.protobuf.StringValue\022J\n" + "\022SetColorSchemeName\022\034.google.protobuf.St" + "ringValue\032\026.google.protobuf.Empty\022G\n\017Col" + "orSchemeName\022\026.google.protobuf.Empty\032\034.g" + "oogle.protobuf.StringValue\022J\n\022CurrentEma" + "ilClient\022\026.google.protobuf.Empty\032\034.googl" + "e.protobuf.StringValue\022;\n\tReportBug\022\026.gr" + "pc.ReportBugRequest\032\026.google.protobuf.Em" + "pty\022M\n\025ExportTLSCertificates\022\034.google.pr" "otobuf.StringValue\032\026.google.protobuf.Emp" - "ty\022G\n\017CurrentKeychain\022\026.google.protobuf." - "Empty\032\034.google.protobuf.StringValue\022=\n\013G" - "etUserList\022\026.google.protobuf.Empty\032\026.grp" - "c.UserListResponse\0223\n\007GetUser\022\034.google.p" - "rotobuf.StringValue\032\n.grpc.User\022F\n\020SetUs" - "erSplitMode\022\032.grpc.UserSplitModeRequest\032" - "\026.google.protobuf.Empty\022B\n\nLogoutUser\022\034." - "google.protobuf.StringValue\032\026.google.pro" - "tobuf.Empty\022B\n\nRemoveUser\022\034.google.proto" - "buf.StringValue\032\026.google.protobuf.Empty\022" - "Q\n\026ConfigureUserAppleMail\022\037.grpc.Configu" - "reAppleMailRequest\032\026.google.protobuf.Emp" - "ty\022\?\n\016RunEventStream\022\030.grpc.EventStreamR" - "equest\032\021.grpc.StreamEvent0\001\022A\n\017StopEvent" - "Stream\022\026.google.protobuf.Empty\032\026.google." - "protobuf.EmptyB6Z4github.com/ProtonMail/" - "proton-bridge/v3/internal/grpcb\006proto3" + "ty\022E\n\rForceLauncher\022\034.google.protobuf.St" + "ringValue\032\026.google.protobuf.Empty\022I\n\021Set" + "MainExecutable\022\034.google.protobuf.StringV" + "alue\032\026.google.protobuf.Empty\0223\n\005Login\022\022." + "grpc.LoginRequest\032\026.google.protobuf.Empt" + "y\0226\n\010Login2FA\022\022.grpc.LoginRequest\032\026.goog" + "le.protobuf.Empty\022=\n\017Login2Passwords\022\022.g" + "rpc.LoginRequest\032\026.google.protobuf.Empty" + "\022=\n\nLoginAbort\022\027.grpc.LoginAbortRequest\032" + "\026.google.protobuf.Empty\022=\n\013CheckUpdate\022\026" + ".google.protobuf.Empty\032\026.google.protobuf" + ".Empty\022\?\n\rInstallUpdate\022\026.google.protobu" + "f.Empty\032\026.google.protobuf.Empty\022L\n\026SetIs" + "AutomaticUpdateOn\022\032.google.protobuf.Bool" + "Value\032\026.google.protobuf.Empty\022I\n\023IsAutom" + "aticUpdateOn\022\026.google.protobuf.Empty\032\032.g" + "oogle.protobuf.BoolValue\022E\n\rDiskCachePat" + "h\022\026.google.protobuf.Empty\032\034.google.proto" + "buf.StringValue\022H\n\020SetDiskCachePath\022\034.go" + "ogle.protobuf.StringValue\032\026.google.proto" + "buf.Empty\022E\n\017SetIsDoHEnabled\022\032.google.pr" + "otobuf.BoolValue\032\026.google.protobuf.Empty" + "\022B\n\014IsDoHEnabled\022\026.google.protobuf.Empty" + "\032\032.google.protobuf.BoolValue\022D\n\022MailServ" + "erSettings\022\026.google.protobuf.Empty\032\026.grp" + "c.ImapSmtpSettings\022G\n\025SetMailServerSetti" + "ngs\022\026.grpc.ImapSmtpSettings\032\026.google.pro" + "tobuf.Empty\022@\n\010Hostname\022\026.google.protobu" + "f.Empty\032\034.google.protobuf.StringValue\022E\n" + "\nIsPortFree\022\033.google.protobuf.Int32Value" + "\032\032.google.protobuf.BoolValue\022N\n\022Availabl" + "eKeychains\022\026.google.protobuf.Empty\032 .grp" + "c.AvailableKeychainsResponse\022J\n\022SetCurre" + "ntKeychain\022\034.google.protobuf.StringValue" + "\032\026.google.protobuf.Empty\022G\n\017CurrentKeych" + "ain\022\026.google.protobuf.Empty\032\034.google.pro" + "tobuf.StringValue\022=\n\013GetUserList\022\026.googl" + "e.protobuf.Empty\032\026.grpc.UserListResponse" + "\0223\n\007GetUser\022\034.google.protobuf.StringValu" + "e\032\n.grpc.User\022F\n\020SetUserSplitMode\022\032.grpc" + ".UserSplitModeRequest\032\026.google.protobuf." + "Empty\022B\n\nLogoutUser\022\034.google.protobuf.St" + "ringValue\032\026.google.protobuf.Empty\022B\n\nRem" + "oveUser\022\034.google.protobuf.StringValue\032\026." + "google.protobuf.Empty\022Q\n\026ConfigureUserAp" + "pleMail\022\037.grpc.ConfigureAppleMailRequest" + "\032\026.google.protobuf.Empty\022\?\n\016RunEventStre" + "am\022\030.grpc.EventStreamRequest\032\021.grpc.Stre" + "amEvent0\001\022A\n\017StopEventStream\022\026.google.pr" + "otobuf.Empty\032\026.google.protobuf.EmptyB6Z4" + "github.com/ProtonMail/proton-bridge/v3/i" + "nternal/grpcb\006proto3" ; static const ::_pbi::DescriptorTable* const descriptor_table_bridge_2eproto_deps[2] = { &::descriptor_table_google_2fprotobuf_2fempty_2eproto, @@ -1748,7 +1750,7 @@ static const ::_pbi::DescriptorTable* const descriptor_table_bridge_2eproto_deps }; static ::_pbi::once_flag descriptor_table_bridge_2eproto_once; const ::_pbi::DescriptorTable descriptor_table_bridge_2eproto = { - false, false, 10318, descriptor_table_protodef_bridge_2eproto, + false, false, 10380, descriptor_table_protodef_bridge_2eproto, "bridge.proto", &descriptor_table_bridge_2eproto_once, descriptor_table_bridge_2eproto_deps, 2, 63, schemas, file_default_instances, TableStruct_bridge_2eproto::offsets, diff --git a/internal/frontend/grpc/bridge.pb.go b/internal/frontend/grpc/bridge.pb.go index 020b4b7e..0f6a1a8b 100644 --- a/internal/frontend/grpc/bridge.pb.go +++ b/internal/frontend/grpc/bridge.pb.go @@ -4743,7 +4743,7 @@ var file_bridge_proto_rawDesc = []byte{ 0x52, 0x52, 0x4f, 0x52, 0x10, 0x00, 0x12, 0x19, 0x0a, 0x15, 0x54, 0x4c, 0x53, 0x5f, 0x43, 0x45, 0x52, 0x54, 0x5f, 0x45, 0x58, 0x50, 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x01, 0x12, 0x18, 0x0a, 0x14, 0x54, 0x4c, 0x53, 0x5f, 0x4b, 0x45, 0x59, 0x5f, 0x45, 0x58, 0x50, - 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x32, 0xdb, 0x1c, 0x0a, 0x06, + 0x4f, 0x52, 0x54, 0x5f, 0x45, 0x52, 0x52, 0x4f, 0x52, 0x10, 0x02, 0x32, 0x99, 0x1d, 0x0a, 0x06, 0x42, 0x72, 0x69, 0x64, 0x67, 0x65, 0x12, 0x49, 0x0a, 0x0b, 0x43, 0x68, 0x65, 0x63, 0x6b, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, @@ -4795,189 +4795,193 @@ var file_bridge_proto_rawDesc = []byte{ 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, - 0x73, 0x65, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6c, 0x75, 0x65, 0x12, 0x3c, 0x0a, 0x04, 0x47, 0x6f, 0x4f, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, + 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x3e, 0x0a, 0x0c, 0x54, 0x72, 0x69, 0x67, 0x67, 0x65, 0x72, 0x52, 0x65, 0x73, 0x65, + 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, + 0x79, 0x12, 0x3f, 0x0a, 0x07, 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, + 0x75, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, - 0x61, 0x6c, 0x75, 0x65, 0x12, 0x40, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x73, 0x50, 0x61, 0x74, 0x68, - 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, - 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4c, 0x0a, 0x14, 0x52, - 0x65, 0x6c, 0x65, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x50, 0x61, 0x67, 0x65, 0x4c, - 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x61, 0x6c, 0x75, 0x65, 0x12, 0x43, 0x0a, 0x0b, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x50, + 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x16, 0x44, 0x65, 0x70, - 0x65, 0x6e, 0x64, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x4c, - 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x47, 0x0a, 0x0f, 0x4c, 0x61, 0x6e, - 0x64, 0x69, 0x6e, 0x67, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, - 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, - 0x0a, 0x0f, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, - 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4c, 0x0a, 0x14, 0x52, 0x65, 0x6c, + 0x65, 0x61, 0x73, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x73, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, + 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, - 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x43, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x74, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, - 0x6c, 0x75, 0x65, 0x12, 0x3b, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, - 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, - 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x4d, 0x0a, 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x16, 0x44, 0x65, 0x70, 0x65, 0x6e, + 0x64, 0x65, 0x6e, 0x63, 0x79, 0x4c, 0x69, 0x63, 0x65, 0x6e, 0x73, 0x65, 0x73, 0x4c, 0x69, 0x6e, + 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, + 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x47, 0x0a, 0x0f, 0x4c, 0x61, 0x6e, 0x64, 0x69, + 0x6e, 0x67, 0x50, 0x61, 0x67, 0x65, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, + 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, + 0x43, 0x6f, 0x6c, 0x6f, 0x72, 0x53, 0x63, 0x68, 0x65, 0x6d, 0x65, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, + 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, + 0x65, 0x12, 0x3b, 0x0a, 0x09, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, 0x12, 0x16, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x42, 0x75, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4d, + 0x0a, 0x15, 0x45, 0x78, 0x70, 0x6f, 0x72, 0x74, 0x54, 0x4c, 0x53, 0x43, 0x65, 0x72, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x65, 0x73, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, + 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, + 0x0d, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x72, 0x12, 0x1c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6e, 0x45, + 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, - 0x45, 0x0a, 0x0d, 0x46, 0x6f, 0x72, 0x63, 0x65, 0x4c, 0x61, 0x75, 0x6e, 0x63, 0x68, 0x65, 0x72, - 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x11, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, - 0x6e, 0x45, 0x78, 0x65, 0x63, 0x75, 0x74, 0x61, 0x62, 0x6c, 0x65, 0x12, 0x1c, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, - 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, - 0x79, 0x12, 0x33, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, - 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, - 0x46, 0x41, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, - 0x0a, 0x0f, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, - 0x73, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, - 0x0a, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x67, 0x72, - 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, + 0x33, 0x0a, 0x05, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, + 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x12, 0x36, 0x0a, 0x08, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x46, 0x41, + 0x12, 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0b, - 0x43, 0x68, 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, - 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, - 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0d, 0x49, - 0x6e, 0x73, 0x74, 0x61, 0x6c, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4c, 0x0a, 0x16, - 0x53, 0x65, 0x74, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x13, 0x49, 0x73, - 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, - 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, - 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x48, 0x0a, 0x10, - 0x53, 0x65, 0x74, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, - 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x49, 0x73, 0x44, - 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, - 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, - 0x0c, 0x49, 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, - 0x65, 0x12, 0x44, 0x0a, 0x12, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, - 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, - 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x4d, 0x61, - 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x12, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, - 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x12, 0x40, 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, - 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, - 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0a, 0x49, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x72, 0x65, 0x65, - 0x12, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1a, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x12, 0x41, 0x76, 0x61, - 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, - 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, - 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, - 0x73, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, - 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, - 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, - 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, - 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, - 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, - 0x72, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, - 0x07, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x0a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, - 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, - 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0f, + 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x32, 0x50, 0x61, 0x73, 0x73, 0x77, 0x6f, 0x72, 0x64, 0x73, 0x12, + 0x12, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0a, 0x4c, + 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x12, 0x17, 0x2e, 0x67, 0x72, 0x70, 0x63, + 0x2e, 0x4c, 0x6f, 0x67, 0x69, 0x6e, 0x41, 0x62, 0x6f, 0x72, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x4c, 0x6f, - 0x67, 0x6f, 0x75, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, - 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, - 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, - 0x0a, 0x0a, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, - 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, - 0x74, 0x79, 0x12, 0x51, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x55, - 0x73, 0x65, 0x72, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x2e, 0x67, - 0x72, 0x70, 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x41, 0x70, 0x70, - 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, - 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x11, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x74, 0x6f, 0x70, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3d, 0x0a, 0x0b, 0x43, 0x68, + 0x65, 0x63, 0x6b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, - 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, - 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x4d, 0x61, - 0x69, 0x6c, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, - 0x2f, 0x76, 0x33, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x72, 0x70, - 0x63, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0d, 0x49, 0x6e, 0x73, + 0x74, 0x61, 0x6c, 0x6c, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x4c, 0x0a, 0x16, 0x53, 0x65, + 0x74, 0x49, 0x73, 0x41, 0x75, 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x4f, 0x6e, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x49, 0x0a, 0x13, 0x49, 0x73, 0x41, 0x75, + 0x74, 0x6f, 0x6d, 0x61, 0x74, 0x69, 0x63, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4f, 0x6e, 0x12, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x12, 0x45, 0x0a, 0x0d, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, + 0x50, 0x61, 0x74, 0x68, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, + 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x48, 0x0a, 0x10, 0x53, 0x65, + 0x74, 0x44, 0x69, 0x73, 0x6b, 0x43, 0x61, 0x63, 0x68, 0x65, 0x50, 0x61, 0x74, 0x68, 0x12, 0x1c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, + 0x6d, 0x70, 0x74, 0x79, 0x12, 0x45, 0x0a, 0x0f, 0x53, 0x65, 0x74, 0x49, 0x73, 0x44, 0x6f, 0x48, + 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, + 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0c, 0x49, + 0x73, 0x44, 0x6f, 0x48, 0x45, 0x6e, 0x61, 0x62, 0x6c, 0x65, 0x64, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, + 0x44, 0x0a, 0x12, 0x4d, 0x61, 0x69, 0x6c, 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, + 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, 0x74, + 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x47, 0x0a, 0x15, 0x53, 0x65, 0x74, 0x4d, 0x61, 0x69, 0x6c, + 0x53, 0x65, 0x72, 0x76, 0x65, 0x72, 0x53, 0x65, 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x16, + 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x49, 0x6d, 0x61, 0x70, 0x53, 0x6d, 0x74, 0x70, 0x53, 0x65, + 0x74, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x40, + 0x0a, 0x08, 0x48, 0x6f, 0x73, 0x74, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, + 0x74, 0x79, 0x1a, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, + 0x12, 0x45, 0x0a, 0x0a, 0x49, 0x73, 0x50, 0x6f, 0x72, 0x74, 0x46, 0x72, 0x65, 0x65, 0x12, 0x1b, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x1a, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x42, 0x6f, + 0x6f, 0x6c, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x4e, 0x0a, 0x12, 0x41, 0x76, 0x61, 0x69, 0x6c, + 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x12, 0x16, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x20, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x41, 0x76, 0x61, + 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x73, 0x52, + 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x4a, 0x0a, 0x12, 0x53, 0x65, 0x74, 0x43, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x1c, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x47, 0x0a, 0x0f, 0x43, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x4b, 0x65, + 0x79, 0x63, 0x68, 0x61, 0x69, 0x6e, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, 0x1c, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x12, 0x3d, 0x0a, 0x0b, + 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x1a, 0x16, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x65, 0x12, 0x33, 0x0a, 0x07, 0x47, + 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x0a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x12, 0x46, 0x0a, 0x10, 0x53, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x53, 0x70, 0x6c, 0x69, 0x74, + 0x4d, 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x55, 0x73, 0x65, 0x72, + 0x53, 0x70, 0x6c, 0x69, 0x74, 0x4d, 0x6f, 0x64, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, 0x4c, 0x6f, 0x67, 0x6f, + 0x75, 0x74, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, 0x69, 0x6e, 0x67, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, + 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x12, 0x42, 0x0a, 0x0a, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x55, 0x73, 0x65, 0x72, 0x12, 0x1c, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x53, 0x74, 0x72, + 0x69, 0x6e, 0x67, 0x56, 0x61, 0x6c, 0x75, 0x65, 0x1a, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, + 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, + 0x12, 0x51, 0x0a, 0x16, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x55, 0x73, 0x65, + 0x72, 0x41, 0x70, 0x70, 0x6c, 0x65, 0x4d, 0x61, 0x69, 0x6c, 0x12, 0x1f, 0x2e, 0x67, 0x72, 0x70, + 0x63, 0x2e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x67, 0x75, 0x72, 0x65, 0x41, 0x70, 0x70, 0x6c, 0x65, + 0x4d, 0x61, 0x69, 0x6c, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x67, 0x6f, + 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, + 0x70, 0x74, 0x79, 0x12, 0x3f, 0x0a, 0x0e, 0x52, 0x75, 0x6e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, + 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x18, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x11, 0x2e, 0x67, 0x72, 0x70, 0x63, 0x2e, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x30, 0x01, 0x12, 0x41, 0x0a, 0x0f, 0x53, 0x74, 0x6f, 0x70, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x53, 0x74, 0x72, 0x65, 0x61, 0x6d, 0x12, 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x1a, + 0x16, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, + 0x66, 0x2e, 0x45, 0x6d, 0x70, 0x74, 0x79, 0x42, 0x36, 0x5a, 0x34, 0x67, 0x69, 0x74, 0x68, 0x75, + 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x4d, 0x61, 0x69, 0x6c, + 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x6e, 0x2d, 0x62, 0x72, 0x69, 0x64, 0x67, 0x65, 0x2f, 0x76, + 0x33, 0x2f, 0x69, 0x6e, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x2f, 0x67, 0x72, 0x70, 0x63, 0x62, + 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -5143,102 +5147,104 @@ var file_bridge_proto_depIdxs = []int32{ 71, // 69: grpc.Bridge.IsBetaEnabled:input_type -> google.protobuf.Empty 72, // 70: grpc.Bridge.SetIsAllMailVisible:input_type -> google.protobuf.BoolValue 71, // 71: grpc.Bridge.IsAllMailVisible:input_type -> google.protobuf.Empty - 71, // 72: grpc.Bridge.TriggerReset:input_type -> google.protobuf.Empty - 71, // 73: grpc.Bridge.Version:input_type -> google.protobuf.Empty - 71, // 74: grpc.Bridge.LogsPath:input_type -> google.protobuf.Empty - 71, // 75: grpc.Bridge.LicensePath:input_type -> google.protobuf.Empty - 71, // 76: grpc.Bridge.ReleaseNotesPageLink:input_type -> google.protobuf.Empty - 71, // 77: grpc.Bridge.DependencyLicensesLink:input_type -> google.protobuf.Empty - 71, // 78: grpc.Bridge.LandingPageLink:input_type -> google.protobuf.Empty - 70, // 79: grpc.Bridge.SetColorSchemeName:input_type -> google.protobuf.StringValue - 71, // 80: grpc.Bridge.ColorSchemeName:input_type -> google.protobuf.Empty - 71, // 81: grpc.Bridge.CurrentEmailClient:input_type -> google.protobuf.Empty - 9, // 82: grpc.Bridge.ReportBug:input_type -> grpc.ReportBugRequest - 70, // 83: grpc.Bridge.ExportTLSCertificates:input_type -> google.protobuf.StringValue - 70, // 84: grpc.Bridge.ForceLauncher:input_type -> google.protobuf.StringValue - 70, // 85: grpc.Bridge.SetMainExecutable:input_type -> google.protobuf.StringValue - 10, // 86: grpc.Bridge.Login:input_type -> grpc.LoginRequest - 10, // 87: grpc.Bridge.Login2FA:input_type -> grpc.LoginRequest - 10, // 88: grpc.Bridge.Login2Passwords:input_type -> grpc.LoginRequest - 11, // 89: grpc.Bridge.LoginAbort:input_type -> grpc.LoginAbortRequest - 71, // 90: grpc.Bridge.CheckUpdate:input_type -> google.protobuf.Empty - 71, // 91: grpc.Bridge.InstallUpdate:input_type -> google.protobuf.Empty - 72, // 92: grpc.Bridge.SetIsAutomaticUpdateOn:input_type -> google.protobuf.BoolValue - 71, // 93: grpc.Bridge.IsAutomaticUpdateOn:input_type -> google.protobuf.Empty - 71, // 94: grpc.Bridge.DiskCachePath:input_type -> google.protobuf.Empty - 70, // 95: grpc.Bridge.SetDiskCachePath:input_type -> google.protobuf.StringValue - 72, // 96: grpc.Bridge.SetIsDoHEnabled:input_type -> google.protobuf.BoolValue - 71, // 97: grpc.Bridge.IsDoHEnabled:input_type -> google.protobuf.Empty - 71, // 98: grpc.Bridge.MailServerSettings:input_type -> google.protobuf.Empty - 12, // 99: grpc.Bridge.SetMailServerSettings:input_type -> grpc.ImapSmtpSettings - 71, // 100: grpc.Bridge.Hostname:input_type -> google.protobuf.Empty - 73, // 101: grpc.Bridge.IsPortFree:input_type -> google.protobuf.Int32Value - 71, // 102: grpc.Bridge.AvailableKeychains:input_type -> google.protobuf.Empty - 70, // 103: grpc.Bridge.SetCurrentKeychain:input_type -> google.protobuf.StringValue - 71, // 104: grpc.Bridge.CurrentKeychain:input_type -> google.protobuf.Empty - 71, // 105: grpc.Bridge.GetUserList:input_type -> google.protobuf.Empty - 70, // 106: grpc.Bridge.GetUser:input_type -> google.protobuf.StringValue - 15, // 107: grpc.Bridge.SetUserSplitMode:input_type -> grpc.UserSplitModeRequest - 70, // 108: grpc.Bridge.LogoutUser:input_type -> google.protobuf.StringValue - 70, // 109: grpc.Bridge.RemoveUser:input_type -> google.protobuf.StringValue - 17, // 110: grpc.Bridge.ConfigureUserAppleMail:input_type -> grpc.ConfigureAppleMailRequest - 18, // 111: grpc.Bridge.RunEventStream:input_type -> grpc.EventStreamRequest - 71, // 112: grpc.Bridge.StopEventStream:input_type -> google.protobuf.Empty - 70, // 113: grpc.Bridge.CheckTokens:output_type -> google.protobuf.StringValue - 71, // 114: grpc.Bridge.AddLogEntry:output_type -> google.protobuf.Empty - 8, // 115: grpc.Bridge.GuiReady:output_type -> grpc.GuiReadyResponse - 71, // 116: grpc.Bridge.Quit:output_type -> google.protobuf.Empty - 71, // 117: grpc.Bridge.Restart:output_type -> google.protobuf.Empty - 72, // 118: grpc.Bridge.ShowOnStartup:output_type -> google.protobuf.BoolValue - 71, // 119: grpc.Bridge.SetIsAutostartOn:output_type -> google.protobuf.Empty - 72, // 120: grpc.Bridge.IsAutostartOn:output_type -> google.protobuf.BoolValue - 71, // 121: grpc.Bridge.SetIsBetaEnabled:output_type -> google.protobuf.Empty - 72, // 122: grpc.Bridge.IsBetaEnabled:output_type -> google.protobuf.BoolValue - 71, // 123: grpc.Bridge.SetIsAllMailVisible:output_type -> google.protobuf.Empty - 72, // 124: grpc.Bridge.IsAllMailVisible:output_type -> google.protobuf.BoolValue - 71, // 125: grpc.Bridge.TriggerReset:output_type -> google.protobuf.Empty - 70, // 126: grpc.Bridge.Version:output_type -> google.protobuf.StringValue - 70, // 127: grpc.Bridge.LogsPath:output_type -> google.protobuf.StringValue - 70, // 128: grpc.Bridge.LicensePath:output_type -> google.protobuf.StringValue - 70, // 129: grpc.Bridge.ReleaseNotesPageLink:output_type -> google.protobuf.StringValue - 70, // 130: grpc.Bridge.DependencyLicensesLink:output_type -> google.protobuf.StringValue - 70, // 131: grpc.Bridge.LandingPageLink:output_type -> google.protobuf.StringValue - 71, // 132: grpc.Bridge.SetColorSchemeName:output_type -> google.protobuf.Empty - 70, // 133: grpc.Bridge.ColorSchemeName:output_type -> google.protobuf.StringValue - 70, // 134: grpc.Bridge.CurrentEmailClient:output_type -> google.protobuf.StringValue - 71, // 135: grpc.Bridge.ReportBug:output_type -> google.protobuf.Empty - 71, // 136: grpc.Bridge.ExportTLSCertificates:output_type -> google.protobuf.Empty - 71, // 137: grpc.Bridge.ForceLauncher:output_type -> google.protobuf.Empty - 71, // 138: grpc.Bridge.SetMainExecutable:output_type -> google.protobuf.Empty - 71, // 139: grpc.Bridge.Login:output_type -> google.protobuf.Empty - 71, // 140: grpc.Bridge.Login2FA:output_type -> google.protobuf.Empty - 71, // 141: grpc.Bridge.Login2Passwords:output_type -> google.protobuf.Empty - 71, // 142: grpc.Bridge.LoginAbort:output_type -> google.protobuf.Empty - 71, // 143: grpc.Bridge.CheckUpdate:output_type -> google.protobuf.Empty - 71, // 144: grpc.Bridge.InstallUpdate:output_type -> google.protobuf.Empty - 71, // 145: grpc.Bridge.SetIsAutomaticUpdateOn:output_type -> google.protobuf.Empty - 72, // 146: grpc.Bridge.IsAutomaticUpdateOn:output_type -> google.protobuf.BoolValue - 70, // 147: grpc.Bridge.DiskCachePath:output_type -> google.protobuf.StringValue - 71, // 148: grpc.Bridge.SetDiskCachePath:output_type -> google.protobuf.Empty - 71, // 149: grpc.Bridge.SetIsDoHEnabled:output_type -> google.protobuf.Empty - 72, // 150: grpc.Bridge.IsDoHEnabled:output_type -> google.protobuf.BoolValue - 12, // 151: grpc.Bridge.MailServerSettings:output_type -> grpc.ImapSmtpSettings - 71, // 152: grpc.Bridge.SetMailServerSettings:output_type -> google.protobuf.Empty - 70, // 153: grpc.Bridge.Hostname:output_type -> google.protobuf.StringValue - 72, // 154: grpc.Bridge.IsPortFree:output_type -> google.protobuf.BoolValue - 13, // 155: grpc.Bridge.AvailableKeychains:output_type -> grpc.AvailableKeychainsResponse - 71, // 156: grpc.Bridge.SetCurrentKeychain:output_type -> google.protobuf.Empty - 70, // 157: grpc.Bridge.CurrentKeychain:output_type -> google.protobuf.StringValue - 16, // 158: grpc.Bridge.GetUserList:output_type -> grpc.UserListResponse - 14, // 159: grpc.Bridge.GetUser:output_type -> grpc.User - 71, // 160: grpc.Bridge.SetUserSplitMode:output_type -> google.protobuf.Empty - 71, // 161: grpc.Bridge.LogoutUser:output_type -> google.protobuf.Empty - 71, // 162: grpc.Bridge.RemoveUser:output_type -> google.protobuf.Empty - 71, // 163: grpc.Bridge.ConfigureUserAppleMail:output_type -> google.protobuf.Empty - 19, // 164: grpc.Bridge.RunEventStream:output_type -> grpc.StreamEvent - 71, // 165: grpc.Bridge.StopEventStream:output_type -> google.protobuf.Empty - 113, // [113:166] is the sub-list for method output_type - 60, // [60:113] is the sub-list for method input_type + 71, // 72: grpc.Bridge.GoOs:input_type -> google.protobuf.Empty + 71, // 73: grpc.Bridge.TriggerReset:input_type -> google.protobuf.Empty + 71, // 74: grpc.Bridge.Version:input_type -> google.protobuf.Empty + 71, // 75: grpc.Bridge.LogsPath:input_type -> google.protobuf.Empty + 71, // 76: grpc.Bridge.LicensePath:input_type -> google.protobuf.Empty + 71, // 77: grpc.Bridge.ReleaseNotesPageLink:input_type -> google.protobuf.Empty + 71, // 78: grpc.Bridge.DependencyLicensesLink:input_type -> google.protobuf.Empty + 71, // 79: grpc.Bridge.LandingPageLink:input_type -> google.protobuf.Empty + 70, // 80: grpc.Bridge.SetColorSchemeName:input_type -> google.protobuf.StringValue + 71, // 81: grpc.Bridge.ColorSchemeName:input_type -> google.protobuf.Empty + 71, // 82: grpc.Bridge.CurrentEmailClient:input_type -> google.protobuf.Empty + 9, // 83: grpc.Bridge.ReportBug:input_type -> grpc.ReportBugRequest + 70, // 84: grpc.Bridge.ExportTLSCertificates:input_type -> google.protobuf.StringValue + 70, // 85: grpc.Bridge.ForceLauncher:input_type -> google.protobuf.StringValue + 70, // 86: grpc.Bridge.SetMainExecutable:input_type -> google.protobuf.StringValue + 10, // 87: grpc.Bridge.Login:input_type -> grpc.LoginRequest + 10, // 88: grpc.Bridge.Login2FA:input_type -> grpc.LoginRequest + 10, // 89: grpc.Bridge.Login2Passwords:input_type -> grpc.LoginRequest + 11, // 90: grpc.Bridge.LoginAbort:input_type -> grpc.LoginAbortRequest + 71, // 91: grpc.Bridge.CheckUpdate:input_type -> google.protobuf.Empty + 71, // 92: grpc.Bridge.InstallUpdate:input_type -> google.protobuf.Empty + 72, // 93: grpc.Bridge.SetIsAutomaticUpdateOn:input_type -> google.protobuf.BoolValue + 71, // 94: grpc.Bridge.IsAutomaticUpdateOn:input_type -> google.protobuf.Empty + 71, // 95: grpc.Bridge.DiskCachePath:input_type -> google.protobuf.Empty + 70, // 96: grpc.Bridge.SetDiskCachePath:input_type -> google.protobuf.StringValue + 72, // 97: grpc.Bridge.SetIsDoHEnabled:input_type -> google.protobuf.BoolValue + 71, // 98: grpc.Bridge.IsDoHEnabled:input_type -> google.protobuf.Empty + 71, // 99: grpc.Bridge.MailServerSettings:input_type -> google.protobuf.Empty + 12, // 100: grpc.Bridge.SetMailServerSettings:input_type -> grpc.ImapSmtpSettings + 71, // 101: grpc.Bridge.Hostname:input_type -> google.protobuf.Empty + 73, // 102: grpc.Bridge.IsPortFree:input_type -> google.protobuf.Int32Value + 71, // 103: grpc.Bridge.AvailableKeychains:input_type -> google.protobuf.Empty + 70, // 104: grpc.Bridge.SetCurrentKeychain:input_type -> google.protobuf.StringValue + 71, // 105: grpc.Bridge.CurrentKeychain:input_type -> google.protobuf.Empty + 71, // 106: grpc.Bridge.GetUserList:input_type -> google.protobuf.Empty + 70, // 107: grpc.Bridge.GetUser:input_type -> google.protobuf.StringValue + 15, // 108: grpc.Bridge.SetUserSplitMode:input_type -> grpc.UserSplitModeRequest + 70, // 109: grpc.Bridge.LogoutUser:input_type -> google.protobuf.StringValue + 70, // 110: grpc.Bridge.RemoveUser:input_type -> google.protobuf.StringValue + 17, // 111: grpc.Bridge.ConfigureUserAppleMail:input_type -> grpc.ConfigureAppleMailRequest + 18, // 112: grpc.Bridge.RunEventStream:input_type -> grpc.EventStreamRequest + 71, // 113: grpc.Bridge.StopEventStream:input_type -> google.protobuf.Empty + 70, // 114: grpc.Bridge.CheckTokens:output_type -> google.protobuf.StringValue + 71, // 115: grpc.Bridge.AddLogEntry:output_type -> google.protobuf.Empty + 8, // 116: grpc.Bridge.GuiReady:output_type -> grpc.GuiReadyResponse + 71, // 117: grpc.Bridge.Quit:output_type -> google.protobuf.Empty + 71, // 118: grpc.Bridge.Restart:output_type -> google.protobuf.Empty + 72, // 119: grpc.Bridge.ShowOnStartup:output_type -> google.protobuf.BoolValue + 71, // 120: grpc.Bridge.SetIsAutostartOn:output_type -> google.protobuf.Empty + 72, // 121: grpc.Bridge.IsAutostartOn:output_type -> google.protobuf.BoolValue + 71, // 122: grpc.Bridge.SetIsBetaEnabled:output_type -> google.protobuf.Empty + 72, // 123: grpc.Bridge.IsBetaEnabled:output_type -> google.protobuf.BoolValue + 71, // 124: grpc.Bridge.SetIsAllMailVisible:output_type -> google.protobuf.Empty + 72, // 125: grpc.Bridge.IsAllMailVisible:output_type -> google.protobuf.BoolValue + 70, // 126: grpc.Bridge.GoOs:output_type -> google.protobuf.StringValue + 71, // 127: grpc.Bridge.TriggerReset:output_type -> google.protobuf.Empty + 70, // 128: grpc.Bridge.Version:output_type -> google.protobuf.StringValue + 70, // 129: grpc.Bridge.LogsPath:output_type -> google.protobuf.StringValue + 70, // 130: grpc.Bridge.LicensePath:output_type -> google.protobuf.StringValue + 70, // 131: grpc.Bridge.ReleaseNotesPageLink:output_type -> google.protobuf.StringValue + 70, // 132: grpc.Bridge.DependencyLicensesLink:output_type -> google.protobuf.StringValue + 70, // 133: grpc.Bridge.LandingPageLink:output_type -> google.protobuf.StringValue + 71, // 134: grpc.Bridge.SetColorSchemeName:output_type -> google.protobuf.Empty + 70, // 135: grpc.Bridge.ColorSchemeName:output_type -> google.protobuf.StringValue + 70, // 136: grpc.Bridge.CurrentEmailClient:output_type -> google.protobuf.StringValue + 71, // 137: grpc.Bridge.ReportBug:output_type -> google.protobuf.Empty + 71, // 138: grpc.Bridge.ExportTLSCertificates:output_type -> google.protobuf.Empty + 71, // 139: grpc.Bridge.ForceLauncher:output_type -> google.protobuf.Empty + 71, // 140: grpc.Bridge.SetMainExecutable:output_type -> google.protobuf.Empty + 71, // 141: grpc.Bridge.Login:output_type -> google.protobuf.Empty + 71, // 142: grpc.Bridge.Login2FA:output_type -> google.protobuf.Empty + 71, // 143: grpc.Bridge.Login2Passwords:output_type -> google.protobuf.Empty + 71, // 144: grpc.Bridge.LoginAbort:output_type -> google.protobuf.Empty + 71, // 145: grpc.Bridge.CheckUpdate:output_type -> google.protobuf.Empty + 71, // 146: grpc.Bridge.InstallUpdate:output_type -> google.protobuf.Empty + 71, // 147: grpc.Bridge.SetIsAutomaticUpdateOn:output_type -> google.protobuf.Empty + 72, // 148: grpc.Bridge.IsAutomaticUpdateOn:output_type -> google.protobuf.BoolValue + 70, // 149: grpc.Bridge.DiskCachePath:output_type -> google.protobuf.StringValue + 71, // 150: grpc.Bridge.SetDiskCachePath:output_type -> google.protobuf.Empty + 71, // 151: grpc.Bridge.SetIsDoHEnabled:output_type -> google.protobuf.Empty + 72, // 152: grpc.Bridge.IsDoHEnabled:output_type -> google.protobuf.BoolValue + 12, // 153: grpc.Bridge.MailServerSettings:output_type -> grpc.ImapSmtpSettings + 71, // 154: grpc.Bridge.SetMailServerSettings:output_type -> google.protobuf.Empty + 70, // 155: grpc.Bridge.Hostname:output_type -> google.protobuf.StringValue + 72, // 156: grpc.Bridge.IsPortFree:output_type -> google.protobuf.BoolValue + 13, // 157: grpc.Bridge.AvailableKeychains:output_type -> grpc.AvailableKeychainsResponse + 71, // 158: grpc.Bridge.SetCurrentKeychain:output_type -> google.protobuf.Empty + 70, // 159: grpc.Bridge.CurrentKeychain:output_type -> google.protobuf.StringValue + 16, // 160: grpc.Bridge.GetUserList:output_type -> grpc.UserListResponse + 14, // 161: grpc.Bridge.GetUser:output_type -> grpc.User + 71, // 162: grpc.Bridge.SetUserSplitMode:output_type -> google.protobuf.Empty + 71, // 163: grpc.Bridge.LogoutUser:output_type -> google.protobuf.Empty + 71, // 164: grpc.Bridge.RemoveUser:output_type -> google.protobuf.Empty + 71, // 165: grpc.Bridge.ConfigureUserAppleMail:output_type -> google.protobuf.Empty + 19, // 166: grpc.Bridge.RunEventStream:output_type -> grpc.StreamEvent + 71, // 167: grpc.Bridge.StopEventStream:output_type -> google.protobuf.Empty + 114, // [114:168] is the sub-list for method output_type + 60, // [60:114] is the sub-list for method input_type 60, // [60:60] is the sub-list for extension type_name 60, // [60:60] is the sub-list for extension extendee 0, // [0:60] is the sub-list for field type_name diff --git a/internal/frontend/grpc/bridge.proto b/internal/frontend/grpc/bridge.proto index b44271ad..328b4ca4 100644 --- a/internal/frontend/grpc/bridge.proto +++ b/internal/frontend/grpc/bridge.proto @@ -42,6 +42,7 @@ service Bridge { rpc IsBetaEnabled(google.protobuf.Empty) returns (google.protobuf.BoolValue); rpc SetIsAllMailVisible(google.protobuf.BoolValue) returns (google.protobuf.Empty); rpc IsAllMailVisible(google.protobuf.Empty) returns (google.protobuf.BoolValue); + rpc GoOs(google.protobuf.Empty) returns (google.protobuf.StringValue); rpc TriggerReset(google.protobuf.Empty) returns (google.protobuf.Empty); rpc Version(google.protobuf.Empty) returns (google.protobuf.StringValue); rpc LogsPath(google.protobuf.Empty) returns (google.protobuf.StringValue); diff --git a/internal/frontend/grpc/bridge_grpc.pb.go b/internal/frontend/grpc/bridge_grpc.pb.go index e2097ff5..84e3c73f 100644 --- a/internal/frontend/grpc/bridge_grpc.pb.go +++ b/internal/frontend/grpc/bridge_grpc.pb.go @@ -37,6 +37,7 @@ type BridgeClient interface { IsBetaEnabled(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) SetIsAllMailVisible(ctx context.Context, in *wrapperspb.BoolValue, opts ...grpc.CallOption) (*emptypb.Empty, error) IsAllMailVisible(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.BoolValue, error) + GoOs(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) TriggerReset(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) Version(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) LogsPath(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) @@ -203,6 +204,15 @@ func (c *bridgeClient) IsAllMailVisible(ctx context.Context, in *emptypb.Empty, return out, nil } +func (c *bridgeClient) GoOs(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*wrapperspb.StringValue, error) { + out := new(wrapperspb.StringValue) + err := c.cc.Invoke(ctx, "/grpc.Bridge/GoOs", in, out, opts...) + if err != nil { + return nil, err + } + return out, nil +} + func (c *bridgeClient) TriggerReset(ctx context.Context, in *emptypb.Empty, opts ...grpc.CallOption) (*emptypb.Empty, error) { out := new(emptypb.Empty) err := c.cc.Invoke(ctx, "/grpc.Bridge/TriggerReset", in, out, opts...) @@ -612,6 +622,7 @@ type BridgeServer interface { IsBetaEnabled(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) SetIsAllMailVisible(context.Context, *wrapperspb.BoolValue) (*emptypb.Empty, error) IsAllMailVisible(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) + GoOs(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) TriggerReset(context.Context, *emptypb.Empty) (*emptypb.Empty, error) Version(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) LogsPath(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) @@ -703,6 +714,9 @@ func (UnimplementedBridgeServer) SetIsAllMailVisible(context.Context, *wrappersp func (UnimplementedBridgeServer) IsAllMailVisible(context.Context, *emptypb.Empty) (*wrapperspb.BoolValue, error) { return nil, status.Errorf(codes.Unimplemented, "method IsAllMailVisible not implemented") } +func (UnimplementedBridgeServer) GoOs(context.Context, *emptypb.Empty) (*wrapperspb.StringValue, error) { + return nil, status.Errorf(codes.Unimplemented, "method GoOs not implemented") +} func (UnimplementedBridgeServer) TriggerReset(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { return nil, status.Errorf(codes.Unimplemented, "method TriggerReset not implemented") } @@ -1055,6 +1069,24 @@ func _Bridge_IsAllMailVisible_Handler(srv interface{}, ctx context.Context, dec return interceptor(ctx, in, info, handler) } +func _Bridge_GoOs_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { + in := new(emptypb.Empty) + if err := dec(in); err != nil { + return nil, err + } + if interceptor == nil { + return srv.(BridgeServer).GoOs(ctx, in) + } + info := &grpc.UnaryServerInfo{ + Server: srv, + FullMethod: "/grpc.Bridge/GoOs", + } + handler := func(ctx context.Context, req interface{}) (interface{}, error) { + return srv.(BridgeServer).GoOs(ctx, req.(*emptypb.Empty)) + } + return interceptor(ctx, in, info, handler) +} + func _Bridge_TriggerReset_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { in := new(emptypb.Empty) if err := dec(in); err != nil { @@ -1851,6 +1883,10 @@ var Bridge_ServiceDesc = grpc.ServiceDesc{ MethodName: "IsAllMailVisible", Handler: _Bridge_IsAllMailVisible_Handler, }, + { + MethodName: "GoOs", + Handler: _Bridge_GoOs_Handler, + }, { MethodName: "TriggerReset", Handler: _Bridge_TriggerReset_Handler, diff --git a/internal/frontend/grpc/service_methods.go b/internal/frontend/grpc/service_methods.go index 874f35c2..4ef13cee 100644 --- a/internal/frontend/grpc/service_methods.go +++ b/internal/frontend/grpc/service_methods.go @@ -211,6 +211,12 @@ func (s *Service) IsAllMailVisible(ctx context.Context, _ *emptypb.Empty) (*wrap return wrapperspb.Bool(s.bridge.GetShowAllMail()), nil } +func (s *Service) GoOs(ctx context.Context, _ *emptypb.Empty) (*wrapperspb.StringValue, error) { + s.log.Debug("GoOs") // TO-DO We can probably get rid of this and use QSysInfo::product name + + return wrapperspb.String(runtime.GOOS), nil +} + func (s *Service) TriggerReset(ctx context.Context, _ *emptypb.Empty) (*emptypb.Empty, error) { s.log.Debug("TriggerReset") diff --git a/pkg/bridgelib/bridgelib.go b/pkg/bridgelib/bridgelib.go deleted file mode 100644 index 351b6db8..00000000 --- a/pkg/bridgelib/bridgelib.go +++ /dev/null @@ -1,116 +0,0 @@ -// Copyright (c) 2023 Proton AG -// -// This file is part of Proton Mail Bridge. -// -// Proton Mail Bridge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Proton Mail Bridge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Proton Mail Bridge. If not, see . - -package main - -// bridgelib export bridge go code as a C library. [More info](https://pkg.go.dev/cmd/go#hdr-Build_modes). -// on Windows bridge-gui is built using the MSVC compiler with cannot link against mingw static library, -// As a consequence, the library should be built as a C shared library (.dll/.so/.dylib depending on the platform): -// -// macOS: go build -buildmode=c-shared -o bridgelib.dylib bridgelib.go -// Linux: go build -buildmode=c-shared -o bridgelib.so bridgelib.go -// Windows: go build -buildmode=c-shared -o bridgelib.dll bridgelib.go -// -// In addition to the library file, the header will export a C header file container the relevant type declarations. -// -// Requirements to export a go library -// -// - The package name must be main, and as a consequence, must contain a main() function. -// - The package must import "C" -// - Functions to be exported must be annotated with the cgo //export comment. -// -// Heap allocated data such as go string needs to be released. On macOS and linux, the caller of the library function can call free/delete, -// but it crashes on Windows because of the VC++/MinGW incompatibility. As a consequence, the caller is responsible for freeing the memory -// using the DeleteCString function. - -//#include -import "C" -import ( - "path/filepath" - "runtime" - "sync" - "unsafe" - - "github.com/ProtonMail/proton-bridge/v3/internal/constants" - "github.com/ProtonMail/proton-bridge/v3/internal/locations" -) - -// main is empty but required. -func main() { -} - -var locs *locations.DefaultProvider //nolint:gochecknoglobals -var locsMutex sync.Mutex //nolint:gochecknoglobals - -// GoOS returns the value of runtime.GOOS. -// -//export GoOS -func GoOS() *C.char { - return C.CString(runtime.GOOS) -} - -// UserCacheDir returns the path of the user's cache directory. -// -//export UserCacheDir -func UserCacheDir() *C.char { - return withLocationProvider(func(loc *locations.DefaultProvider) string { return loc.UserCache() }) -} - -// UserConfigDir returns the path of the user's config directory. -// -//export UserConfigDir -func UserConfigDir() *C.char { - return withLocationProvider(func(loc *locations.DefaultProvider) string { return loc.UserConfig() }) -} - -// UserDataDir returns the path of the user's data directory. -// -//export UserDataDir -func UserDataDir() *C.char { - return withLocationProvider(func(loc *locations.DefaultProvider) string { return loc.UserData() }) -} - -// DeleteCString deletes a C-style string allocated by one of the library calls. -// -//export DeleteCString -func DeleteCString(cStr *C.char) { - if cStr != nil { - C.free(unsafe.Pointer(cStr)) - } -} - -func withLocationProvider(fn func(provider *locations.DefaultProvider) string) *C.char { - locsMutex.Lock() - defer locsMutex.Unlock() - - if locs == nil { - var err error - if locs, err = locations.NewDefaultProvider(filepath.Join(constants.VendorName, constants.ConfigName)); err != nil { - return nil - } - } - - return C.CString(fn(locs)) -} - -// cStringToGoString converts a cString to a GoString and release the memory for the C-String. This function is implemented -// here because cgo code is not allowed in Go test files. -func cStringToGoString(cStr *C.char) string { - str := C.GoString(cStr) - DeleteCString(cStr) // preferred over a direct call to C.free so that the former is covered in tests. - return str -} diff --git a/pkg/bridgelib/bridgelib_test.go b/pkg/bridgelib/bridgelib_test.go deleted file mode 100644 index c233a835..00000000 --- a/pkg/bridgelib/bridgelib_test.go +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2023 Proton AG -// -// This file is part of Proton Mail Bridge. -// -// Proton Mail Bridge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Proton Mail Bridge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Proton Mail Bridge. If not, see . - -package main - -import ( - "path/filepath" - "runtime" - "testing" - - "github.com/ProtonMail/proton-bridge/v3/internal/constants" - "github.com/ProtonMail/proton-bridge/v3/internal/locations" - "github.com/stretchr/testify/require" -) - -func TestBridgelib(t *testing.T) { - locs, err := locations.NewDefaultProvider(filepath.Join(constants.VendorName, constants.ConfigName)) - require.NoError(t, err) - - require.Equal(t, cStringToGoString(GoOS()), runtime.GOOS) - require.Equal(t, cStringToGoString(UserCacheDir()), locs.UserCache()) - require.Equal(t, cStringToGoString(UserConfigDir()), locs.UserConfig()) - require.Equal(t, cStringToGoString(UserDataDir()), locs.UserData()) -} From c15917aba46d3eef84d14c0c6b645cb0b659e1b2 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Fri, 24 Feb 2023 16:02:15 +0100 Subject: [PATCH 081/130] fix(GODT-2404): Handle unexpected EOF When fetching too many attachment bodies at once, the read can fail with io.ErrUnexpectedEOF. In that case, we returun an error so the fetch is retried. --- internal/user/user.go | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/internal/user/user.go b/internal/user/user.go index 359836ff..5a690a36 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -650,6 +650,8 @@ func (user *User) doEventPoll(ctx context.Context) error { UserID: user.ID(), Error: err, }) + + return fmt.Errorf("failed to get event due to JSON issue: %w", err) } // If the error is a server-side issue, return error to retry later. @@ -694,6 +696,18 @@ func (user *User) doEventPoll(ctx context.Context) error { UserID: user.ID(), Error: err, }) + + return fmt.Errorf("failed to handle event due to JSON issue: %w", err) + } + + // If the error is an unexpected EOF, return error to retry later. + if errors.Is(err, io.ErrUnexpectedEOF) { + user.eventCh.Enqueue(events.UncategorizedEventError{ + UserID: user.ID(), + Error: err, + }) + + return fmt.Errorf("failed to handle event due to EOF: %w", err) } // If the error is a server-side issue, return error to retry later. From 810705ba010887ea48b0af14564c3d24af33afb1 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Thu, 23 Feb 2023 16:21:41 +0100 Subject: [PATCH 082/130] fix(GODT-1945): Handle disabled addresses correctly When listing all a user's email addresses (e.g. for apple mail autoconf) we need to exclude disabled addresses. Similarly, we need to remove them from gluon if using split mode. --- internal/bridge/user_event_test.go | 77 +++++++++++++++++++++ internal/bridge/user_events.go | 104 +++++++++++++++++++---------- internal/events/address.go | 24 +++++++ internal/frontend/cli/frontend.go | 23 ++++++- internal/user/events.go | 78 +++++++++++++++++++--- internal/user/user.go | 6 +- 6 files changed, 264 insertions(+), 48 deletions(-) diff --git a/internal/bridge/user_event_test.go b/internal/bridge/user_event_test.go index 87d5cfc2..f38da332 100644 --- a/internal/bridge/user_event_test.go +++ b/internal/bridge/user_event_test.go @@ -534,6 +534,83 @@ func TestBridge_User_SendDraftRemoveDraftFlag(t *testing.T) { }) } +func TestBridge_User_DisableEnableAddress(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + // Create a user. + userID, _, err := s.CreateUser("user", password) + require.NoError(t, err) + + // Create an additional address for the user. + aliasID, err := s.CreateAddress(userID, "alias@"+s.GetDomain(), password) + require.NoError(t, err) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + require.NoError(t, getErr(bridge.LoginFull(ctx, "user", password, nil, nil))) + + // Initially we should list the address. + info, err := bridge.QueryUserInfo("user") + require.NoError(t, err) + require.Contains(t, info.Addresses, "alias@"+s.GetDomain()) + }) + + // Disable the address. + withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { + require.NoError(t, c.DisableAddress(ctx, aliasID)) + }) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + // Eventually we shouldn't list the address. + require.Eventually(t, func() bool { + info, err := bridge.QueryUserInfo("user") + require.NoError(t, err) + + return xslices.Index(info.Addresses, "alias@"+s.GetDomain()) < 0 + }, 5*time.Second, 100*time.Millisecond) + }) + + // Enable the address. + withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { + require.NoError(t, c.EnableAddress(ctx, aliasID)) + }) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + // Eventually we should list the address. + require.Eventually(t, func() bool { + info, err := bridge.QueryUserInfo("user") + require.NoError(t, err) + + return xslices.Index(info.Addresses, "alias@"+s.GetDomain()) >= 0 + }, 5*time.Second, 100*time.Millisecond) + }) + }) +} + +func TestBridge_User_CreateDisabledAddress(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + // Create a user. + userID, _, err := s.CreateUser("user", password) + require.NoError(t, err) + + // Create an additional address for the user. + aliasID, err := s.CreateAddress(userID, "alias@"+s.GetDomain(), password) + require.NoError(t, err) + + // Immediately disable the address. + withClient(ctx, t, s, "user", password, func(ctx context.Context, c *proton.Client) { + require.NoError(t, c.DisableAddress(ctx, aliasID)) + }) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + require.NoError(t, getErr(bridge.LoginFull(ctx, "user", password, nil, nil))) + + // Initially we shouldn't list the address. + info, err := bridge.QueryUserInfo("user") + require.NoError(t, err) + require.NotContains(t, info.Addresses, "alias@"+s.GetDomain()) + }) + }) +} + // userLoginAndSync logs in user and waits until user is fully synced. func userLoginAndSync( ctx context.Context, diff --git a/internal/bridge/user_events.go b/internal/bridge/user_events.go index 4422b27f..6d53f0b7 100644 --- a/internal/bridge/user_events.go +++ b/internal/bridge/user_events.go @@ -37,9 +37,14 @@ func (bridge *Bridge) handleUserEvent(ctx context.Context, user *user.User, even return fmt.Errorf("failed to handle user address created event: %w", err) } - case events.UserAddressUpdated: - if err := bridge.handleUserAddressUpdated(ctx, user, event); err != nil { - return fmt.Errorf("failed to handle user address updated event: %w", err) + case events.UserAddressEnabled: + if err := bridge.handleUserAddressEnabled(ctx, user, event); err != nil { + return fmt.Errorf("failed to handle user address enabled event: %w", err) + } + + case events.UserAddressDisabled: + if err := bridge.handleUserAddressDisabled(ctx, user, event); err != nil { + return fmt.Errorf("failed to handle user address disabled event: %w", err) } case events.UserAddressDeleted: @@ -66,55 +71,84 @@ func (bridge *Bridge) handleUserEvent(ctx context.Context, user *user.User, even } func (bridge *Bridge) handleUserAddressCreated(ctx context.Context, user *user.User, event events.UserAddressCreated) error { - if user.GetAddressMode() == vault.SplitMode { - if bridge.imapServer == nil { - return fmt.Errorf("no imap server instance running") - } + if user.GetAddressMode() != vault.SplitMode { + return nil + } - gluonID, err := bridge.imapServer.AddUser(ctx, user.NewIMAPConnector(event.AddressID), user.GluonKey()) - if err != nil { - return fmt.Errorf("failed to add user to IMAP server: %w", err) - } + if bridge.imapServer == nil { + return fmt.Errorf("no imap server instance running") + } - if err := user.SetGluonID(event.AddressID, gluonID); err != nil { - return fmt.Errorf("failed to set gluon ID: %w", err) - } + gluonID, err := bridge.imapServer.AddUser(ctx, user.NewIMAPConnector(event.AddressID), user.GluonKey()) + if err != nil { + return fmt.Errorf("failed to add user to IMAP server: %w", err) + } + + if err := user.SetGluonID(event.AddressID, gluonID); err != nil { + return fmt.Errorf("failed to set gluon ID: %w", err) } return nil } -// GODT-1948: Handle addresses that have been disabled! -func (bridge *Bridge) handleUserAddressUpdated(_ context.Context, user *user.User, _ events.UserAddressUpdated) error { - switch user.GetAddressMode() { - case vault.CombinedMode: - return fmt.Errorf("not implemented") +func (bridge *Bridge) handleUserAddressEnabled(ctx context.Context, user *user.User, event events.UserAddressEnabled) error { + if user.GetAddressMode() != vault.SplitMode { + return nil + } - case vault.SplitMode: - return fmt.Errorf("not implemented") + gluonID, err := bridge.imapServer.AddUser(ctx, user.NewIMAPConnector(event.AddressID), user.GluonKey()) + if err != nil { + return fmt.Errorf("failed to add user to IMAP server: %w", err) + } + + if err := user.SetGluonID(event.AddressID, gluonID); err != nil { + return fmt.Errorf("failed to set gluon ID: %w", err) + } + + return nil +} + +func (bridge *Bridge) handleUserAddressDisabled(ctx context.Context, user *user.User, event events.UserAddressDisabled) error { + if user.GetAddressMode() != vault.SplitMode { + return nil + } + + gluonID, ok := user.GetGluonID(event.AddressID) + if !ok { + return fmt.Errorf("gluon ID not found for address %s", event.AddressID) + } + + if err := bridge.imapServer.RemoveUser(ctx, gluonID, true); err != nil { + return fmt.Errorf("failed to remove user from IMAP server: %w", err) + } + + if err := user.RemoveGluonID(event.AddressID, gluonID); err != nil { + return fmt.Errorf("failed to remove gluon ID for address: %w", err) } return nil } func (bridge *Bridge) handleUserAddressDeleted(ctx context.Context, user *user.User, event events.UserAddressDeleted) error { - if user.GetAddressMode() == vault.SplitMode { - if bridge.imapServer == nil { - return fmt.Errorf("no imap server instance running") - } + if user.GetAddressMode() != vault.SplitMode { + return nil + } - gluonID, ok := user.GetGluonID(event.AddressID) - if !ok { - return fmt.Errorf("gluon ID not found for address %s", event.AddressID) - } + if bridge.imapServer == nil { + return fmt.Errorf("no imap server instance running") + } - if err := bridge.imapServer.RemoveUser(ctx, gluonID, true); err != nil { - return fmt.Errorf("failed to remove user from IMAP server: %w", err) - } + gluonID, ok := user.GetGluonID(event.AddressID) + if !ok { + return fmt.Errorf("gluon ID not found for address %s", event.AddressID) + } - if err := user.RemoveGluonID(event.AddressID, gluonID); err != nil { - return fmt.Errorf("failed to remove gluon ID for address: %w", err) - } + if err := bridge.imapServer.RemoveUser(ctx, gluonID, true); err != nil { + return fmt.Errorf("failed to remove user from IMAP server: %w", err) + } + + if err := user.RemoveGluonID(event.AddressID, gluonID); err != nil { + return fmt.Errorf("failed to remove gluon ID for address: %w", err) } return nil diff --git a/internal/events/address.go b/internal/events/address.go index 687ea578..96695e26 100644 --- a/internal/events/address.go +++ b/internal/events/address.go @@ -35,6 +35,30 @@ func (event UserAddressCreated) String() string { return fmt.Sprintf("UserAddressCreated: UserID: %s, AddressID: %s, Email: %s", event.UserID, event.AddressID, logging.Sensitive(event.Email)) } +type UserAddressEnabled struct { + eventBase + + UserID string + AddressID string + Email string +} + +func (event UserAddressEnabled) String() string { + return fmt.Sprintf("UserAddressEnabled: UserID: %s, AddressID: %s, Email: %s", event.UserID, event.AddressID, logging.Sensitive(event.Email)) +} + +type UserAddressDisabled struct { + eventBase + + UserID string + AddressID string + Email string +} + +func (event UserAddressDisabled) String() string { + return fmt.Sprintf("UserAddressDisabled: UserID: %s, AddressID: %s, Email: %s", event.UserID, event.AddressID, logging.Sensitive(event.Email)) +} + type UserAddressUpdated struct { eventBase diff --git a/internal/frontend/cli/frontend.go b/internal/frontend/cli/frontend.go index 07719c4f..e06c3a3a 100644 --- a/internal/frontend/cli/frontend.go +++ b/internal/frontend/cli/frontend.go @@ -310,6 +310,14 @@ func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:gocyc case events.IMAPLoginFailed: f.Printf("An IMAP login attempt failed for user %v\n", event.Username) + case events.UserAddressEnabled: + user, err := f.bridge.GetUserInfo(event.UserID) + if err != nil { + return + } + + f.Printf("An address for %s was enabled. You may need to reconfigure your email client.\n", user.Username) + case events.UserAddressUpdated: user, err := f.bridge.GetUserInfo(event.UserID) if err != nil { @@ -318,8 +326,21 @@ func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:gocyc f.Printf("Address changed for %s. You may need to reconfigure your email client.\n", user.Username) + case events.UserAddressDisabled: + user, err := f.bridge.GetUserInfo(event.UserID) + if err != nil { + return + } + + f.Printf("An address for %s was disabled. You may need to reconfigure your email client.\n", user.Username) + case events.UserAddressDeleted: - f.notifyLogout(event.Email) + user, err := f.bridge.GetUserInfo(event.UserID) + if err != nil { + return + } + + f.Printf("An address for %s was disabled. You may need to reconfigure your email client.\n", user.Username) case events.SyncStarted: user, err := f.bridge.GetUserInfo(event.UserID) diff --git a/internal/user/events.go b/internal/user/events.go index b80180b2..25854222 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -205,6 +205,12 @@ func (user *User) handleCreateAddressEvent(ctx context.Context, event proton.Add user.apiAddrs[event.Address.ID] = event.Address + // If the address is disabled. + if event.Address.Status != proton.AddressStatusEnabled { + return nil + } + + // If the address is enabled, we need to hook it up to the update channels. switch user.vault.AddressMode() { case vault.CombinedMode: primAddr, err := getAddrIdx(user.apiAddrs, 0) @@ -231,6 +237,10 @@ func (user *User) handleCreateAddressEvent(ctx context.Context, event proton.Add // Perform the sync in an RLock. return safe.RLockRet(func() error { + if event.Address.Status != proton.AddressStatusEnabled { + return nil + } + if user.vault.AddressMode() == vault.SplitMode { if err := syncLabels(ctx, user.apiLabels, user.updateCh[event.Address.ID]); err != nil { return fmt.Errorf("failed to sync labels to new address: %w", err) @@ -248,18 +258,58 @@ func (user *User) handleUpdateAddressEvent(_ context.Context, event proton.Addre "email": logging.Sensitive(event.Address.Email), }).Info("Handling address updated event") - if _, ok := user.apiAddrs[event.Address.ID]; !ok { + oldAddr, ok := user.apiAddrs[event.Address.ID] + if !ok { user.log.Debugf("Address %q does not exist", event.Address.ID) return nil } user.apiAddrs[event.Address.ID] = event.Address - user.eventCh.Enqueue(events.UserAddressUpdated{ - UserID: user.apiUser.ID, - AddressID: event.Address.ID, - Email: event.Address.Email, - }) + switch { + // If the address was newly enabled: + case oldAddr.Status != proton.AddressStatusEnabled && event.Address.Status == proton.AddressStatusEnabled: + switch user.vault.AddressMode() { + case vault.CombinedMode: + primAddr, err := getAddrIdx(user.apiAddrs, 0) + if err != nil { + return fmt.Errorf("failed to get primary address: %w", err) + } + + user.updateCh[event.Address.ID] = user.updateCh[primAddr.ID] + + case vault.SplitMode: + user.updateCh[event.Address.ID] = queue.NewQueuedChannel[imap.Update](0, 0) + } + + user.eventCh.Enqueue(events.UserAddressEnabled{ + UserID: user.apiUser.ID, + AddressID: event.Address.ID, + Email: event.Address.Email, + }) + + // If the address was newly disabled: + case oldAddr.Status == proton.AddressStatusEnabled && event.Address.Status != proton.AddressStatusEnabled: + if user.vault.AddressMode() == vault.SplitMode { + user.updateCh[event.ID].CloseAndDiscardQueued() + } + + delete(user.updateCh, event.ID) + + user.eventCh.Enqueue(events.UserAddressDisabled{ + UserID: user.apiUser.ID, + AddressID: event.Address.ID, + Email: event.Address.Email, + }) + + // Otherwise it's just an update: + default: + user.eventCh.Enqueue(events.UserAddressUpdated{ + UserID: user.apiUser.ID, + AddressID: event.Address.ID, + Email: event.Address.Email, + }) + } return nil }, user.apiAddrsLock) @@ -275,12 +325,20 @@ func (user *User) handleDeleteAddressEvent(_ context.Context, event proton.Addre return nil } - if user.vault.AddressMode() == vault.SplitMode { - user.updateCh[event.ID].CloseAndDiscardQueued() - delete(user.updateCh, event.ID) + delete(user.apiAddrs, event.ID) + + // If the address was disabled to begin with, we don't need to do anything. + if addr.Status != proton.AddressStatusEnabled { + return nil } - delete(user.apiAddrs, event.ID) + // Otherwise, in split mode, drop the update queue. + if user.vault.AddressMode() == vault.SplitMode { + user.updateCh[event.ID].CloseAndDiscardQueued() + } + + // And in either mode, remove the address from the update channel map. + delete(user.updateCh, event.ID) user.eventCh.Enqueue(events.UserAddressDeleted{ UserID: user.apiUser.ID, diff --git a/internal/user/user.go b/internal/user/user.go index 5a690a36..e3e31539 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -264,11 +264,13 @@ func (user *User) Match(query string) bool { }, user.apiUserLock, user.apiAddrsLock) } -// Emails returns all the user's email addresses. +// Emails returns all the user's active email addresses. // It returns them in sorted order; the user's primary address is first. func (user *User) Emails() []string { return safe.RLockRet(func() []string { - addresses := maps.Values(user.apiAddrs) + addresses := xslices.Filter(maps.Values(user.apiAddrs), func(addr proton.Address) bool { + return addr.Status == proton.AddressStatusEnabled + }) slices.SortFunc(addresses, func(a, b proton.Address) bool { return a.Order < b.Order From 761c16d8cd49b7857c3568a1280f8995ff6e6f37 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Mon, 27 Feb 2023 13:00:32 +0100 Subject: [PATCH 083/130] fix(GODT-2412): Don't treat context cancellation as BadEvent --- internal/bridge/user_events.go | 19 +++-------------- internal/errors.go | 31 ++++++++++++++++++++++++++++ internal/user/user.go | 37 +++++++--------------------------- 3 files changed, 41 insertions(+), 46 deletions(-) create mode 100644 internal/errors.go diff --git a/internal/bridge/user_events.go b/internal/bridge/user_events.go index 6d53f0b7..47215021 100644 --- a/internal/bridge/user_events.go +++ b/internal/bridge/user_events.go @@ -19,10 +19,10 @@ package bridge import ( "context" - "errors" "fmt" "github.com/ProtonMail/gluon/reporter" + "github.com/ProtonMail/proton-bridge/v3/internal" "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/safe" "github.com/ProtonMail/proton-bridge/v3/internal/user" @@ -177,7 +177,7 @@ func (bridge *Bridge) handleUserDeauth(ctx context.Context, user *user.User) { func (bridge *Bridge) handleUserBadEvent(ctx context.Context, user *user.User, err error) { safe.Lock(func() { if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle event", reporter.Context{ - "error_type": fmt.Sprintf("%T", getUnwrappedError(err)), + "error_type": fmt.Sprintf("%T", internal.ErrCause(err)), "error": err, }); rerr != nil { logrus.WithError(rerr).Error("Failed to report failed event handling") @@ -189,22 +189,9 @@ func (bridge *Bridge) handleUserBadEvent(ctx context.Context, user *user.User, e func (bridge *Bridge) handleUncategorizedErrorEvent(event events.UncategorizedEventError) { if rerr := bridge.reporter.ReportMessageWithContext("Failed to handle due to uncategorized error", reporter.Context{ - "error_type": fmt.Sprintf("%T", getUnwrappedError(event.Error)), + "error_type": fmt.Sprintf("%T", internal.ErrCause(event.Error)), "error": event.Error, }); rerr != nil { logrus.WithError(rerr).Error("Failed to report failed event handling") } } - -func getUnwrappedError(err error) error { - for { - unwrapped := errors.Unwrap(err) - if unwrapped == nil { - break - } - - err = unwrapped - } - - return err -} diff --git a/internal/errors.go b/internal/errors.go new file mode 100644 index 00000000..f8e839a6 --- /dev/null +++ b/internal/errors.go @@ -0,0 +1,31 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + +package internal + +import "errors" + +// ErrCause returns the cause of the error, the inner-most error in the wrapped chain. +func ErrCause(err error) error { + cause := err + + for errors.Unwrap(cause) != nil { + cause = errors.Unwrap(cause) + } + + return cause +} diff --git a/internal/user/user.go b/internal/user/user.go index e3e31539..64d0fdd0 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -34,6 +34,7 @@ import ( "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/go-proton-api" + "github.com/ProtonMail/proton-bridge/v3/internal" "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/logging" @@ -632,36 +633,7 @@ func (user *User) doEventPoll(ctx context.Context) error { event, err := user.client.GetEvent(ctx, user.vault.EventID()) if err != nil { - if netErr := new(proton.NetError); errors.As(err, &netErr) { - return fmt.Errorf("failed to get event due to network issue: %w", err) - } - - // Catch all for uncategorized net errors that may slip through. - if netErr := new(net.OpError); errors.As(err, &netErr) { - user.eventCh.Enqueue(events.UncategorizedEventError{ - UserID: user.ID(), - Error: err, - }) - - return fmt.Errorf("failed to get event due to network issues (uncategorized): %w", err) - } - - // In case a json decode error slips through. - if jsonErr := new(json.UnmarshalTypeError); errors.As(err, &jsonErr) { - user.eventCh.Enqueue(events.UncategorizedEventError{ - UserID: user.ID(), - Error: err, - }) - - return fmt.Errorf("failed to get event due to JSON issue: %w", err) - } - - // If the error is a server-side issue, return error to retry later. - if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status >= 500 { - return fmt.Errorf("failed to get event due to server error: %w", err) - } - - return fmt.Errorf("failed to get event: %w", err) + return fmt.Errorf("failed to get event (caused by %T): %w", internal.ErrCause(err), err) } // If the event ID hasn't changed, there are no new events. @@ -677,6 +649,11 @@ func (user *User) doEventPoll(ctx context.Context) error { // Handle the event. if err := user.handleAPIEvent(ctx, event); err != nil { + // If the error is a context cancellation, return error to retry later. + if errors.Is(err, context.Canceled) { + return fmt.Errorf("failed to handle event due to context cancellation: %w", err) + } + // If the error is a network error, return error to retry later. if netErr := new(proton.NetError); errors.As(err, &netErr) { return fmt.Errorf("failed to handle event due to network issue: %w", err) From a2b9fc3deec89ec6a6b5248e1615f162b0ddb1fc Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Wed, 15 Feb 2023 08:33:40 +0100 Subject: [PATCH 084/130] feat(GODT-2273): menu with "Close window" and "Quit Bridge" button in main window. --- .../bridge-gui/qml/ContentWrapper.qml | 53 ++++++++++++++++++- .../bridge-gui/bridge-gui/qml/MainWindow.qml | 11 ++++ .../bridge-gui/qml/NotificationPopups.qml | 5 ++ .../qml/Notifications/Notifications.qml | 51 +++++++++++++++++- .../bridge-gui/qml/Proton/MenuItem.qml | 5 +- 5 files changed, 119 insertions(+), 6 deletions(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/ContentWrapper.qml b/internal/frontend/bridge-gui/bridge-gui/qml/ContentWrapper.qml index 93b2e8f7..6dc46d79 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/ContentWrapper.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/ContentWrapper.qml @@ -29,6 +29,8 @@ Item { property var notifications signal showSetupGuide(var user, string address) + signal closeWindow() + signal quitBridge() RowLayout { anchors.fill: parent @@ -107,7 +109,7 @@ Item { Layout.topMargin: 16 Layout.bottomMargin: 9 - Layout.rightMargin: 16 + Layout.rightMargin: 4 horizontalPadding: 0 @@ -115,6 +117,55 @@ Item { onClicked: rightContent.showGeneralSettings() } + + Button { + id: dotMenuButton + Layout.bottomMargin: 9 + Layout.maximumHeight: 36 + Layout.maximumWidth: 36 + Layout.minimumHeight: 36 + Layout.minimumWidth: 36 + Layout.preferredHeight: 36 + Layout.preferredWidth: 36 + Layout.rightMargin: 16 + Layout.topMargin: 16 + colorScheme: leftBar.colorScheme + horizontalPadding: 0 + icon.source: "/qml/icons/ic-three-dots-vertical.svg" + + onClicked: { + dotMenu.open() + } + + Menu { + id: dotMenu + colorScheme: root.colorScheme + modal: true + y: dotMenuButton.Layout.preferredHeight + dotMenuButton.Layout.bottomMargin + + MenuItem { + colorScheme: root.colorScheme + text: qsTr("Close window") + onClicked: { + root.closeWindow() + } + } + MenuItem { + colorScheme: root.colorScheme + text: qsTr("Quit Bridge") + onClicked: { + root.quitBridge() + } + } + + onClosed: { + parent.checked = false + } + onOpened: { + parent.checked = true + } + } + } } Item {implicitHeight:10} diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/MainWindow.qml b/internal/frontend/bridge-gui/bridge-gui/qml/MainWindow.qml index 2abb52b4..491206ad 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/MainWindow.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/MainWindow.qml @@ -142,6 +142,17 @@ ApplicationWindow { onShowSetupGuide: function(user, address) { root.showSetup(user,address) } + + onCloseWindow: { + root.close() + } + + onQuitBridge: { + // If we ever want to add a confirmation dialog before quitting: + //root.notifications.askQuestion("Quit Bridge", "Insert warning message here.", "Quit", "Cancel", Backend.quit, null) + root.close() + Backend.quit() + } } WelcomeGuide { // 1 diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/NotificationPopups.qml b/internal/frontend/bridge-gui/bridge-gui/qml/NotificationPopups.qml index 5c65ddad..bf6d45bb 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/NotificationPopups.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/NotificationPopups.qml @@ -138,4 +138,9 @@ Item { colorScheme: root.colorScheme notification: root.notifications.genericError } + + NotificationDialog { + colorScheme: root.colorScheme + notification: root.notifications.genericQuestion + } } diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml b/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml index c4d250cc..2564f336 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/Notifications/Notifications.qml @@ -32,7 +32,7 @@ QtObject { signal askResetBridge() signal askChangeAllMailVisibility(var isVisibleNow) signal askDeleteAccount(var user) - + signal askQuestion(var title, var description, var option1, var option2, var action1, var action2) enum Group { Connection = 1, Update = 2, @@ -82,7 +82,8 @@ QtObject { root.noActiveKeyForRecipient, root.userBadEvent, root.imapLoginWhileSignedOut, - root.genericError + root.genericError, + root.genericQuestion, ] // Connection @@ -1201,4 +1202,50 @@ QtObject { } ] } + + property Notification genericQuestion: Notification { + title: "" + brief: "" + description: "" + type: Notification.NotificationType.Warning + group: Notifications.Group.Dialogs + property var option1: "" + property var option2: "" + property variant action1: null + property variant action2: null + + Connections { + target: root + function onAskQuestion(title, description, option1, option2, action1, action2) { + root.genericQuestion.title = title + root.genericQuestion.description = description + root.genericQuestion.option1 = option1 + root.genericQuestion.option2 = option2 + root.genericQuestion.action1 = action1 + root.genericQuestion.action2 = action2 + root.genericQuestion.active = true + } + } + + action: [ + Action { + text: root.genericQuestion.option1 + + onTriggered: { + root.genericQuestion.active = false + if (root.genericQuestion.action1) + root.genericQuestion.action1() + } + }, + Action { + text: root.genericQuestion.option2 + + onTriggered: { + root.genericQuestion.active = false + if (root.genericQuestion.action2) + root.genericQuestion.action2() + } + } + ] + } } diff --git a/internal/frontend/bridge-gui/bridge-gui/qml/Proton/MenuItem.qml b/internal/frontend/bridge-gui/bridge-gui/qml/Proton/MenuItem.qml index 7a6c6c1a..7c30d353 100644 --- a/internal/frontend/bridge-gui/bridge-gui/qml/Proton/MenuItem.qml +++ b/internal/frontend/bridge-gui/bridge-gui/qml/Proton/MenuItem.qml @@ -26,13 +26,12 @@ T.MenuItem { property ColorScheme colorScheme - implicitWidth: Math.max(implicitBackgroundWidth + leftInset + rightInset, - implicitContentWidth + leftPadding + rightPadding) + width: parent.width // required. Other item overflows to the right of the menu and get clipped. implicitHeight: Math.max(implicitBackgroundHeight + topInset + bottomInset, implicitContentHeight + topPadding + bottomPadding, implicitIndicatorHeight + topPadding + bottomPadding) - padding: 6 + padding: 12 spacing: 6 icon.width: 24 From 2b09796d1c2df0bab46e7394a0d5e360c58b4a23 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Mon, 27 Feb 2023 15:06:16 +0100 Subject: [PATCH 085/130] fix(GODT-2399): Fix immediate message deletion during updates Fix was applied in Gluon. --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index c4fea1c1..b0b1b5cc 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.1.1 - github.com/ProtonMail/gluon v0.15.1-0.20230223111926-1b870f5c0988 + github.com/ProtonMail/gluon v0.15.1-0.20230227132318-45c83ff156d7 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 81a138cf..b920d42f 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.15.1-0.20230223111926-1b870f5c0988 h1:HU5F+tpx6pdZ7f52oIfjmxfoR4bNkkQ+oG2frMPWHl4= -github.com/ProtonMail/gluon v0.15.1-0.20230223111926-1b870f5c0988/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230227132318-45c83ff156d7 h1:4FL3ttMChrjXqmRHYaSMJZJeZZj/Xao4Mm5QnhTUSc4= +github.com/ProtonMail/gluon v0.15.1-0.20230227132318-45c83ff156d7/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= From 4a6460f3ed8f4425762899c6fea324c3eaf12a40 Mon Sep 17 00:00:00 2001 From: Mark Conway Date: Sat, 25 Feb 2023 12:36:11 -0600 Subject: [PATCH 086/130] feat(GODT-2411): allow qmake executable to be named qmake6. And a free a typo fix. (cherry picked from commit 4153a6925321e89e3ace7d747109484c1d28162e) --- internal/frontend/bridge-gui/FindQt.cmake | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/internal/frontend/bridge-gui/FindQt.cmake b/internal/frontend/bridge-gui/FindQt.cmake index ab7f8a1a..351d7b7b 100644 --- a/internal/frontend/bridge-gui/FindQt.cmake +++ b/internal/frontend/bridge-gui/FindQt.cmake @@ -1,8 +1,8 @@ -find_program(QMAKE_EXE "qmake") +find_program(QMAKE_EXE NAMES "qmake" "qmake6") if (NOT QMAKE_EXE) - message(FATAL_ERROR "Could not locate qmake executable, make sur you have Qt 6 installed in that qmake is in your PATH environment variable.") + message(FATAL_ERROR "Could not locate qmake executable, make sure you have Qt 6 installed in that qmake is in your PATH environment variable.") endif() message(STATUS "Found qmake at ${QMAKE_EXE}") execute_process(COMMAND "${QMAKE_EXE}" -query QT_INSTALL_PREFIX OUTPUT_VARIABLE QT_DIR OUTPUT_STRIP_TRAILING_WHITESPACE) -set(CMAKE_PREFIX_PATH ${QT_DIR} ${CMAKE_PREFIX_PATH}) \ No newline at end of file +set(CMAKE_PREFIX_PATH ${QT_DIR} ${CMAKE_PREFIX_PATH}) From d7bfee2414094fa2b70d1ae877040039acaaa78f Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Tue, 28 Feb 2023 11:30:03 +0100 Subject: [PATCH 087/130] feat(GODT-2382): Added bridge-gui settings file with 'UseSoftwareRenderer' value. --- .../bridge-gui/bridge-gui/AppController.cpp | 37 +++++++++--- .../bridge-gui/bridge-gui/AppController.h | 19 +++---- .../bridge-gui/bridge-gui/CMakeLists.txt | 1 + .../bridge-gui/bridge-gui/Settings.cpp | 56 +++++++++++++++++++ .../frontend/bridge-gui/bridge-gui/Settings.h | 47 ++++++++++++++++ .../frontend/bridge-gui/bridge-gui/main.cpp | 6 +- 6 files changed, 145 insertions(+), 21 deletions(-) create mode 100644 internal/frontend/bridge-gui/bridge-gui/Settings.cpp create mode 100644 internal/frontend/bridge-gui/bridge-gui/Settings.h diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp index 4152d7d9..e0df2a5a 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp @@ -19,6 +19,7 @@ #include "AppController.h" #include "QMLBackend.h" #include "SentryUtils.h" +#include "Settings.h" #include #include #include @@ -32,6 +33,7 @@ namespace { QString const noWindowFlag = "--no-window"; ///< The no-window command-line flag. } + //**************************************************************************************************************************************************** /// \return The AppController instance. //**************************************************************************************************************************************************** @@ -47,10 +49,19 @@ AppController &app() { AppController::AppController() : backend_(std::make_unique()) , grpc_(std::make_unique()) - , log_(std::make_unique()) { + , log_(std::make_unique()) + , settings_(new Settings) { } + +//**************************************************************************************************************************************************** +// The following is in the implementation file because of unique pointers with incomplete types in headers. +// See https://stackoverflow.com/questions/6012157/is-stdunique-ptrt-required-to-know-the-full-definition-of-t +//**************************************************************************************************************************************************** +AppController::~AppController() = default; + + //**************************************************************************************************************************************************** /// \return The bridge worker, which can be null if the application was run in 'attach' mode (-a command-line switch). //**************************************************************************************************************************************************** @@ -70,15 +81,24 @@ ProcessMonitor *AppController::bridgeMonitor() const { } +//**************************************************************************************************************************************************** +/// \return A reference to the application settings. +//**************************************************************************************************************************************************** +Settings &AppController::settings() { + return *settings_; +} + + //**************************************************************************************************************************************************** /// \param[in] function The function that caught the exception. /// \param[in] message The error message. /// \param[in] details The details for the error. //**************************************************************************************************************************************************** -void AppController::onFatalError(QString const &function, QString const &message, QString const& details) { +void AppController::onFatalError(QString const &function, QString const &message, QString const &details) { QString fullMessage = QString("%1(): %2").arg(function, message); - if (!details.isEmpty()) + if (!details.isEmpty()) { fullMessage += "\n\nDetails:\n" + details; + } sentry_uuid_s const uuid = reportSentryException(SENTRY_LEVEL_ERROR, "AppController got notified of a fatal error", "Exception", fullMessage.toLocal8Bit()); QMessageBox::critical(nullptr, tr("Error"), message); @@ -87,20 +107,23 @@ void AppController::onFatalError(QString const &function, QString const &message qApp->exit(EXIT_FAILURE); } + void AppController::restart(bool isCrashing) { if (!launcher_.isEmpty()) { QProcess p; - log_->info(QString("Restarting - App : %1 - Args : %2").arg(launcher_,launcherArgs_.join(" "))); + log_->info(QString("Restarting - App : %1 - Args : %2").arg(launcher_, launcherArgs_.join(" "))); QStringList args = launcherArgs_; - if (isCrashing) + if (isCrashing) { args.append(noWindowFlag); + } p.startDetached(launcher_, args); p.waitForStarted(); } } -void AppController::setLauncherArgs(const QString& launcher, const QStringList& args){ + +void AppController::setLauncherArgs(const QString &launcher, const QStringList &args) { launcher_ = launcher; launcherArgs_ = args; -} \ No newline at end of file +} diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.h b/internal/frontend/bridge-gui/bridge-gui/AppController.h index cba3bebd..f8955dd5 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.h +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.h @@ -20,21 +20,16 @@ #define BRIDGE_GUI_APP_CONTROLLER_H +//@formatter:off class QMLBackend; - - +class Settings; namespace bridgepp { class Log; - - class Overseer; - - class GRPCClient; - - class ProcessMonitor; } +//@formatter:on //**************************************************************************************************************************************************** @@ -47,7 +42,7 @@ Q_OBJECT public: // member functions. AppController(AppController const &) = delete; ///< Disabled copy-constructor. AppController(AppController &&) = delete; ///< Disabled assignment copy-constructor. - ~AppController() override = default; ///< Destructor. + ~AppController() override; ///< Destructor. AppController &operator=(AppController const &) = delete; ///< Disabled assignment operator. AppController &operator=(AppController &&) = delete; ///< Disabled move assignment operator. QMLBackend &backend() { return *backend_; } ///< Return a reference to the backend. @@ -55,10 +50,11 @@ public: // member functions. bridgepp::Log &log() { return *log_; } ///< Return a reference to the log. std::unique_ptr &bridgeOverseer() { return bridgeOverseer_; }; ///< Returns a reference the bridge overseer bridgepp::ProcessMonitor *bridgeMonitor() const; ///< Return the bridge worker. - void setLauncherArgs(const QString& launcher, const QStringList& args); + Settings &settings();; ///< Return the application settings. + void setLauncherArgs(const QString &launcher, const QStringList &args); public slots: - void onFatalError(QString const &function, QString const &message, QString const& details); ///< Handle fatal errors. + void onFatalError(QString const &function, QString const &message, QString const &details); ///< Handle fatal errors. private: // member functions AppController(); ///< Default constructor. @@ -69,6 +65,7 @@ private: // data members std::unique_ptr grpc_; ///< The RPC client. std::unique_ptr log_; ///< The log. std::unique_ptr bridgeOverseer_; ///< The overseer for the bridge monitor worker. + std::unique_ptr settings_; ///< The application settings. QString launcher_; QStringList launcherArgs_; }; diff --git a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt index 58591bdf..e491356f 100644 --- a/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridge-gui/CMakeLists.txt @@ -118,6 +118,7 @@ add_executable(bridge-gui QMLBackend.cpp QMLBackend.h UserList.cpp UserList.h SentryUtils.cpp SentryUtils.h + Settings.cpp Settings.h ${DOCK_ICON_SRC_FILE} MacOS/DockIcon.h ) diff --git a/internal/frontend/bridge-gui/bridge-gui/Settings.cpp b/internal/frontend/bridge-gui/bridge-gui/Settings.cpp new file mode 100644 index 00000000..e7acb259 --- /dev/null +++ b/internal/frontend/bridge-gui/bridge-gui/Settings.cpp @@ -0,0 +1,56 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + + +#include "Settings.h" +#include + + +using namespace bridgepp; + + +namespace { + + +QString const settingsFileName = "bridge-gui.ini"; ///< The name of the settings file. +QString const keyUseSoftwareRenderer = "UseSoftwareRenderer"; ///< The key for storing the 'Use software rendering' setting. + + +} + +//**************************************************************************************************************************************************** +// +//**************************************************************************************************************************************************** +Settings::Settings() + : settings_(QDir(userConfigDir()).absoluteFilePath("bridge-gui.ini"), QSettings::Format::IniFormat) { +} + + +//**************************************************************************************************************************************************** +/// \return The value for the 'Use software renderer' setting. +//**************************************************************************************************************************************************** +bool Settings::useSoftwareRenderer() const { + return settings_.value(keyUseSoftwareRenderer, false).toBool(); +} + + +//**************************************************************************************************************************************************** +/// \param[in] value The value for the 'Use software renderer' setting. +//**************************************************************************************************************************************************** +void Settings::setUseSoftwareRenderer(bool value) { + settings_.setValue(keyUseSoftwareRenderer, value); +} diff --git a/internal/frontend/bridge-gui/bridge-gui/Settings.h b/internal/frontend/bridge-gui/bridge-gui/Settings.h new file mode 100644 index 00000000..977fc6ba --- /dev/null +++ b/internal/frontend/bridge-gui/bridge-gui/Settings.h @@ -0,0 +1,47 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + + +#ifndef BRIDGE_GUI_SETTINGS_H +#define BRIDGE_GUI_SETTINGS_H + + +//**************************************************************************************************************************************************** +/// \brief Application settings class +//**************************************************************************************************************************************************** +class Settings { +public: // member functions. + Settings(Settings const&) = delete; ///< Disabled copy-constructor. + Settings(Settings&&) = delete; ///< Disabled assignment copy-constructor. + ~Settings() = default; ///< Destructor. + Settings& operator=(Settings const&) = delete; ///< Disabled assignment operator. + Settings& operator=(Settings&&) = delete; ///< Disabled move assignment operator. + + bool useSoftwareRenderer() const; ///< Get the 'Use software renderer' settings value. + void setUseSoftwareRenderer(bool value); ///< Set the 'Use software renderer' settings value. + +private: // member functions. + Settings(); ///< Default constructor. + +private: // data members. + QSettings settings_; ///< The settings. + + friend class AppController; +}; + + +#endif //BRIDGE_GUI_SETTINGS_H diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 03cd64d1..35d0e14e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -16,13 +16,13 @@ // along with Proton Mail Bridge. If not, see . -#include "Pch.h" #include "BridgeApp.h" +#include "BuildConfig.h" #include "CommandLine.h" #include "LogUtils.h" #include "QMLBackend.h" #include "SentryUtils.h" -#include "BuildConfig.h" +#include "Settings.h" #include #include #include @@ -334,7 +334,7 @@ int main(int argc, char *argv[]) { // The following allows to render QML content in software with a 'Rendering Hardware Interface' (OpenGL, Vulkan, Metal, Direct3D...) // Note that it is different from the Qt::AA_UseSoftwareOpenGL attribute we use on some platforms that instruct Qt that we would like // to use a software-only implementation of OpenGL. - QQuickWindow::setSceneGraphBackend(cliOptions.useSoftwareRenderer ? "software" : "rhi"); + QQuickWindow::setSceneGraphBackend((app().settings().useSoftwareRenderer() || cliOptions.useSoftwareRenderer) ? "software" : "rhi"); log.info(QString("Qt Quick renderer: %1").arg(QQuickWindow::sceneGraphBackend())); QQmlApplicationEngine engine; From d6acb0fb19c652247676e4cc994959d5ddb8ab45 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Tue, 28 Feb 2023 12:17:23 +0100 Subject: [PATCH 088/130] fix(GODT-2418): Ensure child folders are updated when parent is --- COPYING_NOTES.md | 6 +- go.mod | 46 +++++----- go.sum | 135 +++++++++++++++-------------- internal/bridge/user_event_test.go | 75 ++++++++++++++++ internal/user/events.go | 60 +++++++++---- thing | 1 + 6 files changed, 218 insertions(+), 105 deletions(-) create mode 100644 thing diff --git a/COPYING_NOTES.md b/COPYING_NOTES.md index ede8163c..171fa8fd 100644 --- a/COPYING_NOTES.md +++ b/COPYING_NOTES.md @@ -79,6 +79,8 @@ Proton Mail Bridge includes the following 3rd party software: * [cascadia](https://github.com/andybalholm/cascadia) available under [license](https://github.com/andybalholm/cascadia/blob/master/LICENSE) * [antlr](https://github.com/antlr/antlr4/runtime/Go/antlr) available under [license](https://github.com/antlr/antlr4/runtime/Go/antlr/blob/master/LICENSE) * [go-textseg](https://github.com/apparentlymart/go-textseg/v13) available under [license](https://github.com/apparentlymart/go-textseg/v13/blob/master/LICENSE) +* [sonic](https://github.com/bytedance/sonic) available under [license](https://github.com/bytedance/sonic/blob/master/LICENSE) +* [base64x](https://github.com/chenzhuoyu/base64x) available under [license](https://github.com/chenzhuoyu/base64x/blob/master/LICENSE) * [test](https://github.com/chzyer/test) available under [license](https://github.com/chzyer/test/blob/master/LICENSE) * [circl](https://github.com/cloudflare/circl) available under [license](https://github.com/cloudflare/circl/blob/master/LICENSE) * [go-md2man](https://github.com/cpuguy83/go-md2man/v2) available under [license](https://github.com/cpuguy83/go-md2man/v2/blob/master/LICENSE) @@ -107,6 +109,7 @@ Proton Mail Bridge includes the following 3rd party software: * [hcl](https://github.com/hashicorp/hcl/v2) available under [license](https://github.com/hashicorp/hcl/v2/blob/master/LICENSE) * [multierror](https://github.com/joeshaw/multierror) available under [license](https://github.com/joeshaw/multierror/blob/master/LICENSE) * [go](https://github.com/json-iterator/go) available under [license](https://github.com/json-iterator/go/blob/master/LICENSE) +* [cpuid](https://github.com/klauspost/cpuid/v2) available under [license](https://github.com/klauspost/cpuid/v2/blob/master/LICENSE) * [go-urn](https://github.com/leodido/go-urn) available under [license](https://github.com/leodido/go-urn/blob/master/LICENSE) * [go-colorable](https://github.com/mattn/go-colorable) available under [license](https://github.com/mattn/go-colorable/blob/master/LICENSE) * [go-isatty](https://github.com/mattn/go-isatty) available under [license](https://github.com/mattn/go-isatty/blob/master/LICENSE) @@ -124,16 +127,17 @@ Proton Mail Bridge includes the following 3rd party software: * [blackfriday](https://github.com/russross/blackfriday/v2) available under [license](https://github.com/russross/blackfriday/v2/blob/master/LICENSE) * [pflag](https://github.com/spf13/pflag) available under [license](https://github.com/spf13/pflag/blob/master/LICENSE) * [bom](https://github.com/ssor/bom) available under [license](https://github.com/ssor/bom/blob/master/LICENSE) +* [golang-asm](https://github.com/twitchyliquid64/golang-asm) available under [license](https://github.com/twitchyliquid64/golang-asm/blob/master/LICENSE) * [codec](https://github.com/ugorji/go/codec) available under [license](https://github.com/ugorji/go/codec/blob/master/LICENSE) * [tagparser](https://github.com/vmihailenco/tagparser/v2) available under [license](https://github.com/vmihailenco/tagparser/v2/blob/master/LICENSE) * [smetrics](https://github.com/xrash/smetrics) available under [license](https://github.com/xrash/smetrics/blob/master/LICENSE) * [go-cty](https://github.com/zclconf/go-cty) available under [license](https://github.com/zclconf/go-cty/blob/master/LICENSE) +* [arch](https://golang.org/x/arch) available under [license](https://cs.opensource.google/go/x/arch/+/master:LICENSE) * [crypto](https://golang.org/x/crypto) available under [license](https://cs.opensource.google/go/x/crypto/+/master:LICENSE) * [mod](https://golang.org/x/mod) available under [license](https://cs.opensource.google/go/x/mod/+/master:LICENSE) * [sync](https://golang.org/x/sync) available under [license](https://cs.opensource.google/go/x/sync/+/master:LICENSE) * [tools](https://golang.org/x/tools) available under [license](https://cs.opensource.google/go/x/tools/+/master:LICENSE) * [genproto](https://google.golang.org/genproto) -gopkg.in/yaml.v2 gopkg.in/yaml.v3 * [docker-credential-helpers](https://github.com/ProtonMail/docker-credential-helpers) available under [license](https://github.com/ProtonMail/docker-credential-helpers/blob/master/LICENSE) * [go-message](https://github.com/ProtonMail/go-message) available under [license](https://github.com/ProtonMail/go-message/blob/master/LICENSE) diff --git a/go.mod b/go.mod index b0b1b5cc..127e6ca5 100644 --- a/go.mod +++ b/go.mod @@ -4,13 +4,13 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 - github.com/Masterminds/semver/v3 v3.1.1 + github.com/Masterminds/semver/v3 v3.2.0 github.com/ProtonMail/gluon v0.15.1-0.20230227132318-45c83ff156d7 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 + github.com/ProtonMail/go-proton-api v0.4.1-0.20230228124441-781ee183e1b4 github.com/ProtonMail/go-rfc5322 v0.11.0 - github.com/ProtonMail/gopenpgp/v2 v2.4.10 - github.com/PuerkitoBio/goquery v1.8.0 + github.com/ProtonMail/gopenpgp/v2 v2.5.2 + github.com/PuerkitoBio/goquery v1.8.1 github.com/abiosoft/ishell v2.0.0+incompatible github.com/allan-simon/go-singleinstance v0.0.0-20210120080615-d0997106ab37 github.com/bradenaw/juniper v0.10.2 @@ -26,7 +26,7 @@ require ( github.com/fatih/color v1.13.0 github.com/getsentry/sentry-go v0.15.0 github.com/go-resty/resty/v2 v2.7.0 - github.com/goccy/go-json v0.9.11 + github.com/goccy/go-json v0.10.0 github.com/godbus/dbus v4.1.0+incompatible github.com/golang/mock v1.6.0 github.com/google/go-cmp v0.5.9 @@ -40,14 +40,14 @@ require ( github.com/pkg/profile v1.7.0 github.com/sirupsen/logrus v1.9.0 github.com/stretchr/testify v1.8.1 - github.com/urfave/cli/v2 v2.20.3 + github.com/urfave/cli/v2 v2.24.4 github.com/vmihailenco/msgpack/v5 v5.3.5 go.uber.org/goleak v1.2.1 golang.org/x/exp v0.0.0-20230213192124-5e25df0256eb - golang.org/x/net v0.2.0 + golang.org/x/net v0.7.0 golang.org/x/sys v0.5.0 golang.org/x/text v0.7.0 - google.golang.org/grpc v1.50.1 + google.golang.org/grpc v1.53.0 google.golang.org/protobuf v1.28.1 howett.net/plist v1.0.0 ) @@ -56,16 +56,18 @@ require ( ariga.io/atlas v0.9.1-0.20230119145809-92243f7c55cb // indirect entgo.io/ent v0.11.8 // indirect github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf // indirect - github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895 // indirect - github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f // indirect + github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect + github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 // indirect github.com/ProtonMail/go-srp v0.0.5 // indirect github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect + github.com/bytedance/sonic v1.8.1 // indirect + github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/chzyer/test v1.0.0 // indirect - github.com/cloudflare/circl v1.2.0 // indirect + github.com/cloudflare/circl v1.3.2 // indirect github.com/cpuguy83/go-md2man/v2 v2.0.2 // indirect github.com/cronokirby/saferith v0.33.0 // indirect github.com/cucumber/gherkin-go/v19 v19.0.3 // indirect @@ -77,11 +79,11 @@ require ( github.com/felixge/fgprof v0.9.3 // indirect github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 // indirect github.com/gin-contrib/sse v0.1.0 // indirect - github.com/gin-gonic/gin v1.8.1 // indirect + github.com/gin-gonic/gin v1.9.0 // indirect github.com/go-openapi/inflect v0.19.0 // indirect - github.com/go-playground/locales v0.14.0 // indirect - github.com/go-playground/universal-translator v0.18.0 // indirect - github.com/go-playground/validator/v10 v10.11.1 // indirect + github.com/go-playground/locales v0.14.1 // indirect + github.com/go-playground/universal-translator v0.18.1 // indirect + github.com/go-playground/validator/v10 v10.11.2 // indirect github.com/gofrs/uuid v4.3.0+incompatible // indirect github.com/golang/protobuf v1.5.2 // indirect github.com/google/pprof v0.0.0-20211214055906-6f57359322fd // indirect @@ -92,16 +94,17 @@ require ( github.com/hashicorp/hcl/v2 v2.16.1 // indirect github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/leodido/go-urn v1.2.1 // indirect github.com/mattn/go-colorable v0.1.13 // indirect - github.com/mattn/go-isatty v0.0.16 // indirect + github.com/mattn/go-isatty v0.0.17 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-sqlite3 v1.14.16 // indirect github.com/mitchellh/go-wordwrap v1.0.1 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/olekukonko/tablewriter v0.0.5 // indirect - github.com/pelletier/go-toml/v2 v2.0.5 // indirect + github.com/pelletier/go-toml/v2 v2.0.6 // indirect github.com/pierrec/lz4/v4 v4.1.17 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/procfs v0.8.0 // indirect @@ -109,16 +112,17 @@ require ( github.com/russross/blackfriday/v2 v2.1.0 // indirect github.com/spf13/pflag v1.0.5 // indirect github.com/ssor/bom v0.0.0-20170718123548-6386211fdfcf // indirect - github.com/ugorji/go/codec v1.2.7 // indirect + github.com/twitchyliquid64/golang-asm v0.15.1 // indirect + github.com/ugorji/go/codec v1.2.10 // indirect github.com/vmihailenco/tagparser/v2 v2.0.0 // indirect github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 // indirect github.com/zclconf/go-cty v1.12.1 // indirect - golang.org/x/crypto v0.1.0 // indirect + golang.org/x/arch v0.2.0 // indirect + golang.org/x/crypto v0.6.0 // indirect golang.org/x/mod v0.8.0 // indirect golang.org/x/sync v0.1.0 // indirect golang.org/x/tools v0.3.1-0.20221202221704-aa9f4b2f3d57 // indirect - google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + google.golang.org/genproto v0.0.0-20230221151758-ace64dc21148 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index b920d42f..56944a7e 100644 --- a/go.sum +++ b/go.sum @@ -20,8 +20,8 @@ github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557/go.mod h1:sTrmvD/ github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/DATA-DOG/go-sqlmock v1.5.0 h1:Shsta01QNfFxHCfpW6YH2STWB0MudeXXEWMr20OEh60= -github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= -github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Masterminds/semver/v3 v3.2.0 h1:3MEsd0SM6jqZojhjLWWeBY+Kcjy9i6MQAeY7YgDP83g= +github.com/Masterminds/semver/v3 v3.2.0/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/ProtonMail/bcrypt v0.0.0-20210511135022-227b4adcab57/go.mod h1:HecWFHognK8GfRDGnFQbW/LiV7A3MX3gZVs45vk5h8I= github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs69zUkSzubzjBbL+cmOXgnmt9Fyd9ug= @@ -33,24 +33,23 @@ github.com/ProtonMail/gluon v0.15.1-0.20230227132318-45c83ff156d7/go.mod h1:yA4h github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= -github.com/ProtonMail/go-crypto v0.0.0-20220822140716-1678d6eb0cbe/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8= -github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895 h1:NsReiLpErIPzRrnogAXYwSoU7txA977LjDGrbkewJbg= -github.com/ProtonMail/go-crypto v0.0.0-20220824120805-4b6e5c587895/go.mod h1:UBYPn8k0D56RtnR8RFQMjmh4KrZzWJ5o7Z9SYjossQ8= +github.com/ProtonMail/go-crypto v0.0.0-20230124153114-0acdc8ae009b/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 h1:I8IsYA297x0QLU80G5I6aLYUu3JYNSpo8j5fkXtFDW0= github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= -github.com/ProtonMail/go-mime v0.0.0-20220302105931-303f85f7fe0f/go.mod h1:NYt+V3/4rEeDuaev/zw1zCq8uqVEuPHzDPo3OZrlGJ4= -github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f h1:4IWzKjHzZxdrW9k4zl/qCwenOVHDbVDADPPHFLjs0Oc= -github.com/ProtonMail/go-mime v0.0.0-20220429130430-2192574d760f/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497 h1:R78tKuV4FnTILa/yCx8+9lvKMl3ZA6gduM10inz7pSc= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230217130533-0af5d2f08497/go.mod h1:JUo5IQG0hNuPRuDpOUsCOvtee6UjTEHHF1QN2i8RSos= +github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 h1:dS7r5z4iGS0qCjM7UwWdsEMzQesUQbGcXdSm2/tWboA= +github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230228124441-781ee183e1b4 h1:isPTVpbcwhLB36fcpI9/YzLUi2rapuLsJiHP8GCB5EY= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230228124441-781ee183e1b4/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs= -github.com/ProtonMail/gopenpgp/v2 v2.4.10 h1:EYgkxzwmQvsa6kxxkgP1AwzkFqKHscF2UINxaSn6rdI= -github.com/ProtonMail/gopenpgp/v2 v2.4.10/go.mod h1:CTRA7/toc/4DxDy5Du4hPDnIZnJvXSeQ8LsRTOUJoyc= -github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0gta/U= -github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= +github.com/ProtonMail/gopenpgp/v2 v2.5.2 h1:97SjlWNAxXl9P22lgwgrZRshQdiEfAht0g3ZoiA1GCw= +github.com/ProtonMail/gopenpgp/v2 v2.5.2/go.mod h1:52qDaCnto6r+CoWbuU50T77XQt99lIs46HtHtvgFO3o= +github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= +github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= github.com/abiosoft/ishell v2.0.0+incompatible h1:zpwIuEHc37EzrsIYah3cpevrIc8Oma7oZPxr03tlmmw= github.com/abiosoft/ishell v2.0.0+incompatible/go.mod h1:HQR9AqF2R3P4XXpMpI0NAzgHf/aS6+zVXRj14cVk9qg= github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db h1:CjPUSXOiYptLbTdr1RceuZgSFDQ7U15ITERUGrUORx8= @@ -78,8 +77,13 @@ github.com/bketelsen/crypt v0.0.3-0.20200106085610-5cbc8cc4026c/go.mod h1:MKsuJm github.com/bradenaw/juniper v0.10.2 h1:EY7r8SJJrigJ7lvWk6ews3K5RD4XTG9z+WSwHJKijP4= github.com/bradenaw/juniper v0.10.2/go.mod h1:Z2B7aJlQ7xbfWsnMLROj5t/5FQ94/MkIdKC30J4WvzI= github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= -github.com/bwesterb/go-ristretto v1.2.1/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= +github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= +github.com/bytedance/sonic v1.8.1 h1:NqAHCaGaTzro0xMmnTCLUyRlbEP6r8MCA1cJUrH3Pu4= +github.com/bytedance/sonic v1.8.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= +github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams= +github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI= github.com/chzyer/logex v1.2.1 h1:XHDu3E6q+gdHgsdTPH6ImJMIp436vR6MPtH8gP05QzM= github.com/chzyer/logex v1.2.1/go.mod h1:JLbx6lG2kDbNRFnfkgvh4eRJRPX1QCoOIWomwysCBrQ= @@ -89,8 +93,8 @@ github.com/chzyer/test v1.0.0 h1:p3BQDXSxOhOG0P9z6/hGnII4LGiEPOYBhs8asl/fC04= github.com/chzyer/test v1.0.0/go.mod h1:2JlltgoNkt4TW/z9V/IzDdFaMTM2JPIi26O1pF38GC8= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= -github.com/cloudflare/circl v1.2.0 h1:NheeISPSUcYftKlfrLuOo4T62FkmD4t4jviLfFFYaec= -github.com/cloudflare/circl v1.2.0/go.mod h1:Ch2UgYr6ti2KTtlejELlROl0YIYj7SLjAC8M+INXlMk= +github.com/cloudflare/circl v1.3.2 h1:VWp8dY3yH69fdM7lM6A1+NhhVoDu9vqK0jOgmkQHFWk= +github.com/cloudflare/circl v1.3.2/go.mod h1:+CauBF6R70Jqcyl8N2hC8pAXYbWkGIezuSbuGLtRhnw= github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk= github.com/coreos/etcd v3.3.13+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= @@ -99,7 +103,6 @@ github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfc github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.2 h1:p1EgwI/C7NhT0JmVkwCD2ZBK8j4aeHQX2pMHHBfMQ6w= github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= -github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/cronokirby/saferith v0.33.0 h1:TgoQlfsD4LIwx71+ChfRcIpjkw+RPOapDEVxa+LhwLo= github.com/cronokirby/saferith v0.33.0/go.mod h1:QKJhjoqUtBsXCAVEjw38mFqoi7DebT7kthcD7UzbnoA= github.com/cucumber/gherkin-go/v19 v19.0.3 h1:mMSKu1077ffLbTJULUfM5HPokgeBcIGboyeNUof1MdE= @@ -149,8 +152,8 @@ github.com/getsentry/sentry-go v0.15.0/go.mod h1:RZPJKSw+adu8PBNygiri/A98FqVr2Ht github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.8.1 h1:4+fr/el88TOO3ewCmQr8cx/CtZ/umlIRIs5M4NTNjf8= -github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk= +github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= +github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= github.com/go-errors/errors v1.4.2 h1:J6MZopCL4uSllY1OfXM374weqZFFItUbrImctkmUxIA= github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -158,20 +161,19 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9 github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4= github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4= -github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= -github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= -github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU= -github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs= -github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho= -github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA= -github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ= -github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= +github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= +github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA= +github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= +github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= +github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= +github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU= +github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68= -github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk= -github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= +github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/godbus/dbus v4.1.0+incompatible h1:WqqLRTsQic3apZUK9qC5sGNfXthmPXzUZ7nQPrNITa4= github.com/godbus/dbus v4.1.0+incompatible/go.mod h1:/YcGZj5zSblfDWMMoOzV4fas9FZnQYTkDnsGvmh2Grw= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= @@ -269,16 +271,17 @@ github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfV github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= +github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= -github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= -github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4= github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= @@ -290,8 +293,9 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= +github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= @@ -325,12 +329,11 @@ github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FI github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58 h1:onHthvaw9LFnH4t2DcNVpwGmV9E1BkGknEliJkfwQj0= github.com/pbnjay/memory v0.0.0-20210728143218-7b4eea64cf58/go.mod h1:DXv8WO4yhMYhSNPKjeNKa5WY9YCIEBRbNzFFPJbWO6Y= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= -github.com/pelletier/go-toml/v2 v2.0.5 h1:ipoSadvV8oGUjnUbMub59IDPPwfxF694nG/jwbMiyQg= -github.com/pelletier/go-toml/v2 v2.0.5/go.mod h1:OMHamSCAODeSsVrwwvcJOaoN0LIUIaFVNZzmWyNfXas= +github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= +github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pingcap/errors v0.11.4 h1:lFuQV/oaUMGcD2tqt+01ROSmJs75VG1ToEOkZIZ4nE4= -github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= @@ -356,9 +359,7 @@ github.com/rivo/uniseg v0.4.2 h1:YwD0ulJSJytLpiaWua0sBDusfsCZohxjxzVTYjwxfV8= github.com/rivo/uniseg v0.4.2/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= -github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= -github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -367,7 +368,6 @@ github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg github.com/sergi/go-diff v1.0.0 h1:Kpca3qRNrduNnOQeazBd0ysaKrUJiIuISHxogkT9RPQ= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= -github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0= github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= @@ -393,7 +393,6 @@ github.com/stretchr/objx v0.5.0 h1:1zr/of2m5FGMsad5YfcqgdqdWrIhu+EBEJRhR1U7z/c= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= 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.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= @@ -403,11 +402,12 @@ github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKs github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= -github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= -github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0= -github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= -github.com/urfave/cli/v2 v2.20.3 h1:lOgGidH/N5loaigd9HjFsOIhXSTrzl7tBpHswZ428w4= -github.com/urfave/cli/v2 v2.20.3/go.mod h1:1CNUng3PtjQMtRzJO4FMXBQvkGtuYRxxiR9xMa7jMwI= +github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= +github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= +github.com/ugorji/go/codec v1.2.10 h1:eimT6Lsr+2lzmSZxPhLFoOWFmQqwk0fllJJ5hEbTXtQ= +github.com/ugorji/go/codec v1.2.10/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/urfave/cli/v2 v2.24.4 h1:0gyJJEBYtCV87zI/x2nZCPyDxD51K6xM8SkwjHFCNEU= +github.com/urfave/cli/v2 v2.24.4/go.mod h1:GHupkWPMM0M/sj1a2b4wUrWBPzazNrIjouW6fmdJLxc= github.com/vmihailenco/msgpack/v5 v5.3.5 h1:5gO0H1iULLWGhs2H5tbAHIZTV8/cYafcFOr9znI5mJU= github.com/vmihailenco/msgpack/v5 v5.3.5/go.mod h1:7xyJ9e+0+9SaZT0Wt1RGleJXzli6Q/V5KbhBonMG9jc= github.com/vmihailenco/tagparser/v2 v2.0.0 h1:y09buUbR+b5aycVFQs/g70pqKVZNBmxwAhO7/IwNM9g= @@ -416,6 +416,7 @@ github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673 h1:bAn7/zixMGCfxrRTfdpNzjtPYqr8smhKouy9mxVdGPU= github.com/xrash/smetrics v0.0.0-20201216005158-039620a65673/go.mod h1:N3UwUGtsrSj3ccvlPHLoLsHnpR27oXr4ZE984MbSER8= github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k= +github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/zclconf/go-cty v1.12.1 h1:PcupnljUm9EIvbgSHQnHhUr3fO6oFmkOrvs2BAFNXXY= github.com/zclconf/go-cty v1.12.1/go.mod h1:s9IfD1LK5ccNMSWCVFCE2rJfHiZgi7JijgeWIMfhLvA= go.etcd.io/bbolt v1.3.2/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= @@ -426,6 +427,9 @@ go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A= go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.2.0 h1:W1sUEHXiJTfjaFJ5SLo0N6lZn+0eO5gWD1MFeTGqQEY= +golang.org/x/arch v0.2.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= @@ -434,10 +438,8 @@ golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.1.0 h1:MDRAIl0xIo9Io2xV565hzXHw3zVseKrJKodhohM5CjU= -golang.org/x/crypto v0.1.0/go.mod h1:RecgLatLF4+eUMCP1PoPZQb+cVrJcOPbHkTkbkB9sbw= +golang.org/x/crypto v0.6.0 h1:qfktjS5LUO+fFKeJXZ+ikTRijMmljikvG68fpMMruSc= +golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -457,12 +459,11 @@ golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHl golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE= golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o= -golang.org/x/mobile v0.0.0-20200801112145-973feb4309de/go.mod h1:skQtrUTUwhdJvXM/2KKJzY8pDgNr9I/FOMqDVRPBUS4= +golang.org/x/mobile v0.0.0-20221110043201-43a038452099/go.mod h1:aAjjkJNdrh3PMckS4B10TGS2nag27cbKR1y2BpUxsiY= golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= 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.1.1-0.20191209134235-331c550502dd/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0 h1:LUYupSeNrTNCGzR/hVBk2NHZO4hXcVaW1k4Qx7rjPx8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= @@ -484,9 +485,9 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.2.0 h1:sZfSu1wtKLGlWI4ZZayP0ck9Y73K1ynO6gqzTdBVdPU= -golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= +golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= +golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g= +golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -496,6 +497,8 @@ golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJ golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -507,7 +510,6 @@ golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -521,15 +523,18 @@ golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210819135213-f52c844e1c1c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -559,9 +564,9 @@ golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtn golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= -golang.org/x/tools v0.0.0-20200117012304-6edc0a871e69/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= +golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.3.1-0.20221202221704-aa9f4b2f3d57 h1:/X0t/E4VxbZE7MLS7auvE7YICHeVvbIa9vkOVvYW/24= golang.org/x/tools v0.3.1-0.20221202221704-aa9f4b2f3d57/go.mod h1:/rWhSS2+zyEVwoJf8YAX6L2f0ntZ7Kn/mGgAWcipA5k= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= @@ -586,13 +591,13 @@ google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8= google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc= -google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737 h1:K1zaaMdYBXRyX+cwFnxj7M6zwDyumLQMZ5xqwGvjreQ= -google.golang.org/genproto v0.0.0-20220921223823-23cae91e6737/go.mod h1:2r/26NEF3bFmT3eC3aZreahSal0C3Shl8Gi6vyDYqOQ= +google.golang.org/genproto v0.0.0-20230221151758-ace64dc21148 h1:muK+gVBJBfFb4SejshDBlN2/UgxCCOKH9Y34ljqEGOc= +google.golang.org/genproto v0.0.0-20230221151758-ace64dc21148/go.mod h1:3Dl5ZL0q0isWJt+FVcfpQyirqemEuLAK/iFvg1UP1Hw= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= -google.golang.org/grpc v1.50.1 h1:DS/BukOZWp8s6p4Dt/tOaJaTQyPyOoCcrjroHuCeLzY= -google.golang.org/grpc v1.50.1/go.mod h1:ZgQEeidpAuNRZ8iRrlBKXZQP1ghovWIVhdJRyCDK+GI= +google.golang.org/grpc v1.53.0 h1:LAv2ds7cmFV/XTS3XG1NneeENYrXGmorPxsBbptIjNc= +google.golang.org/grpc v1.53.0/go.mod h1:OnIrk0ipVdj4N5d9IUoFUx72/VlD7+jUsHwZgwSMQpw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w= @@ -611,11 +616,8 @@ gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= @@ -625,3 +627,4 @@ honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt howett.net/plist v1.0.0 h1:7CrbWYbPPO/PyNy38b2EB/+gYbjCe2DXBxgtOOZbSQM= howett.net/plist v1.0.0/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8= +rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= diff --git a/internal/bridge/user_event_test.go b/internal/bridge/user_event_test.go index f38da332..1282ea69 100644 --- a/internal/bridge/user_event_test.go +++ b/internal/bridge/user_event_test.go @@ -611,6 +611,81 @@ func TestBridge_User_CreateDisabledAddress(t *testing.T) { }) } +func TestBridge_User_HandleParentLabelRename(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, mocks *bridge.Mocks) { + require.NoError(t, getErr(bridge.LoginFull(ctx, username, password, nil, nil))) + + info, err := bridge.QueryUserInfo(username) + require.NoError(t, err) + + client, err := client.Dial(fmt.Sprintf("%v:%v", constants.Host, bridge.GetIMAPPort())) + require.NoError(t, err) + require.NoError(t, client.Login(info.Addresses[0], string(info.BridgePass))) + defer func() { _ = client.Logout() }() + + withClient(ctx, t, s, username, password, func(ctx context.Context, c *proton.Client) { + parentName := uuid.NewString() + childName := uuid.NewString() + + // Create a folder. + parentLabel, err := c.CreateLabel(ctx, proton.CreateLabelReq{ + Name: parentName, + Type: proton.LabelTypeFolder, + Color: "#f66", + }) + require.NoError(t, err) + + // Wait for the parent folder to be created. + require.Eventually(t, func() bool { + return xslices.IndexFunc(clientList(client), func(mailbox *imap.MailboxInfo) bool { + return mailbox.Name == fmt.Sprintf("Folders/%v", parentName) + }) >= 0 + }, 100*user.EventPeriod, user.EventPeriod) + + // Create a subfolder. + childLabel, err := c.CreateLabel(ctx, proton.CreateLabelReq{ + Name: childName, + Type: proton.LabelTypeFolder, + Color: "#f66", + ParentID: parentLabel.ID, + }) + require.NoError(t, err) + require.Equal(t, parentLabel.ID, childLabel.ParentID) + + // Wait for the parent folder to be created. + require.Eventually(t, func() bool { + return xslices.IndexFunc(clientList(client), func(mailbox *imap.MailboxInfo) bool { + return mailbox.Name == fmt.Sprintf("Folders/%v/%v", parentName, childName) + }) >= 0 + }, 100*user.EventPeriod, user.EventPeriod) + + newParentName := uuid.NewString() + + // Rename the parent folder. + require.NoError(t, getErr(c.UpdateLabel(ctx, parentLabel.ID, proton.UpdateLabelReq{ + Color: "#f66", + Name: newParentName, + }))) + + // Wait for the parent folder to be renamed. + require.Eventually(t, func() bool { + return xslices.IndexFunc(clientList(client), func(mailbox *imap.MailboxInfo) bool { + return mailbox.Name == fmt.Sprintf("Folders/%v", newParentName) + }) >= 0 + }, 100*user.EventPeriod, user.EventPeriod) + + // Wait for the child folder to be renamed. + require.Eventually(t, func() bool { + return xslices.IndexFunc(clientList(client), func(mailbox *imap.MailboxInfo) bool { + return mailbox.Name == fmt.Sprintf("Folders/%v/%v", newParentName, childName) + }) >= 0 + }, 100*user.EventPeriod, user.EventPeriod) + }) + }) + }) +} + // userLoginAndSync logs in user and waits until user is fully synced. func userLoginAndSync( ctx context.Context, diff --git a/internal/user/events.go b/internal/user/events.go index 25854222..b6a9349d 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -425,25 +425,51 @@ func (user *User) handleUpdateLabelEvent(ctx context.Context, event proton.Label "name": logging.Sensitive(event.Label.Name), }).Info("Handling label updated event") - // Only update the label if it exists; we don't want to create it as a client may have just deleted it. - if _, ok := user.apiLabels[event.Label.ID]; ok { - user.apiLabels[event.Label.ID] = event.Label - } + stack := []proton.Label{event.Label} - for _, updateCh := range xslices.Unique(maps.Values(user.updateCh)) { - update := imap.NewMailboxUpdated( - imap.MailboxID(event.ID), - getMailboxName(event.Label), - ) - updateCh.Enqueue(update) - updates = append(updates, update) - } + for len(stack) > 0 { + label := stack[0] + stack = stack[1:] - user.eventCh.Enqueue(events.UserLabelUpdated{ - UserID: user.apiUser.ID, - LabelID: event.Label.ID, - Name: event.Label.Name, - }) + // Only update the label if it exists; we don't want to create it as a client may have just deleted it. + if _, ok := user.apiLabels[label.ID]; ok { + user.apiLabels[label.ID] = event.Label + } + + // API doesn't notify us that the path has changed. We need to fetch it again. + apiLabel, err := user.client.GetLabel(ctx, label.ID, label.Type) + if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status == http.StatusUnprocessableEntity { + user.log.WithError(apiErr).Warn("Failed to get label: label does not exist") + continue + } else if err != nil { + return nil, fmt.Errorf("failed to get label %q: %w", label.ID, err) + } + + // Update the label in the map. + user.apiLabels[apiLabel.ID] = apiLabel + + // Notify the IMAP clients. + for _, updateCh := range xslices.Unique(maps.Values(user.updateCh)) { + update := imap.NewMailboxUpdated( + imap.MailboxID(apiLabel.ID), + getMailboxName(apiLabel), + ) + updateCh.Enqueue(update) + updates = append(updates, update) + } + + user.eventCh.Enqueue(events.UserLabelUpdated{ + UserID: user.apiUser.ID, + LabelID: apiLabel.ID, + Name: apiLabel.Name, + }) + + children := xslices.Filter(maps.Values(user.apiLabels), func(other proton.Label) bool { + return other.ParentID == label.ID + }) + + stack = append(stack, children...) + } return updates, nil }, user.apiLabelsLock, user.updateChLock) diff --git a/thing b/thing new file mode 100644 index 00000000..8713bc57 --- /dev/null +++ b/thing @@ -0,0 +1 @@ +{"Code":1001,"Responses":[{"LinkID":"hz-Ozxfk3KMyrISzrtKrZg-Vj7Q2iJcXqyONMryqaVyJZcg90RfEeV-1jFKFIXEmPniBsSAPgHoJQfLyTgpc0A==","Response":{"Code":1000}},{"LinkID":"T8mgwjkPPWbpmlkVJdHJIIAcgb3YR8ZW-OnAi8kWaKh6wubRnC8-S5zBxIktELywVxECmssJ9E-wPRj06zPWmg==","Response":{"Code":1000}}]} From 89117bbd59e02225f0c7289dcca49966208044e7 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Mon, 27 Feb 2023 15:40:57 +0100 Subject: [PATCH 089/130] fix(GODT-2413): use qEnvironmentVariable() instead of qgetenv(). (cherry picked from commit 10cf153678095fa0999ee76483da1160cc597525) --- .../bridgepp/bridgepp/BridgeUtils.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp index 195c8ffe..78f2265e 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/BridgeUtils.cpp @@ -71,20 +71,20 @@ std::mt19937_64 &rng() { QString userConfigDir() { QString dir; #ifdef Q_OS_WIN - dir = qgetenv ("AppData"); + dir = qEnvironmentVariable("AppData"); if (dir.isEmpty()) throw Exception("%AppData% is not defined."); #elif defined(Q_OS_IOS) || defined(Q_OS_DARWIN) - dir = qgetenv("HOME"); + dir = qEnvironmentVariable("HOME"); if (dir.isEmpty()) { throw Exception("$HOME is not defined."); } dir += "/Library/Application Support"; #else - dir = qgetenv ("XDG_CONFIG_HOME"); + dir = qEnvironmentVariable("XDG_CONFIG_HOME"); if (dir.isEmpty()) { - dir = qgetenv ("HOME"); + dir = qEnvironmentVariable("HOME"); if (dir.isEmpty()) throw Exception("neither $XDG_CONFIG_HOME nor $HOME are defined"); dir += "/.config"; @@ -104,20 +104,20 @@ QString userCacheDir() { QString dir; #ifdef Q_OS_WIN - dir = qgetenv ("LocalAppData"); + dir = qEnvironmentVariable("LocalAppData"); if (dir.isEmpty()) throw Exception("%LocalAppData% is not defined."); #elif defined(Q_OS_IOS) || defined(Q_OS_DARWIN) - dir = qgetenv("HOME"); + dir = qEnvironmentVariable("HOME"); if (dir.isEmpty()) { throw Exception("$HOME is not defined."); } dir += "/Library/Caches"; #else - dir = qgetenv ("XDG_CACHE_HOME"); + dir = qEnvironmentVariable("XDG_CACHE_HOME"); if (dir.isEmpty()) { - dir = qgetenv ("HOME"); + dir = qEnvironmentVariable("HOME"); if (dir.isEmpty()) throw Exception("neither $XDG_CACHE_HOME nor $HOME are defined"); dir += "/.cache"; @@ -138,10 +138,10 @@ QString userDataDir() { QString folder; #ifdef Q_OS_LINUX - QString dir = qgetenv ("XDG_DATA_HOME"); + QString dir = qEnvironmentVariable("XDG_DATA_HOME"); if (dir.isEmpty()) { - dir = qgetenv ("HOME"); + dir = qEnvironmentVariable("HOME"); if (dir.isEmpty()) throw Exception("neither $XDG_DATA_HOME nor $HOME are defined"); dir += "/.local/share"; From ee4a8939d5abb575ec00a3dccf604e3eca9dd5f9 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Tue, 28 Feb 2023 16:54:57 +0100 Subject: [PATCH 090/130] fix(GODT-2419): Use connector.ErrOperationNotAllowed Return this error when we detect operations that we know are not allowed so that gluon does not report them to sentry. Includes Gluon update for the connector error (https://github.com/ProtonMail/gluon/pull/309) --- go.mod | 2 +- go.sum | 4 ++-- internal/user/imap.go | 24 ++++++++++++------------ 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index 127e6ca5..f5ccc6ad 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.2.0 - github.com/ProtonMail/gluon v0.15.1-0.20230227132318-45c83ff156d7 + github.com/ProtonMail/gluon v0.15.1-0.20230301094306-3b1b90f01c0e github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230228124441-781ee183e1b4 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 56944a7e..9e9fe34c 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.15.1-0.20230227132318-45c83ff156d7 h1:4FL3ttMChrjXqmRHYaSMJZJeZZj/Xao4Mm5QnhTUSc4= -github.com/ProtonMail/gluon v0.15.1-0.20230227132318-45c83ff156d7/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230301094306-3b1b90f01c0e h1:uzpSucUnQsHs5zNTsCR3rYFU82PgqUyHR+UcyZ4nRvY= +github.com/ProtonMail/gluon v0.15.1-0.20230301094306-3b1b90f01c0e/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/internal/user/imap.go b/internal/user/imap.go index ff1ffcda..fb5cdaa3 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -92,7 +92,7 @@ func (conn *imapConnector) CreateMailbox(ctx context.Context, name []string) (im defer conn.goPollAPIEvents(false) if len(name) < 2 { - return imap.Mailbox{}, fmt.Errorf("invalid mailbox name %q", name) + return imap.Mailbox{}, fmt.Errorf("invalid mailbox name %q: %w", name, connector.ErrOperationNotAllowed) } switch name[0] { @@ -103,13 +103,13 @@ func (conn *imapConnector) CreateMailbox(ctx context.Context, name []string) (im return conn.createLabel(ctx, name[1:]) default: - return imap.Mailbox{}, fmt.Errorf("invalid mailbox name %q", name) + return imap.Mailbox{}, fmt.Errorf("invalid mailbox name %q: %w", name, connector.ErrOperationNotAllowed) } } func (conn *imapConnector) createLabel(ctx context.Context, name []string) (imap.Mailbox, error) { if len(name) != 1 { - return imap.Mailbox{}, fmt.Errorf("a label cannot have children") + return imap.Mailbox{}, fmt.Errorf("a label cannot have children: %w", connector.ErrOperationNotAllowed) } return safe.LockRetErr(func() (imap.Mailbox, error) { @@ -144,7 +144,7 @@ func (conn *imapConnector) createFolder(ctx context.Context, name []string) (ima } if parentID == "" { - return imap.Mailbox{}, fmt.Errorf("parent folder %q does not exist", name[:len(name)-1]) + return imap.Mailbox{}, fmt.Errorf("parent folder %q does not exist: %w", name[:len(name)-1], connector.ErrOperationNotAllowed) } } @@ -171,7 +171,7 @@ func (conn *imapConnector) UpdateMailboxName(ctx context.Context, labelID imap.M defer conn.goPollAPIEvents(false) if len(name) < 2 { - return fmt.Errorf("invalid mailbox name %q", name) + return fmt.Errorf("invalid mailbox name %q: %w", name, connector.ErrOperationNotAllowed) } switch name[0] { @@ -182,14 +182,14 @@ func (conn *imapConnector) UpdateMailboxName(ctx context.Context, labelID imap.M return conn.updateLabel(ctx, labelID, name[1:]) default: - return fmt.Errorf("invalid mailbox name %q", name) + return fmt.Errorf("invalid mailbox name %q: %w", name, connector.ErrOperationNotAllowed) } }, conn.apiLabelsLock) } func (conn *imapConnector) updateLabel(ctx context.Context, labelID imap.MailboxID, name []string) error { if len(name) != 1 { - return fmt.Errorf("a label cannot have children") + return fmt.Errorf("a label cannot have children: %w", connector.ErrOperationNotAllowed) } label, err := conn.client.GetLabel(ctx, string(labelID), proton.LabelTypeLabel) @@ -225,7 +225,7 @@ func (conn *imapConnector) updateFolder(ctx context.Context, labelID imap.Mailbo } if parentID == "" { - return fmt.Errorf("parent folder %q does not exist", name[:len(name)-1]) + return fmt.Errorf("parent folder %q does not exist: %w", name[:len(name)-1], connector.ErrOperationNotAllowed) } } @@ -274,7 +274,7 @@ func (conn *imapConnector) CreateMessage( defer conn.goPollAPIEvents(false) if mailboxID == proton.AllMailLabel { - return imap.Message{}, nil, fmt.Errorf("not allowed") + return imap.Message{}, nil, connector.ErrOperationNotAllowed } // Compute the hash of the message (to match it against SMTP messages). @@ -381,7 +381,7 @@ func (conn *imapConnector) AddMessagesToMailbox(ctx context.Context, messageIDs defer conn.goPollAPIEvents(false) if isAllMailOrScheduled(mailboxID) { - return fmt.Errorf("not allowed") + return connector.ErrOperationNotAllowed } return conn.client.LabelMessages(ctx, mapTo[imap.MessageID, string](messageIDs), string(mailboxID)) @@ -392,7 +392,7 @@ func (conn *imapConnector) RemoveMessagesFromMailbox(ctx context.Context, messag defer conn.goPollAPIEvents(false) if isAllMailOrScheduled(mailboxID) { - return fmt.Errorf("not allowed") + return connector.ErrOperationNotAllowed } if err := conn.client.UnlabelMessages(ctx, mapTo[imap.MessageID, string](messageIDs), string(mailboxID)); err != nil { @@ -442,7 +442,7 @@ func (conn *imapConnector) MoveMessages(ctx context.Context, messageIDs []imap.M (labelFromID == proton.SentLabel && labelToID == proton.InboxLabel) || isAllMailOrScheduled(labelFromID) || isAllMailOrScheduled(labelToID) { - return false, fmt.Errorf("not allowed") + return false, connector.ErrOperationNotAllowed } shouldExpungeOldLocation := func() bool { From 825031e05253c3605e77e89c1225879f0144be99 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Wed, 1 Mar 2023 11:10:34 +0100 Subject: [PATCH 091/130] fix(GODT-2426): Fix crash on user delete Ensure we are always acquiring a write lock when modifying the user's `updateCh` contents. --- internal/user/events.go | 2 +- internal/user/user.go | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/internal/user/events.go b/internal/user/events.go index b6a9349d..03172cbd 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -312,7 +312,7 @@ func (user *User) handleUpdateAddressEvent(_ context.Context, event proton.Addre } return nil - }, user.apiAddrsLock) + }, user.apiAddrsLock, user.updateChLock) } func (user *User) handleDeleteAddressEvent(_ context.Context, event proton.AddressEvent) error { diff --git a/internal/user/user.go b/internal/user/user.go index 64d0fdd0..1c163a66 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -553,7 +553,7 @@ func (user *User) Close() { user.client.Close() // Close the user's update channels. - safe.RLock(func() { + safe.Lock(func() { for _, updateCh := range xslices.Unique(maps.Values(user.updateCh)) { updateCh.CloseAndDiscardQueued() } From 91ab77dce9c23a5e9d8d1b733a641b732ac61ffc Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Wed, 1 Mar 2023 09:51:53 +0100 Subject: [PATCH 092/130] fix(GODT-2424): Sync Builder Message Split Incorrect math was causing some messages to not be built and be missing from Gluon. --- internal/user/sync.go | 72 ++++++++++++++++---------------- internal/user/sync_build_test.go | 31 ++++++++++++++ 2 files changed, 68 insertions(+), 35 deletions(-) diff --git a/internal/user/sync.go b/internal/user/sync.go index 76f9b61e..215c3b82 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -503,41 +503,7 @@ func syncMessages( return } - var expectedMemUsage uint64 - var chunks [][]proton.FullMessage - - { - var lastIndex int - var index int - for _, v := range buildBatch.batch { - var dataSize uint64 - for _, a := range v.Attachments { - dataSize += uint64(a.Size) - } - - // 2x increase for attachment due to extra memory needed for decrypting and writing - // in memory buffer. - dataSize *= 2 - dataSize += uint64(len(v.Body)) - - nextMemSize := expectedMemUsage + dataSize - if nextMemSize >= syncMaxMessageBuildingMem { - chunks = append(chunks, buildBatch.batch[lastIndex:index]) - lastIndex = index - expectedMemUsage = dataSize - } else { - expectedMemUsage = nextMemSize - } - - index++ - } - - if index < len(buildBatch.batch) { - chunks = append(chunks, buildBatch.batch[index:]) - } else if index == len(buildBatch.batch) && len(chunks) == 0 { - chunks = [][]proton.FullMessage{buildBatch.batch} - } - } + chunks := chunkSyncBuilderBatch(buildBatch.batch, syncMaxMessageBuildingMem) for index, chunk := range chunks { logrus.Debugf("Build request: %v of %v count=%v", index, len(chunks), len(chunk)) @@ -852,3 +818,39 @@ func (a *attachmentDownloader) getAttachments(ctx context.Context, attachments [ func (a *attachmentDownloader) close() { a.cancel() } + +func chunkSyncBuilderBatch(batch []proton.FullMessage, maxMemory uint64) [][]proton.FullMessage { + var expectedMemUsage uint64 + var chunks [][]proton.FullMessage + var lastIndex int + var index int + + for _, v := range batch { + var dataSize uint64 + for _, a := range v.Attachments { + dataSize += uint64(a.Size) + } + + // 2x increase for attachment due to extra memory needed for decrypting and writing + // in memory buffer. + dataSize *= 2 + dataSize += uint64(len(v.Body)) + + nextMemSize := expectedMemUsage + dataSize + if nextMemSize >= maxMemory { + chunks = append(chunks, batch[lastIndex:index]) + lastIndex = index + expectedMemUsage = dataSize + } else { + expectedMemUsage = nextMemSize + } + + index++ + } + + if lastIndex < len(batch) { + chunks = append(chunks, batch[lastIndex:]) + } + + return chunks +} diff --git a/internal/user/sync_build_test.go b/internal/user/sync_build_test.go index f52f5ef9..3f0aff2e 100644 --- a/internal/user/sync_build_test.go +++ b/internal/user/sync_build_test.go @@ -24,6 +24,8 @@ import ( "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/rfc822" + "github.com/ProtonMail/go-proton-api" + "github.com/bradenaw/juniper/xslices" "github.com/stretchr/testify/require" ) @@ -47,3 +49,32 @@ func TestNewFailedMessageLiteral(t *testing.T) { require.Equal(t, `("text" "plain" () NIL NIL "base64" 114 2)`, parsed.Body) require.Equal(t, `("text" "plain" () NIL NIL "base64" 114 2 NIL NIL NIL NIL)`, parsed.Structure) } + +func TestSyncChunkSyncBuilderBatch(t *testing.T) { + // GODT-2424 - Some messages were not fully built due to a bug in the chunking if the total memory used by the + // message would be higher than the maximum we allowed. + const totalMessageCount = 100 + + msg := proton.FullMessage{ + Message: proton.Message{ + Attachments: []proton.Attachment{ + { + Size: int64(8 * Megabyte), + }, + }, + }, + AttData: nil, + } + + messages := xslices.Repeat(msg, totalMessageCount) + + chunks := chunkSyncBuilderBatch(messages, 16*Megabyte) + + var totalMessagesInChunks int + + for _, v := range chunks { + totalMessagesInChunks += len(v) + } + + require.Equal(t, totalMessagesInChunks, totalMessageCount) +} From 30651a531bb8c86d6953d16797fd1d9c4f3ce1c6 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Thu, 2 Mar 2023 13:48:14 +0100 Subject: [PATCH 093/130] fix(GODT-2427): Fix header parser Fix is included in gluon --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index f5ccc6ad..90b52cb0 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.2.0 - github.com/ProtonMail/gluon v0.15.1-0.20230301094306-3b1b90f01c0e + github.com/ProtonMail/gluon v0.15.1-0.20230302123324-da3a1cd30884 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230228124441-781ee183e1b4 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 9e9fe34c..9b11da47 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.15.1-0.20230301094306-3b1b90f01c0e h1:uzpSucUnQsHs5zNTsCR3rYFU82PgqUyHR+UcyZ4nRvY= -github.com/ProtonMail/gluon v0.15.1-0.20230301094306-3b1b90f01c0e/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230302123324-da3a1cd30884 h1:QnFkmVRM/4KLK3GrKknuXUo6VcjfJQc+/BYlPG5MOy4= +github.com/ProtonMail/gluon v0.15.1-0.20230302123324-da3a1cd30884/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= From f793b71569b43ec6dfc6704c0289f86c995c583f Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Fri, 3 Mar 2023 10:10:06 +0100 Subject: [PATCH 094/130] fix(GODT-2447): Don't assume timestamp exists in log filename --- internal/logging/logging.go | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/internal/logging/logging.go b/internal/logging/logging.go index 90331c02..667f29c4 100644 --- a/internal/logging/logging.go +++ b/internal/logging/logging.go @@ -144,7 +144,14 @@ func getLogName(version, revision string) string { func getLogTime(name string) int { re := regexp.MustCompile(`^v.*_.*_(?P\d+).log$`) - timestamp, err := strconv.Atoi(re.FindStringSubmatch(name)[re.SubexpIndex("timestamp")]) + match := re.FindStringSubmatch(name) + + if len(match) == 0 { + logrus.Warn("Could not parse log name: ", name) + return 0 + } + + timestamp, err := strconv.Atoi(match[re.SubexpIndex("timestamp")]) if err != nil { return 0 } From 667998c20750ab592a065b0f339e9b5998e6510e Mon Sep 17 00:00:00 2001 From: Romain LE JEUNE Date: Thu, 2 Mar 2023 10:56:33 +0100 Subject: [PATCH 095/130] feat(GODT-2435): Group report exception by message if exception message looks corrupted. --- .../frontend/bridge-gui/bridge-gui/SentryUtils.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index 3fe152f0..c940010c 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -118,6 +118,16 @@ sentry_uuid_t reportSentryEvent(sentry_level_t level, const char *message) { sentry_uuid_t reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception) { auto event = sentry_value_new_message_event(level, LoggerName, message); sentry_event_add_exception(event, sentry_value_new_exception(exceptionType, exception)); + + // reject exception content from the fingerprint if there is not enough content + if ( strlen(exception) < 5) { + sentry_value_t fingerprint = sentry_value_new_list(); + sentry_value_append(fingerprint, sentry_value_new_string("level")); + sentry_value_append(fingerprint, sentry_value_new_string(message)); + sentry_value_append(fingerprint, sentry_value_new_string(LoggerName)); + sentry_value_set_by_key(event, "fingerprint", fingerprint); + } + return sentry_capture_event(event); } From 9058544f5cdf627503c6d07599df31bf4aa57fc1 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Mon, 6 Mar 2023 15:48:30 +0100 Subject: [PATCH 096/130] feat(GODT-2448): Supported Answered flag Bump gluon and implement changes required for the flag changes. --- go.mod | 2 +- go.sum | 2 ++ internal/user/events.go | 9 ++++++--- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index 90b52cb0..fa76bce4 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.2.0 - github.com/ProtonMail/gluon v0.15.1-0.20230302123324-da3a1cd30884 + github.com/ProtonMail/gluon v0.15.1-0.20230306144244-3ecf7859b80e github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230228124441-781ee183e1b4 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 9b11da47..4422cd8d 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkF github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= github.com/ProtonMail/gluon v0.15.1-0.20230302123324-da3a1cd30884 h1:QnFkmVRM/4KLK3GrKknuXUo6VcjfJQc+/BYlPG5MOy4= github.com/ProtonMail/gluon v0.15.1-0.20230302123324-da3a1cd30884/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230306144244-3ecf7859b80e h1:Cg03+j04XdwUEqlV9Fhxixp+J3lXTAlGE5RohmcIfzE= +github.com/ProtonMail/gluon v0.15.1-0.20230306144244-3ecf7859b80e/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/internal/user/events.go b/internal/user/events.go index 03172cbd..d17d1080 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -669,9 +669,12 @@ func (user *User) handleUpdateMessageEvent(ctx context.Context, message proton.M update := imap.NewMessageMailboxesUpdated( imap.MessageID(message.ID), mapTo[string, imap.MailboxID](wantLabels(user.apiLabels, message.LabelIDs)), - message.Seen(), - message.Starred(), - message.IsDraft(), + imap.MessageCustomFlags{ + Seen: message.Seen(), + Flagged: message.Starred(), + Draft: message.IsDraft(), + Answered: message.IsRepliedAll == true || message.IsReplied == true, //nolint: gosimple + }, ) user.updateCh[message.AddressID].Enqueue(update) From 21ffde316d663a65f3d15b6d4910956e736580d6 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Tue, 7 Mar 2023 08:52:57 +0100 Subject: [PATCH 097/130] fix(GODT-2449): fix bug in Bridge-GUI's Exception::what(). Cherry picked from release/perth_narrows (1d426e6) --- .../bridgepp/bridgepp/Exception/Exception.cpp | 11 +++++++---- .../bridgepp/bridgepp/Exception/Exception.h | 5 +++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp index a9179038..eeda30d6 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp @@ -26,9 +26,10 @@ namespace bridgepp { /// \param[in] what A description of the exception. /// \param[in] details The optional details for the exception. //**************************************************************************************************************************************************** -Exception::Exception(QString what, QString details) noexcept +Exception::Exception(QString qwhat, QString details) noexcept : std::exception() - , what_(std::move(what)) + , qwhat_(std::move(qwhat)) + , what_(qwhat_.toLocal8Bit()) , details_(std::move(details)) { } @@ -38,6 +39,7 @@ Exception::Exception(QString what, QString details) noexcept //**************************************************************************************************************************************************** Exception::Exception(Exception const &ref) noexcept : std::exception(ref) + , qwhat_(ref.qwhat_) , what_(ref.what_) , details_(ref.details_) { } @@ -48,6 +50,7 @@ Exception::Exception(Exception const &ref) noexcept //**************************************************************************************************************************************************** Exception::Exception(Exception &&ref) noexcept : std::exception(ref) + , qwhat_(ref.qwhat_) , what_(ref.what_) , details_(ref.details_) { } @@ -57,7 +60,7 @@ Exception::Exception(Exception &&ref) noexcept /// \return a string describing the exception //**************************************************************************************************************************************************** QString Exception::qwhat() const noexcept { - return what_; + return qwhat_; } @@ -65,7 +68,7 @@ QString Exception::qwhat() const noexcept { /// \return A pointer to the description string of the exception. //**************************************************************************************************************************************************** const char *Exception::what() const noexcept { - return what_.toLocal8Bit().constData(); + return what_.constData(); } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h index 9cde3e7d..ff565d23 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h @@ -31,7 +31,7 @@ namespace bridgepp { //**************************************************************************************************************************************************** class Exception : public std::exception { public: // member functions - explicit Exception(QString what = QString(), QString details = QString()) noexcept; ///< Constructor + explicit Exception(QString qwhat = QString(), QString details = QString()) noexcept; ///< Constructor Exception(Exception const &ref) noexcept; ///< copy constructor Exception(Exception &&ref) noexcept; ///< copy constructor Exception &operator=(Exception const &) = delete; ///< Disabled assignment operator @@ -42,7 +42,8 @@ public: // member functions QString details() const noexcept; ///< Return the details for the exception private: // data members - QString const what_; ///< The description of the exception. + QString const qwhat_; ///< The description of the exception. + QByteArray const what_; ///< The c-string version of the qwhat message. Stored as a QByteArray for automatic lifetime management. QString const details_; ///< The optional details for the exception. }; From febc994cecb16bf3c650a18afe0c176888719f68 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Tue, 7 Mar 2023 10:02:09 +0100 Subject: [PATCH 098/130] feat(GODT-2446): Attach logs to sentry reports for relevant bridge-gui exceptions. Cherry picked from release/perth_narrows (2aa4e7c) # Conflicts: # internal/frontend/bridge-gui/bridge-gui/AppController.cpp # internal/frontend/bridge-gui/bridge-gui/AppController.h # internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp # internal/frontend/bridge-gui/bridge-gui/LogUtils.h # internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp # internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp # internal/frontend/bridge-gui/bridge-gui/SentryUtils.h # internal/frontend/bridge-gui/bridge-gui/main.cpp --- .../bridge-gui/bridge-gui/AppController.cpp | 18 +++---- .../bridge-gui/bridge-gui/AppController.h | 3 +- .../bridge-gui/EventStreamWorker.cpp | 2 +- .../bridge-gui/bridge-gui/LogUtils.cpp | 38 +++++++++++++++ .../frontend/bridge-gui/bridge-gui/LogUtils.h | 1 + .../bridge-gui/bridge-gui/QMLBackend.cpp | 9 ++-- .../bridge-gui/bridge-gui/QMLBackend.h | 2 +- .../bridge-gui/bridge-gui/SentryUtils.cpp | 47 +++++++++++++++++++ .../bridge-gui/bridge-gui/SentryUtils.h | 3 +- .../frontend/bridge-gui/bridge-gui/main.cpp | 20 +++----- .../bridgepp/bridgepp/Exception/Exception.cpp | 37 +++++++++++++-- .../bridgepp/bridgepp/Exception/Exception.h | 7 ++- 12 files changed, 149 insertions(+), 38 deletions(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp index e0df2a5a..0f2ad890 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.cpp @@ -90,20 +90,14 @@ Settings &AppController::settings() { //**************************************************************************************************************************************************** -/// \param[in] function The function that caught the exception. -/// \param[in] message The error message. -/// \param[in] details The details for the error. +/// \param[in] exception The exception that triggered the fatal error. //**************************************************************************************************************************************************** -void AppController::onFatalError(QString const &function, QString const &message, QString const &details) { - QString fullMessage = QString("%1(): %2").arg(function, message); - if (!details.isEmpty()) { - fullMessage += "\n\nDetails:\n" + details; - } - sentry_uuid_s const uuid = reportSentryException(SENTRY_LEVEL_ERROR, "AppController got notified of a fatal error", "Exception", - fullMessage.toLocal8Bit()); - QMessageBox::critical(nullptr, tr("Error"), message); +void AppController::onFatalError(Exception const &exception) { + sentry_uuid_t uuid = reportSentryException("AppController got notified of a fatal error", exception); + + QMessageBox::critical(nullptr, tr("Error"), exception.what()); restart(true); - log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex(), fullMessage)); + log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex(), exception.detailedWhat())); qApp->exit(EXIT_FAILURE); } diff --git a/internal/frontend/bridge-gui/bridge-gui/AppController.h b/internal/frontend/bridge-gui/bridge-gui/AppController.h index f8955dd5..d55e1f11 100644 --- a/internal/frontend/bridge-gui/bridge-gui/AppController.h +++ b/internal/frontend/bridge-gui/bridge-gui/AppController.h @@ -28,6 +28,7 @@ class Log; class Overseer; class GRPCClient; class ProcessMonitor; +class Exception; } //@formatter:on @@ -54,7 +55,7 @@ public: // member functions. void setLauncherArgs(const QString &launcher, const QStringList &args); public slots: - void onFatalError(QString const &function, QString const &message, QString const &details); ///< Handle fatal errors. + void onFatalError(bridgepp::Exception const& e); ///< Handle fatal errors. private: // member functions AppController(); ///< Default constructor. diff --git a/internal/frontend/bridge-gui/bridge-gui/EventStreamWorker.cpp b/internal/frontend/bridge-gui/bridge-gui/EventStreamWorker.cpp index 10d6ba90..ec38d853 100644 --- a/internal/frontend/bridge-gui/bridge-gui/EventStreamWorker.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/EventStreamWorker.cpp @@ -52,7 +52,7 @@ void EventStreamReader::run() { emit finished(); } catch (Exception const &e) { - reportSentryException(SENTRY_LEVEL_ERROR, "Error during event stream read", "Exception", e.what()); + reportSentryException("Error during event stream read", e); emit error(e.qwhat()); } } diff --git a/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp index 35c1c150..4964039b 100644 --- a/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp @@ -24,6 +24,11 @@ using namespace bridgepp; +namespace { +qsizetype const logFileTailMaxLength = 25 * 1024; ///< The maximum length of the portion of log returned by tailOfLatestBridgeLog() +} + + //**************************************************************************************************************************************************** /// \return user logs directory used by bridge. //**************************************************************************************************************************************************** @@ -64,3 +69,36 @@ Log &initLog() { return log; } + + +//**************************************************************************************************************************************************** +/// \brief Return the path of the latest bridge log. +/// \return The path of the latest bridge log file. +/// \return An empty string if no bridge log file was found. +//**************************************************************************************************************************************************** +QString latestBridgeLogPath() { + QDir const logsDir(userLogsDir()); + if (logsDir.isEmpty()) { + return QString(); + } + QFileInfoList files = logsDir.entryInfoList({ "v*.log" }, QDir::Files); // could do sorting, but only by last modification time. we want to sort by creation time. + std::sort(files.begin(), files.end(), [](QFileInfo const &lhs, QFileInfo const &rhs) -> bool { + return lhs.birthTime() < rhs.birthTime(); + }); + return files.back().absoluteFilePath(); +} + + +//**************************************************************************************************************************************************** +/// Return the maxSize last bytes of the latest bridge log. +//**************************************************************************************************************************************************** +QByteArray tailOfLatestBridgeLog() { + QString path = latestBridgeLogPath(); + if (path.isEmpty()) { + return QByteArray(); + } + + QFile file(path); + return file.open(QIODevice::Text | QIODevice::ReadOnly) ? file.readAll().right(logFileTailMaxLength) : QByteArray(); +} + diff --git a/internal/frontend/bridge-gui/bridge-gui/LogUtils.h b/internal/frontend/bridge-gui/bridge-gui/LogUtils.h index b324301e..60e1896d 100644 --- a/internal/frontend/bridge-gui/bridge-gui/LogUtils.h +++ b/internal/frontend/bridge-gui/bridge-gui/LogUtils.h @@ -24,6 +24,7 @@ bridgepp::Log &initLog(); ///< Initialize the application log. +QByteArray tailOfLatestBridgeLog(); ///< Return the last bytes of the last bridge log. #endif //BRIDGE_GUI_LOG_UTILS_H diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp index c959a3a4..66a62488 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp @@ -19,15 +19,16 @@ #include "QMLBackend.h" #include "BuildConfig.h" #include "EventStreamWorker.h" +#include "LogUtils.h" #include -#include #include +#include #include #define HANDLE_EXCEPTION(x) try { x } \ - catch (Exception const &e) { emit fatalError(__func__, e.qwhat(), e.details()); } \ - catch (...) { emit fatalError(__func__, QString("An unknown exception occurred"), QString()); } + catch (Exception const &e) { emit fatalError(e); } \ + catch (...) { emit fatalError(Exception("An unknown exception occurred", QString(), __func__)); } #define HANDLE_EXCEPTION_RETURN_BOOL(x) HANDLE_EXCEPTION(x) return false; #define HANDLE_EXCEPTION_RETURN_QSTRING(x) HANDLE_EXCEPTION(x) return QString(); #define HANDLE_EXCEPTION_RETURN_ZERO(x) HANDLE_EXCEPTION(x) return 0; @@ -596,7 +597,7 @@ void QMLBackend::login(QString const &username, QString const &password) const { HANDLE_EXCEPTION( if (username.compare("coco@bandicoot", Qt::CaseInsensitive) == 0) { throw Exception("User requested bridge-gui to crash by trying to log as coco@bandicoot", - "This error exists for test purposes and should be ignored."); + "This error exists for test purposes and should be ignored.", __func__, tailOfLatestBridgeLog()); } app().grpc().login(username, password); ) diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h index d5ff668b..880b7a13 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.h @@ -237,7 +237,7 @@ signals: // Signals received from the Go backend, to be forwarded to QML void imapLoginWhileSignedOut(QString const& username); ///< Signal for the notification of IMAP login attempt on a signed out account. // This signal is emitted when an exception is intercepted is calls triggered by QML. QML engine would intercept the exception otherwise. - void fatalError(QString const &function, QString const &message, QString const &details) const; ///< Signal emitted when an fatal error occurs. + void fatalError(bridgepp::Exception const& e) const; ///< Signal emitted when an fatal error occurs. private: // member functions void retrieveUserList(); ///< Retrieve the list of users via gRPC. diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp index c940010c..b7d80720 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.cpp @@ -18,6 +18,7 @@ #include "SentryUtils.h" #include "BuildConfig.h" #include +#include using namespace bridgepp; @@ -26,6 +27,23 @@ using namespace bridgepp; static constexpr const char *LoggerName = "bridge-gui"; +//**************************************************************************************************************************************************** +/// \return The temporary file used for sentry attachment. +//**************************************************************************************************************************************************** +QString sentryAttachmentFilePath() { + static QString path; + if (!path.isEmpty()) { + return path; + } + while (true) { + path = QDir::temp().absoluteFilePath(QUuid::createUuid().toString(QUuid::WithoutBraces) + ".txt"); // Sentry does not offer preview for .log files. + if (!QFileInfo::exists(path)) { + return path; + } + } +} + + //**************************************************************************************************************************************************** /// \brief Get a hash of the computer's host name //**************************************************************************************************************************************************** @@ -96,6 +114,8 @@ sentry_options_t* newSentryOptions(const char *sentryDNS, const char *cacheDir) sentry_options_set_release(sentryOptions, appVersion(PROJECT_VER).toUtf8()); sentry_options_set_max_breadcrumbs(sentryOptions, 50); sentry_options_set_environment(sentryOptions, PROJECT_BUILD_ENV); + QByteArray const array = sentryAttachmentFilePath().toLocal8Bit(); + sentry_options_add_attachment(sentryOptions, array.constData()); // Enable this for debugging sentry. // sentry_options_set_debug(sentryOptions, 1); @@ -132,3 +152,30 @@ sentry_uuid_t reportSentryException(sentry_level_t level, const char *message, c } +//**************************************************************************************************************************************************** +/// \param[in] message The message for the exception. +/// \param[in] function The name of the function that triggered the exception. +/// \param[in] exception The exception. +/// \return The Sentry exception UUID. +//**************************************************************************************************************************************************** +sentry_uuid_t reportSentryException(QString const &message, bridgepp::Exception const exception) { + QByteArray const attachment = exception.attachment(); + QFile file(sentryAttachmentFilePath()); + bool const hasAttachment = !attachment.isEmpty(); + if (hasAttachment) { + if (file.open(QIODevice::Text | QIODevice::WriteOnly)) { + file.write(attachment); + file.close(); + } + } + + sentry_uuid_t const uuid = reportSentryException(SENTRY_LEVEL_ERROR, message.toLocal8Bit(), "Exception", + exception.detailedWhat().toLocal8Bit()); + + if (hasAttachment) { + file.remove(); + } + + return uuid; +} + diff --git a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h index 28e6aeb1..8d1d966e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h +++ b/internal/frontend/bridge-gui/bridge-gui/SentryUtils.h @@ -25,6 +25,7 @@ void initSentry(); void setSentryReportScope(); sentry_options_t* newSentryOptions(const char * sentryDNS, const char * cacheDir); sentry_uuid_t reportSentryEvent(sentry_level_t level, const char *message); -sentry_uuid_t reportSentryException(sentry_level_t level, const char *message, const char *exceptionType, const char *exception); +sentry_uuid_t reportSentryException(QString const& message, bridgepp::Exception const exception); + #endif //BRIDGE_GUI_SENTRYUTILS_H diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 35d0e14e..cc0978aa 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -219,8 +219,8 @@ void focusOtherInstance() { } catch (Exception const &e) { app().log().error(e.qwhat()); - auto uuid = reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during focusOtherInstance()", "Exception", e.what()); - app().log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex(), e.qwhat())); + auto uuid = reportSentryException("Exception occurred during focusOtherInstance()", e); + app().log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex()).arg(e.qwhat())); } } @@ -308,7 +308,8 @@ int main(int argc, char *argv[]) { if (!cliOptions.attach) { if (isBridgeRunning()) { - throw Exception("An orphan instance of bridge is already running. Please terminate it and relaunch the application."); + throw Exception("An orphan instance of bridge is already running. Please terminate it and relaunch the application.", + QString(), QString(), tailOfLatestBridgeLog()); } // before launching bridge, we remove any trailing service config file, because we need to make sure we get a newly generated one. @@ -337,6 +338,7 @@ int main(int argc, char *argv[]) { QQuickWindow::setSceneGraphBackend((app().settings().useSoftwareRenderer() || cliOptions.useSoftwareRenderer) ? "software" : "rhi"); log.info(QString("Qt Quick renderer: %1").arg(QQuickWindow::sceneGraphBackend())); + QQmlApplicationEngine engine; std::unique_ptr rootComponent(createRootQmlComponent(engine)); std::unique_ptr rootObject(rootComponent->create(engine.rootContext())); @@ -398,17 +400,9 @@ int main(int argc, char *argv[]) { return result; } catch (Exception const &e) { - QString fullMessage = e.qwhat(); - bool const hasDetails = !e.details().isEmpty(); - if (hasDetails) - fullMessage += "\n\nDetails:\n" + e.details(); - sentry_uuid_s const uuid = reportSentryException(SENTRY_LEVEL_ERROR, "Exception occurred during main", "Exception", fullMessage.toLocal8Bit()); + sentry_uuid_s const uuid = reportSentryException("Exception occurred during main", e); QMessageBox::critical(nullptr, "Error", e.qwhat()); - QTextStream errStream(stderr); - errStream << "reportID: " << QByteArray(uuid.bytes, 16).toHex() << " Captured exception :" << e.qwhat() << "\n"; - if (hasDetails) - errStream << "\nDetails:\n" << e.details() << "\n"; - closeBridgeApp(); + QTextStream(stderr) << "reportID: " << QByteArray(uuid.bytes, 16).toHex() << " Captured exception :" << e.detailedWhat() << "\n"; return EXIT_FAILURE; } } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp index eeda30d6..dc614b88 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.cpp @@ -25,12 +25,15 @@ namespace bridgepp { //**************************************************************************************************************************************************** /// \param[in] what A description of the exception. /// \param[in] details The optional details for the exception. +/// \param[in] function The name of the calling function. //**************************************************************************************************************************************************** -Exception::Exception(QString qwhat, QString details) noexcept +Exception::Exception(QString qwhat, QString details, QString function, QByteArray attachment) noexcept : std::exception() , qwhat_(std::move(qwhat)) , what_(qwhat_.toLocal8Bit()) - , details_(std::move(details)) { + , details_(std::move(details)) + , function_(std::move(function)) + , attachment_(std::move(attachment)) { } @@ -41,7 +44,9 @@ Exception::Exception(Exception const &ref) noexcept : std::exception(ref) , qwhat_(ref.qwhat_) , what_(ref.what_) - , details_(ref.details_) { + , details_(ref.details_) + , function_(ref.function_) + , attachment_(ref.attachment_) { } @@ -52,7 +57,9 @@ Exception::Exception(Exception &&ref) noexcept : std::exception(ref) , qwhat_(ref.qwhat_) , what_(ref.what_) - , details_(ref.details_) { + , details_(ref.details_) + , function_(ref.function_) + , attachment_(ref.attachment_) { } @@ -80,4 +87,26 @@ QString Exception::details() const noexcept { } +//**************************************************************************************************************************************************** +/// \return The attachment for the exception. +//**************************************************************************************************************************************************** +QByteArray Exception::attachment() const noexcept { + return attachment_; +} + + +//**************************************************************************************************************************************************** +/// \return The details exception. +//**************************************************************************************************************************************************** +QString Exception::detailedWhat() const { + QString result = qwhat_; + if (!function_.isEmpty()) { + result = QString("%1(): %2").arg(function_, result); + } + if (!details_.isEmpty()) { + result += "\n\nDetails:\n" + details_; + } + return result; +} + } // namespace bridgepp diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h index ff565d23..dad9a867 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h @@ -31,7 +31,8 @@ namespace bridgepp { //**************************************************************************************************************************************************** class Exception : public std::exception { public: // member functions - explicit Exception(QString qwhat = QString(), QString details = QString()) noexcept; ///< Constructor + explicit Exception(QString qwhat = QString(), QString details = QString(), QString function = QString(), + QByteArray attachment = QByteArray()) noexcept; ///< Constructor Exception(Exception const &ref) noexcept; ///< copy constructor Exception(Exception &&ref) noexcept; ///< copy constructor Exception &operator=(Exception const &) = delete; ///< Disabled assignment operator @@ -40,11 +41,15 @@ public: // member functions QString qwhat() const noexcept; ///< Return the description of the exception as a QString const char *what() const noexcept override; ///< Return the description of the exception as C style string QString details() const noexcept; ///< Return the details for the exception + QByteArray attachment() const noexcept; ///< Return the attachment for the exception. + QString detailedWhat() const; ///< Return the detailed description of the message (i.e. including the function name and the details). private: // data members QString const qwhat_; ///< The description of the exception. QByteArray const what_; ///< The c-string version of the qwhat message. Stored as a QByteArray for automatic lifetime management. QString const details_; ///< The optional details for the exception. + QString const function_; ///< The name of the function that created the exception. + QByteArray const attachment_; ///< The attachment to add to the exception. }; From 2781f065492434f642859106f476b39f6b6babbd Mon Sep 17 00:00:00 2001 From: Romain LE JEUNE Date: Tue, 7 Mar 2023 11:42:39 +0100 Subject: [PATCH 099/130] chore: Bridge Quebec v3.1.0. --- Changelog.md | 73 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 2 +- 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/Changelog.md b/Changelog.md index e8e75722..558e0e20 100644 --- a/Changelog.md +++ b/Changelog.md @@ -2,6 +2,79 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/) +## [Bridge 3.1.0] Quebec + +### Changed +* GODT-2224: Refactor bridge sync to use less memory. +* GODT-2446: Attach logs to sentry reports for relevant bridge-gui exceptions. +* GODT-2448: Supported Answered flag. +* GODT-2435: Group report exception by message if exception message looks corrupted. +* GODT-2382: Added bridge-gui settings file with 'UseSoftwareRenderer' value. +* GODT-2411: allow qmake executable to be named qmake6. +* GODT-2273: Menu with "Close window" and "Quit Bridge" button in main window. +* GODT-2261: Sync progress in GUI. +* GODT-2385: Gluon cache fallback. +* GODT-2366: Handle failed message updates as creates. +* GODT-2201: Bump Gluon to use pure Go IMAP parser. +* GODT-2374: Import TLS certs via shell. +* GODT-2361: Bump GPA to use simple encrypter. +* GODT-2364: Wait and retry once if the gRPC service config file exists but cannot be opened. +* GODT-2364: Added optional details to C++ exceptions. +* GODT-1264: Constraint on Scheduled mailbox in connector + Integration tests. +* GODT-2356: Unify sentry release description and add more context to it. +* GODT-2357: Hide DSN_SENTRY and use single setting point for DSN_SENTRY. +* GODT-1264: Creation and visibility of the 'Scheduled' system label. +* GODT-2283: Limit max import size to 30MB (bump GPA to v0.4.0). +* GODT-2352: Only copy resource file when needed. +* GODT-2352: Use go-build-finalize macro to build vault-editor for both mac arch. +* GODT-2278: Properly override server_name for go. +* GODT-2255: Randomize the focus service port. +* GODT-2144: Handle IMAP/SMTP server errors via event stream. +* GODT-2144: Delay IMAP/SMTP server start until all users are loaded. +* GODT-2295: Notifications for IMAP login when signed out. +* GODT-2278: Improve sentry logs. +* GODT-2289: UIDValidity as Timestamp. + +### Fixed +* GODT-2449: Fix bug in Bridge-GUI's Exception::what(). +* GODT-2427: Fix header parser. +* GODT-2424: Sync Builder Message Split. +* GODT-2426: Fix crash on user delete. +* GODT-2419: Use connector.ErrOperationNotAllowed. +* GODT-2413: Use qEnvironmentVariable() instead of qgetenv(). +* GODT-2418: Ensure child folders are updated when parent is. +* GODT-2399: Fix immediate message deletion during updates. +* GODT-2412: Don't treat context cancellation as BadEvent. +* GODT-1945: Handle disabled addresses correctly. +* GODT-2404: Handle unexpected EOF. +* GODT-2390: Add reports for uncaught json and net.opErr. +* GODT-2393: Improved handling of unrecoverable error. +* GODT-2394: Bump Gluon for golang.org/x/text DoS risk. +* GODT-2387: Ensure vault can be unlocked after factory reset. +* GODT-2389: Close bridge on exception and add max termination wait time. +* GODT-2201: Add missing rfc5322.CharsetReader initialization. +* GODT-1804: Preserve MIME parameters when uploading attachments. +* GODT-2312: Used space is properly updated. +* GODT-2319: Seed the math/rand RNG on app startup. +* GODT-2272: Use shorter filename for gRPC file socket. +* GODT-2318: Remove gluon DB if label sync was incomplete. +* GODT-2326: Only run sync after addIMAPUser(). +* GODT-2323: Fix Expunge not issued for move. +* GODT-2224: Properly handle context cancellation during sync. +* GODT-2328: Ignore labels that aren't part of user label set. +* GODT-2333: Do not allow modifications to All Mail label. +* GODT-2326: Fix potential Win32 API deadlock. +* GODT-1804: Only promote content headers if non-empty. +* GODT-2327: Remove unnecessary sync when changing address mode. +* GODT-2343: Only poll after send if sync is complete. +* GODT-2336: Recover from changed address order while bridge is down. +* GODT-2347: Prevent updates from being dropped if goroutine doesn't start fast. +* GODT-2351: Bump GPA to properly handle net.OpError and add tests. +* GODT-2351: Bump GPA to automatically retry on net.OpError. +* GODT-2365: Use predictable remote ID for placeholder mailboxes. +* GODT-2381: Unset draft flag on sent messages. +* GODT-2380: Only set external ID in header if non-empty. + ## [Bridge 3.0.15/16] Perth Narrows ### Changed diff --git a/Makefile b/Makefile index 5aba432d..03388819 100644 --- a/Makefile +++ b/Makefile @@ -11,7 +11,7 @@ ROOT_DIR:=$(shell dirname $(realpath $(firstword $(MAKEFILE_LIST)))) .PHONY: build build-gui build-nogui build-launcher versioner hasher # Keep version hardcoded so app build works also without Git repository. -BRIDGE_APP_VERSION?=3.0.15+git +BRIDGE_APP_VERSION?=3.1.0+git APP_VERSION:=${BRIDGE_APP_VERSION} APP_FULL_NAME:=Proton Mail Bridge APP_VENDOR:=Proton AG From 07339aff219de1c2e44547c07b498548349bbccf Mon Sep 17 00:00:00 2001 From: Romain Le Jeune Date: Tue, 7 Mar 2023 16:47:07 +0000 Subject: [PATCH 100/130] fix(GODT-2458): Wait for both bridge and bridge-gui to be ended before restarting on crash. --- cmd/launcher/main.go | 19 +++++++++------- cmd/launcher/main_test.go | 22 +++++++++++++++++++ .../frontend/bridge-gui/bridge-gui/main.cpp | 18 ++++++++++----- 3 files changed, 45 insertions(+), 14 deletions(-) diff --git a/cmd/launcher/main.go b/cmd/launcher/main.go index 32acdf6d..a6c15889 100644 --- a/cmd/launcher/main.go +++ b/cmd/launcher/main.go @@ -127,9 +127,11 @@ func main() { //nolint:funlen l = l.WithField("exe_path", exe) - args, wait, mainExe := findAndStripWait(args) + args, wait, mainExes := findAndStripWait(args) if wait { - waitForProcessToFinish(mainExe) + for _, mainExe := range mainExes { + waitForProcessToFinish(mainExe) + } } cmd := execabs.Command(exe, appendLauncherPath(launcher, args)...) //nolint:gosec @@ -186,12 +188,11 @@ func findAndStrip[T comparable](slice []T, v T) (strippedList []T, found bool) { } // findAndStripWait Check for waiter flag get its value and clean them both. -func findAndStripWait(args []string) ([]string, bool, string) { +func findAndStripWait(args []string) ([]string, bool, []string) { res := append([]string{}, args...) hasFlag := false - var value string - + values := make([]string, 0) for k, v := range res { if v != FlagWait { continue @@ -200,14 +201,16 @@ func findAndStripWait(args []string) ([]string, bool, string) { continue } hasFlag = true - value = res[k+1] + values = append(values, res[k+1]) } if hasFlag { res, _ = findAndStrip(res, FlagWait) - res, _ = findAndStrip(res, value) + for _, v := range values { + res, _ = findAndStrip(res, v) + } } - return res, hasFlag, value + return res, hasFlag, values } func getPathToUpdatedExecutable( diff --git a/cmd/launcher/main_test.go b/cmd/launcher/main_test.go index 607b60fe..42e80595 100644 --- a/cmd/launcher/main_test.go +++ b/cmd/launcher/main_test.go @@ -56,3 +56,25 @@ func TestFindAndStrip(t *testing.T) { assert.False(t, found) assert.True(t, xslices.Equal(result, []string{})) } + +func TestFindAndStripWait(t *testing.T) { + result, found, values := findAndStripWait([]string{"a", "b", "c"}) + assert.False(t, found) + assert.True(t, xslices.Equal(result, []string{"a", "b", "c"})) + assert.True(t, xslices.Equal(values, []string{})) + + result, found, values = findAndStripWait([]string{"a", "--wait", "b"}) + assert.True(t, found) + assert.True(t, xslices.Equal(result, []string{"a"})) + assert.True(t, xslices.Equal(values, []string{"b"})) + + result, found, values = findAndStripWait([]string{"a", "--wait", "b", "--wait", "c"}) + assert.True(t, found) + assert.True(t, xslices.Equal(result, []string{"a"})) + assert.True(t, xslices.Equal(values, []string{"b", "c"})) + + result, found, values = findAndStripWait([]string{"a", "--wait", "b", "--wait", "c", "--wait", "d"}) + assert.True(t, found) + assert.True(t, xslices.Equal(result, []string{"a"})) + assert.True(t, xslices.Equal(values, []string{"b", "c", "d"})) +} diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index cc0978aa..3f7a6a14 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -227,8 +227,9 @@ void focusOtherInstance() { //**************************************************************************************************************************************************** /// \param [in] args list of arguments to pass to bridge. +/// \return bridge executable path //**************************************************************************************************************************************************** -void launchBridge(QStringList const &args) { +const QString launchBridge(QStringList const &args) { UPOverseer &overseer = app().bridgeOverseer(); overseer.reset(); @@ -245,6 +246,7 @@ void launchBridge(QStringList const &args) { app().log().info(QString("Launching bridge process with command \"%1\" %2").arg(bridgeExePath, params.join(" "))); overseer = std::make_unique(new ProcessMonitor(bridgeExePath, params, nullptr), nullptr); overseer->startWorker(true); + return bridgeExePath; } @@ -305,7 +307,7 @@ int main(int argc, char *argv[]) { // When not in attached mode, log entries are forwarded to bridge, which output it on stdout/stderr. bridge-gui's process monitor intercept // these outputs and output them on the command-line. log.setLevel(cliOptions.logLevel); - + QString bridgeexec; if (!cliOptions.attach) { if (isBridgeRunning()) { throw Exception("An orphan instance of bridge is already running. Please terminate it and relaunch the application.", @@ -315,7 +317,7 @@ int main(int argc, char *argv[]) { // before launching bridge, we remove any trailing service config file, because we need to make sure we get a newly generated one. FocusGRPCClient::removeServiceConfigFile(configDir); GRPCClient::removeServiceConfigFile(configDir); - launchBridge(cliOptions.bridgeArgs); + bridgeexec = launchBridge(cliOptions.bridgeArgs); } log.info(QString("Retrieving gRPC service configuration from '%1'").arg(QDir::toNativeSeparators(grpcServerConfigPath(configDir)))); @@ -373,11 +375,15 @@ int main(int argc, char *argv[]) { int result = 0; if (!startError) { // we succeeded in launching bridge, so we can be set as mainExecutable. - QString mainExe = QString::fromLocal8Bit(argv[0]); - app().grpc().setMainExecutable(mainExe); + QString mainexec = QString::fromLocal8Bit(argv[0]); + app().grpc().setMainExecutable(mainexec); QStringList args = cliOptions.bridgeGuiArgs; args.append(waitFlag); - args.append(mainExe); + args.append(mainexec); + if (!bridgeexec.isEmpty()) { + args.append(waitFlag); + args.append(bridgeexec); + } app().setLauncherArgs(cliOptions.launcher, args); result = QGuiApplication::exec(); } From f627151d046ee1c60fe4c52a0b99800d614dec0a Mon Sep 17 00:00:00 2001 From: Romain LE JEUNE Date: Thu, 9 Mar 2023 14:50:34 +0100 Subject: [PATCH 101/130] fix(GODT-2469): Fix sentry revision hash for cmake on windows. --- internal/frontend/bridge-gui/bridge-gui/build.ps1 | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/build.ps1 b/internal/frontend/bridge-gui/bridge-gui/build.ps1 index 004b1a54..1549e272 100644 --- a/internal/frontend/bridge-gui/bridge-gui/build.ps1 +++ b/internal/frontend/bridge-gui/bridge-gui/build.ps1 @@ -92,7 +92,7 @@ git submodule update --init --recursive $vcpkgRoot . $cmakeExe -G "Visual Studio 17 2022" -DCMAKE_BUILD_TYPE="$buildConfig" ` -DBRIDGE_APP_FULL_NAME="$bridgeFullName" ` -DBRIDGE_VENDOR="$bridgeVendor" ` - -DBRIDGE_REVISION=$REVISION_HASH ` + -DBRIDGE_REVISION="$REVISION_HASH" ` -DBRIDGE_APP_VERSION="$bridgeVersion" ` -DBRIDGE_BUILD_TIME="$bridgeBuidTime" ` -DBRIDGE_DSN_SENTRY="$bridgeDsnSentry" ` From 7eaf1655b27c1065c48b325158cd6cbd03c842e6 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Fri, 10 Mar 2023 16:04:04 +0100 Subject: [PATCH 102/130] chore: Bump Gluon for fixes - GODT-2442: Handle DB deletes on windows - GODT-2419: Improve Error Messages - GODT-2430: Collect more info to diagnose issue --- go.mod | 2 +- go.sum | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/go.mod b/go.mod index fa76bce4..fc84cde9 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.2.0 - github.com/ProtonMail/gluon v0.15.1-0.20230306144244-3ecf7859b80e + github.com/ProtonMail/gluon v0.15.1-0.20230310125443-f755e8ce082a github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230228124441-781ee183e1b4 github.com/ProtonMail/go-rfc5322 v0.11.0 diff --git a/go.sum b/go.sum index 4422cd8d..03381247 100644 --- a/go.sum +++ b/go.sum @@ -28,10 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.15.1-0.20230302123324-da3a1cd30884 h1:QnFkmVRM/4KLK3GrKknuXUo6VcjfJQc+/BYlPG5MOy4= -github.com/ProtonMail/gluon v0.15.1-0.20230302123324-da3a1cd30884/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= -github.com/ProtonMail/gluon v0.15.1-0.20230306144244-3ecf7859b80e h1:Cg03+j04XdwUEqlV9Fhxixp+J3lXTAlGE5RohmcIfzE= -github.com/ProtonMail/gluon v0.15.1-0.20230306144244-3ecf7859b80e/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230310125443-f755e8ce082a h1:o7gQKDCJMYju8svD4ufB/YfcUcWUPfQjau3MDNF2dQQ= +github.com/ProtonMail/gluon v0.15.1-0.20230310125443-f755e8ce082a/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= From b57ca1506dd0e6bd1517176b225c0ef42a652e5d Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Fri, 10 Mar 2023 15:49:10 +0100 Subject: [PATCH 103/130] fix(GODT-2473): Fix handling of complex mime types When rebuilding attachments, ensure that more complicated mime types are properly re-constructed. If we fail to parse the mime type, set the value as is. --- pkg/message/build.go | 13 ++++++++++++- pkg/message/build_test.go | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 2 deletions(-) diff --git a/pkg/message/build.go b/pkg/message/build.go index f6bfbc0a..dbace192 100644 --- a/pkg/message/build.go +++ b/pkg/message/build.go @@ -36,6 +36,7 @@ import ( "github.com/emersion/go-message" "github.com/emersion/go-message/textproto" "github.com/pkg/errors" + "github.com/sirupsen/logrus" ) var ( @@ -543,7 +544,17 @@ func getAttachmentPartHeader(att proton.Attachment) message.Header { hdr := toMessageHeader(att.Headers) // All attachments have a content type. - hdr.SetContentType(string(att.MIMEType), map[string]string{"name": mime.QEncoding.Encode("utf-8", att.Name)}) + mimeType, params, err := mime.ParseMediaType(string(att.MIMEType)) + if err != nil { + logrus.WithError(err).Errorf("Failed to parse mime type: '%v'", att.MIMEType) + hdr.Set("Content-Type", string(att.MIMEType)) + } else { + // Merge the overridden name into the params + encodedName := mime.QEncoding.Encode("utf-8", att.Name) + params["name"] = encodedName + params["filename"] = encodedName + hdr.SetContentType(mimeType, params) + } // All attachments have a content disposition. hdr.SetContentDisposition(string(att.Disposition), map[string]string{"filename": mime.QEncoding.Encode("utf-8", att.Name)}) diff --git a/pkg/message/build_test.go b/pkg/message/build_test.go index 5689037e..26d72ced 100644 --- a/pkg/message/build_test.go +++ b/pkg/message/build_test.go @@ -793,7 +793,8 @@ func TestBuildAttachmentWithLongFilename(t *testing.T) { expectHeader(`Content-Type`, contains(veryLongName)). expectContentDispositionParam(`filename`, is(veryLongName)). expectHeader(`Content-Disposition`, contains(veryLongName)). - expectSection(hasMaxLineLength(215)) + // GODT-2477 - Implement line splitting according to RFC-2184. + expectSection(hasMaxLineLength(426)) } func TestBuildMessageDate(t *testing.T) { @@ -1231,3 +1232,38 @@ func readFile(t *testing.T, path string) string { return string(b) } + +func TestBuildComplexMIMEType(t *testing.T) { + m := gomock.NewController(t) + defer m.Finish() + + kr := utils.MakeKeyRing(t) + msg := newTestMessage(t, kr, "messageID", "addressID", "text/html", "body", time.Now()) + att0 := addTestAttachment(t, kr, &msg, "attachID0", "attach0.png", "image/png", "attachment", "attach0") + att1 := addTestAttachment(t, kr, &msg, "attachID1", "Cat_August_2010-4.jpeg", "image/jpeg; name=Cat_August_2010-4.jpeg; x-unix-mode=0644", "attachment", "attach1") + + res, err := BuildRFC822(kr, msg, [][]byte{ + att0, + att1, + }, JobOptions{}) + require.NoError(t, err) + + section(t, res, 1). + expectBody(is(`body`)). + expectContentType(is(`text/html`)). + expectTransferEncoding(is(`quoted-printable`)) + + section(t, res, 2). + expectBody(is(`attach0`)). + expectContentType(is(`image/png`)). + expectTransferEncoding(is(`base64`)). + expectContentTypeParam(`name`, is(`attach0.png`)). + expectContentDispositionParam(`filename`, is(`attach0.png`)) + + section(t, res, 3). + expectBody(is(`attach1`)). + expectContentType(is(`image/jpeg`)). + expectTransferEncoding(is(`base64`)). + expectContentTypeParam(`name`, is(`Cat_August_2010-4.jpeg`)). + expectContentDispositionParam(`filename`, is(`Cat_August_2010-4.jpeg`)) +} From 30c1c145052fb2394cdce61a97b95af58882beff Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Mon, 13 Mar 2023 12:00:23 +0100 Subject: [PATCH 104/130] fix(GODT-2480): Do not override X-Original-Date with invalid Date --- pkg/message/build.go | 6 +++-- pkg/message/build_framework_test.go | 36 ++++++++++++++++++++++------- pkg/message/build_test.go | 35 ++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/pkg/message/build.go b/pkg/message/build.go index dbace192..57d7eb42 100644 --- a/pkg/message/build.go +++ b/pkg/message/build.go @@ -466,8 +466,10 @@ func getMessageHeader(msg proton.Message, opts JobOptions) message.Header { if date, err := rfc5322.ParseDateTime(hdr.Get("Date")); err != nil || date.Before(time.Unix(0, 0)) { msgDate := SanitizeMessageDate(msg.Time) hdr.Set("Date", msgDate.In(time.UTC).Format(time.RFC1123Z)) - // We clobbered the date so we save it under X-Original-Date. - hdr.Set("X-Original-Date", date.In(time.UTC).Format(time.RFC1123Z)) + // We clobbered the date so we save it under X-Original-Date only if no such value exists. + if !hdr.Has("X-Original-Date") { + hdr.Set("X-Original-Date", date.In(time.UTC).Format(time.RFC1123Z)) + } } } diff --git a/pkg/message/build_framework_test.go b/pkg/message/build_framework_test.go index 089d35d4..516e224e 100644 --- a/pkg/message/build_framework_test.go +++ b/pkg/message/build_framework_test.go @@ -38,6 +38,20 @@ func newTestMessage( kr *crypto.KeyRing, messageID, addressID, mimeType, body string, //nolint:unparam date time.Time, +) proton.Message { + return newTestMessageWithHeaders(t, kr, messageID, addressID, mimeType, body, date, nil) +} + +func newRawTestMessage(messageID, addressID, mimeType, body string, date time.Time) proton.Message { // nolint:unparam + return newRawTestMessageWithHeaders(messageID, addressID, mimeType, body, date, nil) +} + +func newTestMessageWithHeaders( + t *testing.T, + kr *crypto.KeyRing, + messageID, addressID, mimeType, body string, //nolint:unparam + date time.Time, + headers map[string][]string, ) proton.Message { enc, err := kr.Encrypt(crypto.NewPlainMessageFromString(body), kr) require.NoError(t, err) @@ -45,22 +59,28 @@ func newTestMessage( arm, err := enc.GetArmored() require.NoError(t, err) - return newRawTestMessage(messageID, addressID, mimeType, arm, date) + return newRawTestMessageWithHeaders(messageID, addressID, mimeType, arm, date, headers) } -func newRawTestMessage(messageID, addressID, mimeType, body string, date time.Time) proton.Message { +func newRawTestMessageWithHeaders(messageID, addressID, mimeType, body string, date time.Time, headers map[string][]string) proton.Message { + msgHeaders := proton.Headers{ + "Content-Type": {mimeType}, + "Date": {date.In(time.UTC).Format(time.RFC1123Z)}, + } + + for k, v := range headers { + msgHeaders[k] = v + } + return proton.Message{ MessageMetadata: proton.MessageMetadata{ ID: messageID, AddressID: addressID, Time: date.Unix(), }, - ParsedHeaders: proton.Headers{ - "Content-Type": {mimeType}, - "Date": {date.In(time.UTC).Format(time.RFC1123Z)}, - }, - MIMEType: rfc822.MIMEType(mimeType), - Body: body, + ParsedHeaders: msgHeaders, + MIMEType: rfc822.MIMEType(mimeType), + Body: body, } } diff --git a/pkg/message/build_test.go b/pkg/message/build_test.go index 26d72ced..41d52936 100644 --- a/pkg/message/build_test.go +++ b/pkg/message/build_test.go @@ -836,6 +836,41 @@ func TestBuildMessageWithInvalidDate(t *testing.T) { expectHeader(`X-Original-Date`, is(`Wed, 31 Dec 1969 23:59:59 +0000`)) } +func TestBuildMessageWithExistingOriginalDate(t *testing.T) { + m := gomock.NewController(t) + defer m.Finish() + + kr := utils.MakeKeyRing(t) + + // Create a new message with existing original date + msg := newTestMessageWithHeaders(t, kr, + "messageID", + "addressID", + "text/html", + "body", + time.Unix(-1, 0), + map[string][]string{ + "X-Original-Date": {"Sun, 15 Jan 2023 04:23:03 +0100 (W. Europe Standard Time)"}, + "Date": {"15-Jan-2023 04:23:13 +0100"}, + }) + + // Build the message as usual; the date will be before 1970. + res, err := BuildRFC822(kr, msg, nil, JobOptions{}) + require.NoError(t, err) + + section(t, res). + expectDate(is(`15-Jan-2023 04:23:13 +0100`)). + expectHeader(`X-Original-Date`, is("Sun, 15 Jan 2023 04:23:03 +0100 (W. Europe Standard Time)")) + + // Build the message with date sanitization enabled; the date will be RFC822's birthdate. + resFix, err := BuildRFC822(kr, msg, nil, JobOptions{SanitizeDate: true}) + require.NoError(t, err) + + section(t, resFix). + expectDate(is(`Fri, 13 Aug 1982 00:00:00 +0000`)). + expectHeader(`X-Original-Date`, is("Sun, 15 Jan 2023 04:23:03 +0100 (W. Europe Standard Time)")) +} + func TestBuildMessageInternalID(t *testing.T) { m := gomock.NewController(t) defer m.Finish() From a3aafabde395398b5b560553f5794672ae4ac8cd Mon Sep 17 00:00:00 2001 From: Jakub Date: Fri, 10 Mar 2023 17:18:03 +0100 Subject: [PATCH 105/130] feat(GODT-2455): upper limit for number of merged events. --- go.mod | 2 +- go.sum | 4 ++-- internal/user/user.go | 6 +++++- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/go.mod b/go.mod index fc84cde9..9deb6745 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.0 github.com/ProtonMail/gluon v0.15.1-0.20230310125443-f755e8ce082a github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.4.1-0.20230228124441-781ee183e1b4 + github.com/ProtonMail/go-proton-api v0.4.1-0.20230313080847-655987fd5899 github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.5.2 github.com/PuerkitoBio/goquery v1.8.1 diff --git a/go.sum b/go.sum index 03381247..526d9a29 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 h1:I8IsYA297 github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 h1:dS7r5z4iGS0qCjM7UwWdsEMzQesUQbGcXdSm2/tWboA= github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230228124441-781ee183e1b4 h1:isPTVpbcwhLB36fcpI9/YzLUi2rapuLsJiHP8GCB5EY= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230228124441-781ee183e1b4/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230313080847-655987fd5899 h1:E4MP+LfriJNfWBbD7Hr2913bEDFFzGei/D9Dh+MB+a0= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230313080847-655987fd5899/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= diff --git a/internal/user/user.go b/internal/user/user.go index 1c163a66..564821f9 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -631,7 +631,7 @@ func (user *User) doEventPoll(ctx context.Context) error { user.eventLock.Lock() defer user.eventLock.Unlock() - event, err := user.client.GetEvent(ctx, user.vault.EventID()) + event, more, err := user.client.GetEvent(ctx, user.vault.EventID()) if err != nil { return fmt.Errorf("failed to get event (caused by %T): %w", internal.ErrCause(err), err) } @@ -719,6 +719,10 @@ func (user *User) doEventPoll(ctx context.Context) error { user.log.WithField("eventID", event.EventID).Debug("Updated event ID in vault") + if more { + user.goPollAPIEvents(false) + } + return nil } From 4273405393e815398551a603d45bde09e84fb2d3 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 13 Mar 2023 16:51:33 +0100 Subject: [PATCH 106/130] chore: Bridge Quebec 3.1.0 - update changelog --- Changelog.md | 39 ++++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/Changelog.md b/Changelog.md index ac3c48f6..9a0ecbda 100644 --- a/Changelog.md +++ b/Changelog.md @@ -8,7 +8,7 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/) * GODT-2224: Refactor bridge sync to use less memory. * GODT-2448: Supported Answered flag. * GODT-2382: Added bridge-gui settings file with 'UseSoftwareRenderer' value. -* GODT-2411: allow qmake executable to be named qmake6. +* GODT-2411: Allow qmake executable to be named qmake6. * GODT-2273: Menu with "Close window" and "Quit Bridge" button in main window. * GODT-2261: Sync progress in GUI. * GODT-2385: Gluon cache fallback. @@ -30,6 +30,10 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/) * GODT-2289: UIDValidity as Timestamp. ### Fixed +* GODT-2455: Upper limit for number of merged events. +* GODT-2480: Do not override X-Original-Date with invalid Date. +* GODT-2473: Fix handling of complex mime types. +* GODT-2469: Fix sentry revision hash for cmake on windows. * GODT-2424: Sync Builder Message Split. * GODT-2419: Use connector.ErrOperationNotAllowed. * GODT-2418: Ensure child folders are updated when parent is. @@ -67,24 +71,25 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/) * GODT-2442: Allow user to re-sync DB without logout. ### Changed -GODT-2419: Reduce sentry reports. -GODT-2458: Wait for both bridge and bridge-gui to be ended before restarting on crash. -GODT-2457: Include address if GetPublickKeys() error message. -GODT-2446: Attach logs to sentry reports for relevant bridge-gui exceptions. -GODT-2425: Out of sync messages and read status. -GODT-2435: Group report exception by message if exception message looks corrupted. -GODT-2356: Unify sentry release description and add more context to it. -GODT-2357: Hide DSN_SENTRY and use single setting point for DSN_SENTRY. -GODT-2444: Bad event info. -GODT-2447: Don't assume timestamp exists in log filename. -GODT-2333: Do not allow modifications to All Mail label. -GODT-2429: Do not report context cancel to sentry. +* GODT-2419: Reduce sentry reports. +* GODT-2458: Wait for both bridge and bridge-gui to be ended before restarting on crash. +* GODT-2457: Include address if GetPublickKeys() error message. +* GODT-2446: Attach logs to sentry reports for relevant bridge-gui exceptions. +* GODT-2425: Out of sync messages and read status. +* GODT-2435: Group report exception by message if exception message looks corrupted. +* GODT-2356: Unify sentry release description and add more context to it. +* GODT-2357: Hide DSN_SENTRY and use single setting point for DSN_SENTRY. +* GODT-2444: Bad event info. +* GODT-2447: Don't assume timestamp exists in log filename. +* GODT-2333: Do not allow modifications to All Mail label. +* GODT-2429: Do not report context cancel to sentry. ### Fixed -GODT-2449: fix bug in Bridge-GUI's Exception::what(). -GODT-2427: Parsing header issues. -GODT-2426: Fix crash on user delete. -GODT-2417: Do not request gluon recovered message from API. +* GODT-2467: elide long email adresses in 'bad event' QML notification dialog. +* GODT-2449: fix bug in Bridge-GUI's Exception::what(). +* GODT-2427: Parsing header issues. +* GODT-2426: Fix crash on user delete. +* GODT-2417: Do not request gluon recovered message from API. ## [Bridge 3.0.19] Perth Narrows From 48274ee17801a35812a59b5827cdcd5bd9f26323 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Mon, 13 Mar 2023 14:55:59 +0100 Subject: [PATCH 107/130] feat(GODT-2482): more attachment to relevant exceptions. --- .../bridge-gui/bridge-gui/LogUtils.cpp | 48 +------------ .../frontend/bridge-gui/bridge-gui/LogUtils.h | 1 - .../bridge-gui/bridge-gui/QMLBackend.cpp | 2 +- .../frontend/bridge-gui/bridge-gui/main.cpp | 18 +++-- .../bridge-gui/bridgepp/CMakeLists.txt | 1 + .../bridgepp/bridgepp/Exception/Exception.h | 4 ++ .../bridgepp/bridgepp/GRPC/GRPCClient.cpp | 27 +++++--- .../bridgepp/bridgepp/Log/LogUtils.cpp | 68 +++++++++++++++++++ .../bridgepp/bridgepp/Log/LogUtils.h | 33 +++++++++ 9 files changed, 135 insertions(+), 67 deletions(-) create mode 100644 internal/frontend/bridge-gui/bridgepp/bridgepp/Log/LogUtils.cpp create mode 100644 internal/frontend/bridge-gui/bridgepp/bridgepp/Log/LogUtils.h diff --git a/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp b/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp index 4964039b..556699a6 100644 --- a/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/LogUtils.cpp @@ -18,26 +18,13 @@ #include "LogUtils.h" #include "BuildConfig.h" +#include #include using namespace bridgepp; -namespace { -qsizetype const logFileTailMaxLength = 25 * 1024; ///< The maximum length of the portion of log returned by tailOfLatestBridgeLog() -} - - -//**************************************************************************************************************************************************** -/// \return user logs directory used by bridge. -//**************************************************************************************************************************************************** -QString userLogsDir() { - QString const path = QDir(bridgepp::userDataDir()).absoluteFilePath("logs"); - QDir().mkpath(path); - return path; -} - //**************************************************************************************************************************************************** /// \return A reference to the log. //**************************************************************************************************************************************************** @@ -69,36 +56,3 @@ Log &initLog() { return log; } - - -//**************************************************************************************************************************************************** -/// \brief Return the path of the latest bridge log. -/// \return The path of the latest bridge log file. -/// \return An empty string if no bridge log file was found. -//**************************************************************************************************************************************************** -QString latestBridgeLogPath() { - QDir const logsDir(userLogsDir()); - if (logsDir.isEmpty()) { - return QString(); - } - QFileInfoList files = logsDir.entryInfoList({ "v*.log" }, QDir::Files); // could do sorting, but only by last modification time. we want to sort by creation time. - std::sort(files.begin(), files.end(), [](QFileInfo const &lhs, QFileInfo const &rhs) -> bool { - return lhs.birthTime() < rhs.birthTime(); - }); - return files.back().absoluteFilePath(); -} - - -//**************************************************************************************************************************************************** -/// Return the maxSize last bytes of the latest bridge log. -//**************************************************************************************************************************************************** -QByteArray tailOfLatestBridgeLog() { - QString path = latestBridgeLogPath(); - if (path.isEmpty()) { - return QByteArray(); - } - - QFile file(path); - return file.open(QIODevice::Text | QIODevice::ReadOnly) ? file.readAll().right(logFileTailMaxLength) : QByteArray(); -} - diff --git a/internal/frontend/bridge-gui/bridge-gui/LogUtils.h b/internal/frontend/bridge-gui/bridge-gui/LogUtils.h index 60e1896d..b324301e 100644 --- a/internal/frontend/bridge-gui/bridge-gui/LogUtils.h +++ b/internal/frontend/bridge-gui/bridge-gui/LogUtils.h @@ -24,7 +24,6 @@ bridgepp::Log &initLog(); ///< Initialize the application log. -QByteArray tailOfLatestBridgeLog(); ///< Return the last bytes of the last bridge log. #endif //BRIDGE_GUI_LOG_UTILS_H diff --git a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp index b0cbad7e..5671245a 100644 --- a/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/QMLBackend.cpp @@ -19,9 +19,9 @@ #include "QMLBackend.h" #include "BuildConfig.h" #include "EventStreamWorker.h" -#include "LogUtils.h" #include #include +#include #include #include #include diff --git a/internal/frontend/bridge-gui/bridge-gui/main.cpp b/internal/frontend/bridge-gui/bridge-gui/main.cpp index 3f7a6a14..b7f3225f 100644 --- a/internal/frontend/bridge-gui/bridge-gui/main.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/main.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include @@ -116,7 +117,7 @@ QQmlComponent *createRootQmlComponent(QQmlApplicationEngine &engine) { rootComponent->loadUrl(QUrl(qrcQmlDir + "/Bridge.qml")); if (rootComponent->status() != QQmlComponent::Status::Ready) { - QString const &err =rootComponent->errorString(); + QString const &err = rootComponent->errorString(); app().log().error(err); throw Exception("Could not load QML component", err); } @@ -211,7 +212,7 @@ void focusOtherInstance() { QString error; if (!client.connectToServer(5000, sc.port, &error)) { - throw Exception(QString("Could not connect to bridge focus service for a raise call: %1").arg(error)); + throw Exception("Could not connect to bridge focus service for a raise call.", error); } if (!client.raise().ok()) { throw Exception(QString("The raise call to the bridge focus service failed.")); @@ -220,7 +221,7 @@ void focusOtherInstance() { catch (Exception const &e) { app().log().error(e.qwhat()); auto uuid = reportSentryException("Exception occurred during focusOtherInstance()", e); - app().log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex()).arg(e.qwhat())); + app().log().fatal(QString("reportID: %1 Captured exception: %2").arg(QByteArray(uuid.bytes, 16).toHex(), e.qwhat())); } } @@ -276,15 +277,12 @@ int main(int argc, char *argv[]) { } BridgeApp guiApp(argc, argv); + initSentry(); + auto sentryCloser = qScopeGuard([] { sentry_close(); }); try { QString const& configDir = bridgepp::userConfigDir(); - // Init sentry. - initSentry(); - - auto sentryClose = qScopeGuard([] { sentry_close(); }); - initQtApplication(); @@ -311,7 +309,7 @@ int main(int argc, char *argv[]) { if (!cliOptions.attach) { if (isBridgeRunning()) { throw Exception("An orphan instance of bridge is already running. Please terminate it and relaunch the application.", - QString(), QString(), tailOfLatestBridgeLog()); + QString(), __FUNCTION__, tailOfLatestBridgeLog()); } // before launching bridge, we remove any trailing service config file, because we need to make sure we get a newly generated one. @@ -345,7 +343,7 @@ int main(int argc, char *argv[]) { std::unique_ptr rootComponent(createRootQmlComponent(engine)); std::unique_ptr rootObject(rootComponent->create(engine.rootContext())); if (!rootObject) { - throw Exception("Could not create root object."); + throw Exception("Could not create QML root object."); } ProcessMonitor *bridgeMonitor = app().bridgeMonitor(); diff --git a/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt b/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt index 3b3ed991..af03519a 100644 --- a/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt +++ b/internal/frontend/bridge-gui/bridgepp/CMakeLists.txt @@ -146,6 +146,7 @@ add_library(bridgepp ${FOCUS_PROTO_CPP_FILE} ${FOCUS_PROTO_H_FILE} ${FOCUS_GRPC_CPP_FILE} ${FOCUS_GRPC_H_FILE} bridgepp/FocusGRPC/FocusGRPCClient.cpp bridgepp/FocusGRPC/FocusGRPCClient.h bridgepp/Log/Log.h bridgepp/Log/Log.cpp + bridgepp/Log/LogUtils.h bridgepp/Log/LogUtils.cpp bridgepp/ProcessMonitor.cpp bridgepp/ProcessMonitor.h bridgepp/User/User.cpp bridgepp/User/User.h bridgepp/Worker/Worker.h bridgepp/Worker/Overseer.h bridgepp/Worker/Overseer.cpp) diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h index dad9a867..21a1689d 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Exception/Exception.h @@ -23,6 +23,7 @@ #include + namespace bridgepp { @@ -44,6 +45,9 @@ public: // member functions QByteArray attachment() const noexcept; ///< Return the attachment for the exception. QString detailedWhat() const; ///< Return the detailed description of the message (i.e. including the function name and the details). +public: // static data members + static qsizetype const attachmentMaxLength {25 * 1024}; ///< The maximum length text attachment sent in Sentry reports, in bytes. + private: // data members QString const qwhat_; ///< The description of the exception. QByteArray const what_; ///< The c-string version of the qwhat message. Stored as a QByteArray for automatic lifetime management. diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp index 22b4a376..350b78bd 100644 --- a/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/GRPC/GRPCClient.cpp @@ -22,6 +22,7 @@ #include "../BridgeUtils.h" #include "../Exception/Exception.h" #include "../ProcessMonitor.h" +#include "../Log/LogUtils.h" using namespace google::protobuf; @@ -70,7 +71,8 @@ GRPCConfig GRPCClient::waitAndRetrieveServiceConfig(QString const &configDir, qi bool found = false; while (true) { if (serverProcess && serverProcess->getStatus().ended) { - throw Exception("Bridge application exited before providing a gRPC service configuration file."); + throw Exception("Bridge application exited before providing a gRPC service configuration file.", QString(), __FUNCTION__, + tailOfLatestBridgeLog()); } if (file.exists()) { @@ -84,13 +86,20 @@ GRPCConfig GRPCClient::waitAndRetrieveServiceConfig(QString const &configDir, qi } if (!found) { - throw Exception("Server did not provide gRPC service configuration in time."); + throw Exception("Server did not provide gRPC service configuration in time.", QString(), __FUNCTION__, tailOfLatestBridgeLog()); } GRPCConfig sc; QString err; if (!sc.load(path, &err)) { - throw Exception("The gRPC service configuration file is invalid.", err); + // include the file content in the exception, if any + QByteArray array; + if (file.open(QIODevice::ReadOnly | QIODevice::Text)) { + file.readAll(); + array = array.right(Exception::attachmentMaxLength); + } + + throw Exception("The gRPC service configuration file is invalid.", err, __FUNCTION__, array); } return sc; @@ -126,19 +135,20 @@ void GRPCClient::connectToServer(QString const &configDir, GRPCConfig const &con channel_ = CreateCustomChannel(address.toStdString(), grpc::SslCredentials(opts), chanArgs); if (!channel_) { - throw Exception("Channel creation failed."); + throw Exception("gRPC channel creation failed."); } stub_ = Bridge::NewStub(channel_); if (!stub_) { - throw Exception("Stub creation failed."); + throw Exception("gRPC stub creation failed."); } QDateTime const giveUpTime = QDateTime::currentDateTime().addMSecs(grpcConnectionWaitTimeoutMs); // if we reach giveUpTime without connecting, we give up int i = 0; while (true) { if (serverProcess && serverProcess->getStatus().ended) { - throw Exception("Bridge application ended before gRPC connexion could be established."); + throw Exception("Bridge application ended before gRPC connexion could be established.", QString(), __FUNCTION__, + tailOfLatestBridgeLog()); } this->logInfo(QString("Connection to gRPC server at %1. attempt #%2").arg(address).arg(++i)); @@ -148,7 +158,8 @@ void GRPCClient::connectToServer(QString const &configDir, GRPCConfig const &con } // connection established. if (QDateTime::currentDateTime() > giveUpTime) { - throw Exception("Connection to the RPC server failed."); + throw Exception("Connection to the gRPC server failed because of a timeout.", QString(), __FUNCTION__, + tailOfLatestBridgeLog()); } } @@ -180,7 +191,7 @@ void GRPCClient::connectToServer(QString const &configDir, GRPCConfig const &con log_->info("gRPC token was validated"); } catch (Exception const &e) { - throw Exception("Cannot connect to Go backend via gRPC: " + e.qwhat(), e.details()); + throw Exception("Cannot connect to Go backend via gRPC: " + e.qwhat(), e.details(), __FUNCTION__, e.attachment()); } } diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Log/LogUtils.cpp b/internal/frontend/bridge-gui/bridgepp/bridgepp/Log/LogUtils.cpp new file mode 100644 index 00000000..ee3780b2 --- /dev/null +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Log/LogUtils.cpp @@ -0,0 +1,68 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + + +#include "LogUtils.h" +#include +#include + + +namespace bridgepp { + + +//**************************************************************************************************************************************************** +/// \return user logs directory used by bridge. +//**************************************************************************************************************************************************** +QString userLogsDir() { + QString const path = QDir(bridgepp::userDataDir()).absoluteFilePath("logs"); + QDir().mkpath(path); + return path; +} + +//**************************************************************************************************************************************************** +/// \brief Return the path of the latest bridge log. +/// \return The path of the latest bridge log file. +/// \return An empty string if no bridge log file was found. +//**************************************************************************************************************************************************** +QString latestBridgeLogPath() { + QDir const logsDir(userLogsDir()); + if (logsDir.isEmpty()) { + return QString(); + } + QFileInfoList files = logsDir.entryInfoList({ "v*.log" }, QDir::Files); // could do sorting, but only by last modification time. we want to sort by creation time. + std::sort(files.begin(), files.end(), [](QFileInfo const &lhs, QFileInfo const &rhs) -> bool { + return lhs.birthTime() < rhs.birthTime(); + }); + return files.back().absoluteFilePath(); +} + + +//**************************************************************************************************************************************************** +/// Return the maxSize last bytes of the latest bridge log. +//**************************************************************************************************************************************************** +QByteArray tailOfLatestBridgeLog() { + QString path = latestBridgeLogPath(); + if (path.isEmpty()) { + return QByteArray(); + } + + QFile file(path); + return file.open(QIODevice::Text | QIODevice::ReadOnly) ? file.readAll().right(Exception::attachmentMaxLength) : QByteArray(); +} + + +} // namespace bridgepp diff --git a/internal/frontend/bridge-gui/bridgepp/bridgepp/Log/LogUtils.h b/internal/frontend/bridge-gui/bridgepp/bridgepp/Log/LogUtils.h new file mode 100644 index 00000000..2918cd15 --- /dev/null +++ b/internal/frontend/bridge-gui/bridgepp/bridgepp/Log/LogUtils.h @@ -0,0 +1,33 @@ +// Copyright (c) 2023 Proton AG +// +// This file is part of Proton Mail Bridge. +// +// Proton Mail Bridge is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Proton Mail Bridge is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Proton Mail Bridge. If not, see . + + +#ifndef BRIDGE_PP_LOG_UTILS_H +#define BRIDGE_PP_LOG_UTILS_H + + +namespace bridgepp { + + +QString userLogsDir(); ///< Return the path of the user logs dir. +QByteArray tailOfLatestBridgeLog(); ///< Return the last bytes of the last bridge log. + + +} // namespace bridgepp + + +#endif //BRIDGE_PP_LOG_UTILS_H From 8b33d56b592c77643a532b8723d38cf6fbaa2b06 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Tue, 14 Mar 2023 10:34:03 +0100 Subject: [PATCH 108/130] fix(GODT-2479): Ensure messages always have a text body part Proton Backend requires that all messages have at least one text/plain or text/html body part, even if it is empty. --- internal/bridge/send_test.go | 179 +++++++++++++++++++++++++++++++++++ internal/bridge/sync_test.go | 7 +- internal/user/smtp.go | 4 + pkg/message/parser/parser.go | 34 +++++++ 4 files changed, 222 insertions(+), 2 deletions(-) diff --git a/internal/bridge/send_test.go b/internal/bridge/send_test.go index b9e6e0ca..c3b5e1ca 100644 --- a/internal/bridge/send_test.go +++ b/internal/bridge/send_test.go @@ -330,3 +330,182 @@ func TestBridge_SendInvite(t *testing.T) { }) }) } + +func TestBridge_SendAddTextBodyPartIfNotExists(t *testing.T) { + const messageMultipartWithoutText = `Content-Type: multipart/mixed; + boundary="Apple-Mail=_E7AC06C7-4EB2-4453-8CBB-80F4412A7C84" +Subject: A new message +Date: Mon, 13 Mar 2023 16:06:16 +0100 + + +--Apple-Mail=_E7AC06C7-4EB2-4453-8CBB-80F4412A7C84 +Content-Disposition: inline; + filename=Cat_August_2010-4.jpeg +Content-Type: image/jpeg; + name="Cat_August_2010-4.jpeg" +Content-Transfer-Encoding: base64 + +SGVsbG8gd29ybGQ= + +--Apple-Mail=_E7AC06C7-4EB2-4453-8CBB-80F4412A7C84-- + ` + + const messageMultipartWithText = `Content-Type: multipart/mixed; + boundary="Apple-Mail=_E7AC06C7-4EB2-4453-8CBB-80F4412A7C84" +Subject: A new message Part2 +Date: Mon, 13 Mar 2023 16:06:16 +0100 + +--Apple-Mail=_E7AC06C7-4EB2-4453-8CBB-80F4412A7C84 +Content-Disposition: inline; + filename=Cat_August_2010-4.jpeg +Content-Type: image/jpeg; + name="Cat_August_2010-4.jpeg" +Content-Transfer-Encoding: base64 + +SGVsbG8gd29ybGQ= + +--Apple-Mail=_E7AC06C7-4EB2-4453-8CBB-80F4412A7C84 +Content-Type: text/html;charset=utf8 +Content-Transfer-Encoding: quoted-printable + +Hello world + +--Apple-Mail=_E7AC06C7-4EB2-4453-8CBB-80F4412A7C84-- +` + + const messageWithTextOnly = `Content-Type: text/plain;charset=utf8 +Content-Transfer-Encoding: quoted-printable +Subject: A new message Part3 +Date: Mon, 13 Mar 2023 16:06:16 +0100 + +Hello world + +` + + const messageMultipartWithoutTextWithTextAttachment = `Content-Type: multipart/mixed; + boundary="Apple-Mail=_E7AC06C7-4EB2-4453-8CBB-80F4412A7C84" +Subject: A new message Part4 +Date: Mon, 13 Mar 2023 16:06:16 +0100 + +--Apple-Mail=_E7AC06C7-4EB2-4453-8CBB-80F4412A7C84 +Content-Type: text/plain; charset=UTF-8; name="text.txt" +Content-Disposition: attachment; filename="text.txt" +Content-Transfer-Encoding: base64 + +SGVsbG8gd29ybGQK + +--Apple-Mail=_E7AC06C7-4EB2-4453-8CBB-80F4412A7C84-- +` + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + _, _, err := s.CreateUser("recipient", password) + require.NoError(t, err) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, _ *bridge.Mocks) { + senderUserID, err := bridge.LoginFull(ctx, username, password, nil, nil) + require.NoError(t, err) + + recipientUserID, err := bridge.LoginFull(ctx, "recipient", password, nil, nil) + require.NoError(t, err) + + senderInfo, err := bridge.GetUserInfo(senderUserID) + require.NoError(t, err) + + recipientInfo, err := bridge.GetUserInfo(recipientUserID) + require.NoError(t, err) + + messages := []string{ + messageMultipartWithoutText, + messageMultipartWithText, + messageWithTextOnly, + messageMultipartWithoutTextWithTextAttachment, + } + + for _, m := range messages { + // Dial the server. + client, err := smtp.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetSMTPPort()))) + require.NoError(t, err) + defer client.Close() //nolint:errcheck + + // Upgrade to TLS. + require.NoError(t, client.StartTLS(&tls.Config{InsecureSkipVerify: true})) + + // Authorize with SASL LOGIN. + require.NoError(t, client.Auth(sasl.NewLoginClient( + senderInfo.Addresses[0], + string(senderInfo.BridgePass)), + )) + + // Send the message. + require.NoError(t, client.SendMail( + senderInfo.Addresses[0], + []string{recipientInfo.Addresses[0]}, + strings.NewReader(m), + )) + } + + // Connect the sender IMAP client. + senderIMAPClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort()))) + require.NoError(t, err) + require.NoError(t, senderIMAPClient.Login(senderInfo.Addresses[0], string(senderInfo.BridgePass))) + defer senderIMAPClient.Logout() //nolint:errcheck + + // Connect the recipient IMAP client. + recipientIMAPClient, err := client.Dial(net.JoinHostPort(constants.Host, fmt.Sprint(bridge.GetIMAPPort()))) + require.NoError(t, err) + require.NoError(t, recipientIMAPClient.Login(recipientInfo.Addresses[0], string(recipientInfo.BridgePass))) + defer recipientIMAPClient.Logout() //nolint:errcheck + + require.Eventually(t, func() bool { + messages, err := clientFetch(senderIMAPClient, `Sent`, imap.FetchBodyStructure) + require.NoError(t, err) + require.Equal(t, 4, len(messages)) + + // messages may not be in order + for _, message := range messages { + switch { + case message.Envelope.Subject == "A new message": + // The message that was sent should now include an empty text/plain body part since there was none + // in the original message. + require.Equal(t, 2, len(message.BodyStructure.Parts)) + + require.Equal(t, "text", message.BodyStructure.Parts[0].MIMEType) + require.Equal(t, "plain", message.BodyStructure.Parts[0].MIMESubType) + require.Equal(t, uint32(0), message.BodyStructure.Parts[0].Size) + require.Equal(t, "image", message.BodyStructure.Parts[1].MIMEType) + require.Equal(t, "jpeg", message.BodyStructure.Parts[1].MIMESubType) + + case message.Envelope.Subject == "A new message Part2": + // This message already has a text body, should be unchanged + require.Equal(t, 2, len(message.BodyStructure.Parts)) + + require.Equal(t, "image", message.BodyStructure.Parts[1].MIMEType) + require.Equal(t, "jpeg", message.BodyStructure.Parts[1].MIMESubType) + require.Equal(t, "text", message.BodyStructure.Parts[0].MIMEType) + require.Equal(t, "html", message.BodyStructure.Parts[0].MIMESubType) + + case message.Envelope.Subject == "A new message Part3": + // This message already has a text body, should be unchanged + require.Equal(t, 0, len(message.BodyStructure.Parts)) + + require.Equal(t, "text", message.BodyStructure.MIMEType) + require.Equal(t, "plain", message.BodyStructure.MIMESubType) + + case message.Envelope.Subject == "A new message Part4": + // The message that was sent should now include an empty text/plain body part since even though + // there was only a text/plain attachment in the original message. + require.Equal(t, 2, len(message.BodyStructure.Parts)) + + require.Equal(t, "text", message.BodyStructure.Parts[0].MIMEType) + require.Equal(t, "plain", message.BodyStructure.Parts[0].MIMESubType) + require.Equal(t, uint32(0), message.BodyStructure.Parts[0].Size) + require.Equal(t, "text", message.BodyStructure.Parts[1].MIMEType) + require.Equal(t, "plain", message.BodyStructure.Parts[1].MIMESubType) + require.Equal(t, "attachment", message.BodyStructure.Parts[1].Disposition) + } + } + + return true + }, 10*time.Second, 100*time.Millisecond) + }) + }) +} diff --git a/internal/bridge/sync_test.go b/internal/bridge/sync_test.go index 329a42c5..182986c2 100644 --- a/internal/bridge/sync_test.go +++ b/internal/bridge/sync_test.go @@ -351,7 +351,7 @@ func withClient(ctx context.Context, t *testing.T, s *server.Server, username st fn(ctx, c) } -func clientFetch(client *client.Client, mailbox string) ([]*imap.Message, error) { +func clientFetch(client *client.Client, mailbox string, extraItems ...imap.FetchItem) ([]*imap.Message, error) { status, err := client.Select(mailbox, false) if err != nil { return nil, err @@ -363,10 +363,13 @@ func clientFetch(client *client.Client, mailbox string) ([]*imap.Message, error) resCh := make(chan *imap.Message) + fetchItems := []imap.FetchItem{imap.FetchFlags, imap.FetchEnvelope, imap.FetchUid, imap.FetchBodyStructure, "BODY.PEEK[]"} + fetchItems = append(fetchItems, extraItems...) + go func() { if err := client.Fetch( &imap.SeqSet{Set: []imap.Seq{{Start: 1, Stop: status.Messages}}}, - []imap.FetchItem{imap.FetchFlags, imap.FetchEnvelope, imap.FetchUid, "BODY.PEEK[]"}, + fetchItems, resCh, ); err != nil { panic(err) diff --git a/internal/user/smtp.go b/internal/user/smtp.go index 0fb6fafd..1a0dd706 100644 --- a/internal/user/smtp.go +++ b/internal/user/smtp.go @@ -117,6 +117,10 @@ func (user *User) sendMail(authID string, from string, to []string, r io.Reader) return fmt.Errorf("failed to get first key: %w", err) } + // Ensure that there is always a text/html or text/plain body part. This is required by the API. If none + // exists and empty text part will be added. + parser.AttachEmptyTextPartIfNoneExists() + // If we have to attach the public key, do it now. if settings.AttachPublicKey { key, err := addrKR.GetKey(0) diff --git a/pkg/message/parser/parser.go b/pkg/message/parser/parser.go index 8266f6fb..e911c76b 100644 --- a/pkg/message/parser/parser.go +++ b/pkg/message/parser/parser.go @@ -20,6 +20,7 @@ package parser import ( "fmt" "io" + "strings" "github.com/emersion/go-message" "github.com/sirupsen/logrus" @@ -81,6 +82,39 @@ func (p *Parser) AttachPublicKey(key, keyName string) { }) } +func (p *Parser) AttachEmptyTextPartIfNoneExists() { + root := p.Root() + if root.isMultipartMixed() { + for _, v := range root.children { + // Must be an attachment of sorts, skip. + if v.Header.Has("Content-Disposition") { + continue + } + contentType, _, err := v.Header.ContentType() + if err == nil && strings.HasPrefix(contentType, "text/") { + // Message already has text part + return + } + } + } else { + contentType, _, err := root.Header.ContentType() + if err == nil && strings.HasPrefix(contentType, "text/") { + // Message already has text part + return + } + } + + h := message.Header{} + + h.Set("Content-Type", "text/plain;charset=utf8") + h.Set("Content-Transfer-Encoding", "quoted-printable") + + p.Root().AddChild(&Part{ + Header: h, + Body: nil, + }) +} + // Section returns the message part referred to by the given section. A section // is zero or more integers. For example, section 1.2.3 will return the third // part of the second part of the first part of the message. From e36c2b3d6e0c236772041f235e4379704fd604c5 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Tue, 14 Mar 2023 15:47:48 +0100 Subject: [PATCH 109/130] chore: Update GPA to include detailed error messages https://github.com/ProtonMail/go-proton-api/pull/62 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1f0703ab..06511858 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.0 github.com/ProtonMail/gluon v0.15.1-0.20230310125443-f755e8ce082a github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.4.1-0.20230313102028-4da9318e5f77 + github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739 github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.5.2 github.com/PuerkitoBio/goquery v1.8.1 diff --git a/go.sum b/go.sum index 951e343d..9dee4d92 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 h1:I8IsYA297 github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 h1:dS7r5z4iGS0qCjM7UwWdsEMzQesUQbGcXdSm2/tWboA= github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230313102028-4da9318e5f77 h1:/BZaVBC2s3Q/0Z++vZ5hJsijOwy2HgK2cVVwxRCjLQs= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230313102028-4da9318e5f77/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739 h1:sJhJQKQcG06mDcqikvLLnMuTz2rngcGTiTvOnc7lQbU= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= From 212eac09257eb24032eb233a0d40a667f8b70fee Mon Sep 17 00:00:00 2001 From: Jakub Date: Wed, 15 Mar 2023 07:17:47 +0100 Subject: [PATCH 110/130] chore: Bridge Quebec 3.1.0 - update changelog --- Changelog.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Changelog.md b/Changelog.md index 9a0ecbda..ece5dbb2 100644 --- a/Changelog.md +++ b/Changelog.md @@ -5,6 +5,9 @@ Changelog [format](http://keepachangelog.com/en/1.0.0/) ## [Bridge 3.1.0] Quebec ### Changed +* Update GPA to include detailed error messages. +* GODT-2479: Ensure messages always have a text body part. +* GODT-2482: More attachment to relevant exceptions. * GODT-2224: Refactor bridge sync to use less memory. * GODT-2448: Supported Answered flag. * GODT-2382: Added bridge-gui settings file with 'UseSoftwareRenderer' value. From 31de358bfd337624b4242f8df0289800747154fd Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 13 Mar 2023 21:26:45 +0100 Subject: [PATCH 111/130] feat(GODT-2487): add windows test job and worker. --- .gitlab-ci.yml | 122 ++++++++++++++--------------- internal/versioner/version_test.go | 2 + 2 files changed, 63 insertions(+), 61 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5cf27441..ddb16c05 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -87,49 +87,62 @@ lint: tags: - medium -test-linux: + +.test-base: stage: test - extends: - - .rules-branch-manual-MR-and-devel-always - - .after-script-code-coverage script: - make test + +test-linux: + extends: + - .test-base + - .rules-branch-manual-MR-and-devel-always + - .after-script-code-coverage tags: - medium test-linux-race: - stage: test extends: + - test-linux - .rules-branch-and-MR-manual script: - make test-race - tags: - - medium test-integration: - stage: test extends: - - .rules-branch-manual-MR-always + - test-linux script: - make test-integration tags: - large test-integration-race: - stage: test extends: + - test-integration - .rules-branch-and-MR-manual script: - make test-integration-race - tags: - - large -dependency-updates: + +.windows-base: + before_script: + - export GOROOT=/c/Go1.18 + - export PATH=$GOROOT/bin:$PATH + - export GOARCH=amd64 + - export GOPATH=~/go18 + - export GO111MODULE=on + - export PATH=$GOPATH/bin:$PATH + - export MSYSTEM= + tags: + - windows-bridge + +test-windows: + extends: + - .rules-branch-manual-MR-always + - .windows-base stage: test script: - - make updates - - + - make test # Stage: BUILD @@ -145,31 +158,20 @@ dependency-updates: when: manual allow_failure: true - when: never - before_script: - - mkdir -p .cache/bin - - export PATH=$(pwd)/.cache/bin:$PATH - - export GOPATH="$CI_PROJECT_DIR/.cache" - - export PATH=$PATH:$QT6DIR/bin - - $(git config --global -l | grep -o 'url.*gitlab.protontech.ch.*insteadof' | xargs -L 1 git config --global --unset &> /dev/null) || echo "nothing to remove" - - git config --global url.https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}.insteadOf https://${CI_SERVER_HOST} script: - make build - git diff && git diff-index --quiet HEAD - make vault-editor artifacts: - # Note: The latest artifacts for refs are locked against deletion, and kept - # regardless of the expiry time. Introduced in GitLab 13.0 behind a - # disabled feature flag, and made the default behavior in GitLab 13.4. expire_in: 1 day when: always + name: "$CI_JOB_NAME-$CI_COMMIT_SHORT_SHA" paths: - bridge_*.tgz - vault-editor - tags: - - large -build-linux: - extends: .build-base + +.linux-build-setup: image: gitlab.protontech.ch:4567/go/bridge-internal:qt6 variables: VCPKG_DEFAULT_BINARY_CACHE: ${CI_PROJECT_DIR}/.cache @@ -178,19 +180,29 @@ build-linux: paths: - .cache when: 'always' - artifacts: - name: "bridge-linux-$CI_COMMIT_SHORT_SHA" + before_script: + - mkdir -p .cache/bin + - export PATH=$(pwd)/.cache/bin:$PATH + - export GOPATH="$CI_PROJECT_DIR/.cache" + - export PATH=$PATH:$QT6DIR/bin + - $(git config --global -l | grep -o 'url.*gitlab.protontech.ch.*insteadof' | xargs -L 1 git config --global --unset &> /dev/null) || echo "nothing to remove" + - git config --global url.https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}.insteadOf https://${CI_SERVER_HOST} + tags: + - large + +build-linux: + extends: + - .build-base + - .linux-build-setup build-linux-qa: - extends: build-linux + extends: + - build-linux variables: BUILD_TAGS: "build_qa" - artifacts: - name: "bridge-linux-qa-$CI_COMMIT_SHORT_SHA" -.build-darwin-base: - extends: .build-base +.darwin-build-setup: before_script: - export PATH=/usr/local/bin:$PATH - export PATH=/usr/local/opt/git/bin:$PATH @@ -202,30 +214,22 @@ build-linux-qa: - export CGO_CPPFLAGS='-Wno-error -Wno-nullability-completeness -Wno-expansion-to-defined -Wno-builtin-requires-header' - $(git config --global -l | grep -o 'url.*gitlab.protontech.ch.*insteadof' | xargs -L 1 git config --global --unset &> /dev/null) || echo "nothing to remove" - git config --global url.https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}.insteadOf https://${CI_SERVER_HOST} - script: - - go version - - make build-nogui - - git diff && git diff-index --quiet HEAD - - make vault-editor cache: {} tags: - macOS build-darwin: - extends: .build-darwin-base - artifacts: - name: "bridge-darwin-$CI_COMMIT_SHORT_SHA" + extends: + - .build-base + - .darwin-build-setup build-darwin-qa: - extends: .build-darwin-base + extends: + - build-darwin variables: BUILD_TAGS: "build_qa" - artifacts: - name: "bridge-darwin-qa-$CI_COMMIT_SHORT_SHA" - -.build-windows-base: - extends: .build-base +.windows-build-setup: before_script: - export GOROOT=/c/Go1.18/ - export PATH=$GOROOT/bin:$PATH @@ -239,23 +243,19 @@ build-darwin-qa: - export PATH="/c/Program Files/Microsoft Visual Studio/2022/Community/Common7/IDE/CommonExtensions/Microsoft/CMake/CMake/bin:$PATH" - $(git config --global -l | grep -o 'url.*gitlab.protontech.ch.*insteadof' | xargs -L 1 git config --global --unset &> /dev/null) || echo "nothing to remove" - git config --global url.https://gitlab-ci-token:${CI_JOB_TOKEN}@${CI_SERVER_HOST}.insteadOf https://${CI_SERVER_HOST} - script: - - make build-nogui - - git diff && git diff-index --quiet HEAD - - make vault-editor + cache: {} tags: - windows-bridge build-windows: - extends: .build-windows-base - artifacts: - name: "bridge-windows-$CI_COMMIT_SHORT_SHA" + extends: + - .build-base + - .windows-build-setup build-windows-qa: - extends: .build-windows-base + extends: + - build-windows variables: BUILD_TAGS: "build_qa" - artifacts: - name: "bridge-windows-qa-$CI_COMMIT_SHORT_SHA" # TODO: PUT BACK ALL THE JOBS! JUST DID THIS FOR NOW TO GET CI WORKING AGAIN... diff --git a/internal/versioner/version_test.go b/internal/versioner/version_test.go index 26f61718..710c3f09 100644 --- a/internal/versioner/version_test.go +++ b/internal/versioner/version_test.go @@ -109,6 +109,8 @@ func createSignedFiles(t *testing.T, root string, paths ...string) *crypto.KeyRi signFile(t, sumFile.Name(), kr) + require.NoError(t, sumFile.Close()) + return kr } From f71a89c265a14e39f6553233aaf6529b4a548f83 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Thu, 16 Mar 2023 11:11:29 +0100 Subject: [PATCH 112/130] fix(GODT-2481): Fix DBUS Secert Service Fix the path we are checking for was not updated for V3. Ensure that we only inspect items that start with the correct prefix. Some implementation (e.g.: KeepassXC) return some values which are not valid. Finally, remove unnecessary attributes. --- pkg/keychain/helper_dbus_linux.go | 26 ++++++++++++++++---------- 1 file changed, 16 insertions(+), 10 deletions(-) diff --git a/pkg/keychain/helper_dbus_linux.go b/pkg/keychain/helper_dbus_linux.go index b759c7f4..bdd1f53e 100644 --- a/pkg/keychain/helper_dbus_linux.go +++ b/pkg/keychain/helper_dbus_linux.go @@ -20,6 +20,8 @@ package keychain import ( "strings" + "github.com/ProtonMail/proton-bridge/v3/internal/constants" + "github.com/bradenaw/juniper/xslices" "github.com/docker/docker-credential-helpers/credentials" "github.com/godbus/dbus" "github.com/keybase/go-keychain/secretservice" @@ -30,10 +32,13 @@ const ( labelAtt = "label" usernameAtt = "username" - defaulDomain = "protonmail/bridge/users/" - defaultLabel = "Docker Credentials" + defaultLabel = "Proton Mail Bridge Credentials" ) +func getDomain() string { + return hostURL(constants.KeyChainName) +} + func getSession() (*secretservice.SecretService, *secretservice.Session, error) { service, err := secretservice.NewService() if err != nil { @@ -73,8 +78,9 @@ func getItems(service *secretservice.SecretService, attributes map[string]string if err != nil { return nil, err } - - return items, err + return xslices.Filter(items, func(t dbus.ObjectPath) bool { + return strings.HasPrefix(string(t), "/org/freedesktop/secrets") + }), err } func unlock(service *secretservice.SecretService) error { @@ -105,11 +111,9 @@ func (s *SecretServiceDBusHelper) Add(creds *credentials.Credentials) error { } attributes := map[string]string{ - usernameAtt: creds.Username, - serverAtt: creds.ServerURL, - labelAtt: defaultLabel, - "xdg:schema": "io.docker.Credentials", - "docker_cli": "1", + usernameAtt: creds.Username, + serverAtt: creds.ServerURL, + labelAtt: defaultLabel, } return handleTimeout(func() error { @@ -203,13 +207,15 @@ func (s *SecretServiceDBusHelper) List() (map[string]string, error) { return nil, err } + defaultDomain := getDomain() + for _, it := range items { attributes, err := service.GetAttributes(it) if err != nil { return nil, err } - if !strings.HasPrefix(attributes[serverAtt], defaulDomain) { + if !strings.HasPrefix(attributes[serverAtt], defaultDomain) { continue } From dd7c81ca4bfa63cbf1f8a7fb5a64968d72d9e492 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Thu, 16 Mar 2023 14:37:50 +0100 Subject: [PATCH 113/130] fix(GODT-2497): Do not report EOF and network errors --- internal/user/user.go | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/internal/user/user.go b/internal/user/user.go index 168967ef..2d0769cb 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -678,11 +678,6 @@ func (user *User) doEventPoll(ctx context.Context) error { // Catch all for uncategorized net errors that may slip through. if netErr := new(net.OpError); errors.As(err, &netErr) { - user.eventCh.Enqueue(events.UncategorizedEventError{ - UserID: user.ID(), - Error: err, - }) - return fmt.Errorf("failed to handle event due to network issues (uncategorized): %w", err) } @@ -698,11 +693,6 @@ func (user *User) doEventPoll(ctx context.Context) error { // If the error is an unexpected EOF, return error to retry later. if errors.Is(err, io.ErrUnexpectedEOF) { - user.eventCh.Enqueue(events.UncategorizedEventError{ - UserID: user.ID(), - Error: err, - }) - return fmt.Errorf("failed to handle event due to EOF: %w", err) } From ec351330f13e63ff3c3ff757810f64af25ca86a6 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Fri, 17 Mar 2023 15:23:22 +0100 Subject: [PATCH 114/130] chore: Replace go-rfc5322 with gluon's rfc5322 parser Bumps Gluon version in order to get the fixes from https://github.com/ProtonMail/gluon/pull/327. --- COPYING_NOTES.md | 2 -- go.mod | 4 +--- go.sum | 9 ++------- internal/user/smtp.go | 2 +- pkg/message/build.go | 2 +- pkg/message/parser.go | 2 +- tests/ctx_test.go | 22 ++++++++++++++++++++++ tests/environment_test.go | 3 ++- 8 files changed, 30 insertions(+), 16 deletions(-) diff --git a/COPYING_NOTES.md b/COPYING_NOTES.md index 171fa8fd..94fac254 100644 --- a/COPYING_NOTES.md +++ b/COPYING_NOTES.md @@ -26,7 +26,6 @@ Proton Mail Bridge includes the following 3rd party software: * [gluon](https://github.com/ProtonMail/gluon) available under [license](https://github.com/ProtonMail/gluon/blob/master/LICENSE) * [go-autostart](https://github.com/ProtonMail/go-autostart) available under [license](https://github.com/ProtonMail/go-autostart/blob/master/LICENSE) * [go-proton-api](https://github.com/ProtonMail/go-proton-api) available under [license](https://github.com/ProtonMail/go-proton-api/blob/master/LICENSE) -* [go-rfc5322](https://github.com/ProtonMail/go-rfc5322) available under [license](https://github.com/ProtonMail/go-rfc5322/blob/master/LICENSE) * [gopenpgp](https://github.com/ProtonMail/gopenpgp/v2) available under [license](https://github.com/ProtonMail/gopenpgp/v2/blob/master/LICENSE) * [goquery](https://github.com/PuerkitoBio/goquery) available under [license](https://github.com/PuerkitoBio/goquery/blob/master/LICENSE) * [ishell](https://github.com/abiosoft/ishell) available under [license](https://github.com/abiosoft/ishell/blob/master/LICENSE) @@ -77,7 +76,6 @@ Proton Mail Bridge includes the following 3rd party software: * [readline](https://github.com/abiosoft/readline) available under [license](https://github.com/abiosoft/readline/blob/master/LICENSE) * [levenshtein](https://github.com/agext/levenshtein) available under [license](https://github.com/agext/levenshtein/blob/master/LICENSE) * [cascadia](https://github.com/andybalholm/cascadia) available under [license](https://github.com/andybalholm/cascadia/blob/master/LICENSE) -* [antlr](https://github.com/antlr/antlr4/runtime/Go/antlr) available under [license](https://github.com/antlr/antlr4/runtime/Go/antlr/blob/master/LICENSE) * [go-textseg](https://github.com/apparentlymart/go-textseg/v13) available under [license](https://github.com/apparentlymart/go-textseg/v13/blob/master/LICENSE) * [sonic](https://github.com/bytedance/sonic) available under [license](https://github.com/bytedance/sonic/blob/master/LICENSE) * [base64x](https://github.com/chenzhuoyu/base64x) available under [license](https://github.com/chenzhuoyu/base64x/blob/master/LICENSE) diff --git a/go.mod b/go.mod index 06511858..372279e7 100644 --- a/go.mod +++ b/go.mod @@ -5,10 +5,9 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.2.0 - github.com/ProtonMail/gluon v0.15.1-0.20230310125443-f755e8ce082a + github.com/ProtonMail/gluon v0.15.1-0.20230317141727-9f7c827f39d2 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739 - github.com/ProtonMail/go-rfc5322 v0.11.0 github.com/ProtonMail/gopenpgp/v2 v2.5.2 github.com/PuerkitoBio/goquery v1.8.1 github.com/abiosoft/ishell v2.0.0+incompatible @@ -62,7 +61,6 @@ require ( github.com/abiosoft/readline v0.0.0-20180607040430-155bce2042db // indirect github.com/agext/levenshtein v1.2.3 // indirect github.com/andybalholm/cascadia v1.3.1 // indirect - github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 // indirect github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect github.com/bytedance/sonic v1.8.1 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect diff --git a/go.sum b/go.sum index 9dee4d92..c024b799 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.15.1-0.20230310125443-f755e8ce082a h1:o7gQKDCJMYju8svD4ufB/YfcUcWUPfQjau3MDNF2dQQ= -github.com/ProtonMail/gluon v0.15.1-0.20230310125443-f755e8ce082a/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230317141727-9f7c827f39d2 h1:WT74oKGqW6gCvzXUvgTK4LarotUvyBz9YsNJqftAO74= +github.com/ProtonMail/gluon v0.15.1-0.20230317141727-9f7c827f39d2/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= @@ -42,8 +42,6 @@ github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 h1:dS7r5z4iGS0q github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739 h1:sJhJQKQcG06mDcqikvLLnMuTz2rngcGTiTvOnc7lQbU= github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= -github.com/ProtonMail/go-rfc5322 v0.11.0 h1:o5Obrm4DpmQEffvgsVqG6S4BKwC1Wat+hYwjIp2YcCY= -github.com/ProtonMail/go-rfc5322 v0.11.0/go.mod h1:6oOKr0jXvpoE6pwTx/HukigQpX2J9WUf6h0auplrFTw= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs= github.com/ProtonMail/gopenpgp/v2 v2.5.2 h1:97SjlWNAxXl9P22lgwgrZRshQdiEfAht0g3ZoiA1GCw= @@ -62,9 +60,6 @@ github.com/allan-simon/go-singleinstance v0.0.0-20210120080615-d0997106ab37 h1:2 github.com/allan-simon/go-singleinstance v0.0.0-20210120080615-d0997106ab37/go.mod h1:6AXRstqK+32jeFmw89QGL2748+dj34Av4xc/I9oo9BY= github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= -github.com/antlr/antlr4/runtime/Go/antlr v0.0.0-20220816024939-bc8df83d7b9d/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= -github.com/antlr/antlr4/runtime/Go/antlr v1.4.10 h1:yL7+Jz0jTC6yykIK/Wh74gnTJnrGr5AyrNMXuA0gves= -github.com/antlr/antlr4/runtime/Go/antlr v1.4.10/go.mod h1:F7bn7fEU90QkQ3tnmaTx3LTKLEDqnwWODIYppRQ5hnY= github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw= github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo= github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= diff --git a/internal/user/smtp.go b/internal/user/smtp.go index 1a0dd706..22cc3b66 100644 --- a/internal/user/smtp.go +++ b/internal/user/smtp.go @@ -30,9 +30,9 @@ import ( "time" "github.com/ProtonMail/gluon/reporter" + "github.com/ProtonMail/gluon/rfc5322" "github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/go-proton-api" - "github.com/ProtonMail/go-rfc5322" "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/proton-bridge/v3/internal/logging" "github.com/ProtonMail/proton-bridge/v3/internal/safe" diff --git a/pkg/message/build.go b/pkg/message/build.go index 57d7eb42..b67503e2 100644 --- a/pkg/message/build.go +++ b/pkg/message/build.go @@ -27,9 +27,9 @@ import ( "time" "unicode/utf8" + "github.com/ProtonMail/gluon/rfc5322" "github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/go-proton-api" - "github.com/ProtonMail/go-rfc5322" "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/proton-bridge/v3/pkg/algo" "github.com/bradenaw/juniper/xslices" diff --git a/pkg/message/parser.go b/pkg/message/parser.go index cba83aee..91fc105c 100644 --- a/pkg/message/parser.go +++ b/pkg/message/parser.go @@ -26,9 +26,9 @@ import ( "regexp" "strings" + "github.com/ProtonMail/gluon/rfc5322" "github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/go-proton-api" - "github.com/ProtonMail/go-rfc5322" "github.com/ProtonMail/proton-bridge/v3/pkg/message/parser" pmmime "github.com/ProtonMail/proton-bridge/v3/pkg/mime" "github.com/emersion/go-message" diff --git a/tests/ctx_test.go b/tests/ctx_test.go index 2089ea89..fd6be67c 100644 --- a/tests/ctx_test.go +++ b/tests/ctx_test.go @@ -366,6 +366,28 @@ func (t *testCtx) getLastCall(method, pathExp string) (server.Call, error) { return server.Call{}, fmt.Errorf("no call with method %q and path %q was made", method, pathExp) } +func (t *testCtx) getLastCallExcludingHTTPOverride(method, pathExp string) (server.Call, error) { + t.callsLock.RLock() + defer t.callsLock.RUnlock() + + root, err := url.Parse(t.api.GetHostURL()) + if err != nil { + return server.Call{}, err + } + + if matches := xslices.Filter(xslices.Join(t.calls...), func(call server.Call) bool { + if len(call.RequestHeader.Get("X-HTTP-Method-Override")) != 0 || len(call.RequestHeader.Get("X-Http-Method")) != 0 { + return false + } + + return call.Method == method && regexp.MustCompile("^"+pathExp+"$").MatchString(strings.TrimPrefix(call.URL.Path, root.Path)) + }); len(matches) > 0 { + return matches[len(matches)-1], nil + } + + return server.Call{}, fmt.Errorf("no call with method %q and path %q was made", method, pathExp) +} + func (t *testCtx) pushError(err error) { t.errorsLock.Lock() defer t.errorsLock.Unlock() diff --git a/tests/environment_test.go b/tests/environment_test.go index d3c1243d..da78767d 100644 --- a/tests/environment_test.go +++ b/tests/environment_test.go @@ -88,7 +88,8 @@ func (s *scenario) theHeaderInTheRequestToHasSetTo(method, path, key, value stri } func (s *scenario) theBodyInTheRequestToIs(method, path string, value *godog.DocString) error { - call, err := s.t.getLastCall(method, path) + // We have to exclude HTTP-Overrides to avoid race condition with the creating and sending of the draft message. + call, err := s.t.getLastCallExcludingHTTPOverride(method, path) if err != nil { return err } From ed05823c78ccaf5946739f02ccb36ad042078eea Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Mon, 20 Mar 2023 13:19:05 +0100 Subject: [PATCH 115/130] fix(GODT-2418): Do not issue connector renames for inferiors Bump Gluon (https://github.com/ProtonMail/gluon/pull/328) and add test. --- go.mod | 2 +- go.sum | 4 ++-- .../imap/mailbox/rename_hiearchy.feature | 19 +++++++++++++++++++ 3 files changed, 22 insertions(+), 3 deletions(-) create mode 100644 tests/features/imap/mailbox/rename_hiearchy.feature diff --git a/go.mod b/go.mod index 372279e7..1cc1c247 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.2.0 - github.com/ProtonMail/gluon v0.15.1-0.20230317141727-9f7c827f39d2 + github.com/ProtonMail/gluon v0.15.1-0.20230320120726-45de5f1292d7 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739 github.com/ProtonMail/gopenpgp/v2 v2.5.2 diff --git a/go.sum b/go.sum index c024b799..b9071ed5 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.15.1-0.20230317141727-9f7c827f39d2 h1:WT74oKGqW6gCvzXUvgTK4LarotUvyBz9YsNJqftAO74= -github.com/ProtonMail/gluon v0.15.1-0.20230317141727-9f7c827f39d2/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230320120726-45de5f1292d7 h1:IV5UN40uycUfexsuMOY1TAuGLVjKof6V2ybHsNPq1CM= +github.com/ProtonMail/gluon v0.15.1-0.20230320120726-45de5f1292d7/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= diff --git a/tests/features/imap/mailbox/rename_hiearchy.feature b/tests/features/imap/mailbox/rename_hiearchy.feature new file mode 100644 index 00000000..7bb0de8d --- /dev/null +++ b/tests/features/imap/mailbox/rename_hiearchy.feature @@ -0,0 +1,19 @@ +Feature: IMAP get mailbox info + Background: + Given there exists an account with username "[user:user]" and password "password" + And the account "[user:user]" has the following custom mailboxes: + | name | type | + | f1 | folder | + | f1/f2| folder | + And bridge starts + And the user logs in with username "[user:user]" and password "password" + And user "[user:user]" finishes syncing + And user "[user:user]" connects and authenticates IMAP client "1" + + Scenario: Rename folder with subfolders + When IMAP client "1" renames "Folders/f1" to "Folders/f3" + And it succeeds + Then IMAP client "1" sees "Folders/f3" + Then IMAP client "1" sees "Folders/f3/f2" + And IMAP client "1" does not see "Folders/f1" + And IMAP client "1" does not see "Folders/f1/f2" From 2d6e0c66a5feee519ff535cb2d3b184cf544fac2 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Tue, 21 Mar 2023 08:45:01 +0100 Subject: [PATCH 116/130] fix(GODT-2507): Memory consumption bug Fix was made in Gluon: https://github.com/ProtonMail/gluon/pull/329 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 1cc1c247..678b6325 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.2.0 - github.com/ProtonMail/gluon v0.15.1-0.20230320120726-45de5f1292d7 + github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739 github.com/ProtonMail/gopenpgp/v2 v2.5.2 diff --git a/go.sum b/go.sum index b9071ed5..c33dfd96 100644 --- a/go.sum +++ b/go.sum @@ -28,8 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.15.1-0.20230320120726-45de5f1292d7 h1:IV5UN40uycUfexsuMOY1TAuGLVjKof6V2ybHsNPq1CM= -github.com/ProtonMail/gluon v0.15.1-0.20230320120726-45de5f1292d7/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1 h1:zVKqnKO/vTMrVw1dleGsj1JlY9jbhK890X0htvGCbjY= +github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= From bb770f38719b5dc1f014e739aa41641fc27b8e1e Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Tue, 21 Mar 2023 11:52:32 +0100 Subject: [PATCH 117/130] fix(GODT-2512): Catch unhandled API errors Bump GPA https://github.com/ProtonMail/go-proton-api/pull/63 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 678b6325..389b343d 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.0 github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739 + github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9 github.com/ProtonMail/gopenpgp/v2 v2.5.2 github.com/PuerkitoBio/goquery v1.8.1 github.com/abiosoft/ishell v2.0.0+incompatible diff --git a/go.sum b/go.sum index c33dfd96..99e41542 100644 --- a/go.sum +++ b/go.sum @@ -40,8 +40,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 h1:I8IsYA297 github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 h1:dS7r5z4iGS0qCjM7UwWdsEMzQesUQbGcXdSm2/tWboA= github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739 h1:sJhJQKQcG06mDcqikvLLnMuTz2rngcGTiTvOnc7lQbU= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230314144605-dd633a1d4739/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9 h1:RyOYt/rc3hQtIKFUDJObah2g8wouIFVTorou5mmIHQI= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs= github.com/ProtonMail/gopenpgp/v2 v2.5.2 h1:97SjlWNAxXl9P22lgwgrZRshQdiEfAht0g3ZoiA1GCw= From f1989193c00bf6b090d7137f447d45add3dbcb32 Mon Sep 17 00:00:00 2001 From: James Houlahan Date: Mon, 20 Mar 2023 14:55:49 +0100 Subject: [PATCH 118/130] feat(GODT-2509): Migrate TLS cert from v1/v2 location during upgrade to v3 --- internal/app/migration.go | 27 +++++- internal/app/migration_test.go | 95 +++++++++++++------ .../with_keys/protonmail/bridge/cert.pem | 1 + .../with_keys/protonmail/bridge/key.pem | 1 + .../protonmail/bridge}/prefs.json | 0 .../without_keys/protonmail/bridge/prefs.json | 31 ++++++ internal/vault/certs.go | 8 ++ 7 files changed, 131 insertions(+), 32 deletions(-) create mode 100644 internal/app/testdata/with_keys/protonmail/bridge/cert.pem create mode 100644 internal/app/testdata/with_keys/protonmail/bridge/key.pem rename internal/app/testdata/{ => with_keys/protonmail/bridge}/prefs.json (100%) create mode 100644 internal/app/testdata/without_keys/protonmail/bridge/prefs.json diff --git a/internal/app/migration.go b/internal/app/migration.go index 4c440e6b..c5197ad9 100644 --- a/internal/app/migration.go +++ b/internal/app/migration.go @@ -87,6 +87,11 @@ func migrateOldSettings(v *vault.Vault) error { return fmt.Errorf("failed to get user config dir: %w", err) } + return migrateOldSettingsWithDir(configDir, v) +} + +// nolint:gosec +func migrateOldSettingsWithDir(configDir string, v *vault.Vault) error { b, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "prefs.json")) if errors.Is(err, fs.ErrNotExist) { return nil @@ -94,7 +99,27 @@ func migrateOldSettings(v *vault.Vault) error { return fmt.Errorf("failed to read old prefs file: %w", err) } - return migratePrefsToVault(v, b) + if err := migratePrefsToVault(v, b); err != nil { + return fmt.Errorf("failed to migrate prefs to vault: %w", err) + } + + logrus.Info("Migrating TLS certificate") + + certPEM, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "cert.pem")) + if errors.Is(err, fs.ErrNotExist) { + return nil + } else if err != nil { + return fmt.Errorf("failed to read old cert file: %w", err) + } + + keyPEM, err := os.ReadFile(filepath.Join(configDir, "protonmail", "bridge", "key.pem")) + if errors.Is(err, fs.ErrNotExist) { + return nil + } else if err != nil { + return fmt.Errorf("failed to read old key file: %w", err) + } + + return v.SetBridgeTLSCertKey(certPEM, keyPEM) } func migrateOldAccounts(locations *locations.Locations, v *vault.Vault) error { diff --git a/internal/app/migration_test.go b/internal/app/migration_test.go index fd0b41e1..02dff7e1 100644 --- a/internal/app/migration_test.go +++ b/internal/app/migration_test.go @@ -38,51 +38,49 @@ import ( "github.com/stretchr/testify/require" ) -func TestMigratePrefsToVault(t *testing.T) { +func TestMigratePrefsToVaultWithKeys(t *testing.T) { // Create a new vault. vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key")) require.NoError(t, err) require.False(t, corrupt) // load the old prefs file. - b, err := os.ReadFile(filepath.Join("testdata", "prefs.json")) - require.NoError(t, err) + configDir := filepath.Join("testdata", "with_keys") // Migrate the old prefs file to the new vault. - require.NoError(t, migratePrefsToVault(vault, b)) + require.NoError(t, migrateOldSettingsWithDir(configDir, vault)) - // Check that the IMAP and SMTP prefs are migrated. - require.Equal(t, 2143, vault.GetIMAPPort()) - require.Equal(t, 2025, vault.GetSMTPPort()) - require.True(t, vault.GetSMTPSSL()) + // Check Json Settings + validateJSONPrefs(t, vault) - // Check that the update channel is migrated. - require.True(t, vault.GetAutoUpdate()) - require.Equal(t, updater.EarlyChannel, vault.GetUpdateChannel()) - require.Equal(t, 0.4849529004202015, vault.GetUpdateRollout()) + cert, key := vault.GetBridgeTLSCert() + // Check the keys were found and collected. + require.Equal(t, "-----BEGIN CERTIFICATE-----", string(cert)) + require.Equal(t, "-----BEGIN RSA PRIVATE KEY-----", string(key)) +} - // Check that the app settings have been migrated. - require.False(t, vault.GetFirstStart()) - require.Equal(t, "blablabla", vault.GetColorScheme()) - require.Equal(t, "2.3.0+git", vault.GetLastVersion().String()) - require.True(t, vault.GetAutostart()) - - // Check that the other app settings have been migrated. - require.False(t, vault.GetProxyAllowed()) - require.False(t, vault.GetShowAllMail()) - - // Check that the cookies have been migrated. - jar, err := cookiejar.New(nil) +func TestMigratePrefsToVaultWithoutKeys(t *testing.T) { + // Create a new vault. + vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key")) require.NoError(t, err) + require.False(t, corrupt) - cookies, err := cookies.NewCookieJar(jar, vault) - require.NoError(t, err) + // load the old prefs file. + configDir := filepath.Join("testdata", "without_keys") - url, err := url.Parse("https://api.protonmail.ch") - require.NoError(t, err) + // Migrate the old prefs file to the new vault. + require.NoError(t, migrateOldSettingsWithDir(configDir, vault)) - // There should be a cookie for the API. - require.NotEmpty(t, cookies.Cookies(url)) + // Migrate the old prefs file to the new vault. + require.NoError(t, migrateOldSettingsWithDir(configDir, vault)) + + // Check Json Settings + validateJSONPrefs(t, vault) + + // Check the keys were found and collected. + cert, key := vault.GetBridgeTLSCert() + require.NotEqual(t, []byte("-----BEGIN CERTIFICATE-----"), cert) + require.NotEqual(t, []byte("-----BEGIN RSA PRIVATE KEY-----"), key) } func TestKeychainMigration(t *testing.T) { @@ -99,7 +97,7 @@ func TestKeychainMigration(t *testing.T) { oldCacheDir := filepath.Join(tmpDir, "protonmail", "bridge") require.NoError(t, os.MkdirAll(oldCacheDir, 0o700)) - oldPrefs, err := os.ReadFile(filepath.Join("testdata", "prefs.json")) + oldPrefs, err := os.ReadFile(filepath.Join("testdata", "without_keys", "protonmail", "bridge", "prefs.json")) require.NoError(t, err) require.NoError(t, os.WriteFile( @@ -194,3 +192,38 @@ func TestUserMigration(t *testing.T) { require.Equal(t, vault.CombinedMode, u.AddressMode()) })) } + +func validateJSONPrefs(t *testing.T, vault *vault.Vault) { + // Check that the IMAP and SMTP prefs are migrated. + require.Equal(t, 2143, vault.GetIMAPPort()) + require.Equal(t, 2025, vault.GetSMTPPort()) + require.True(t, vault.GetSMTPSSL()) + + // Check that the update channel is migrated. + require.True(t, vault.GetAutoUpdate()) + require.Equal(t, updater.EarlyChannel, vault.GetUpdateChannel()) + require.Equal(t, 0.4849529004202015, vault.GetUpdateRollout()) + + // Check that the app settings have been migrated. + require.False(t, vault.GetFirstStart()) + require.Equal(t, "blablabla", vault.GetColorScheme()) + require.Equal(t, "2.3.0+git", vault.GetLastVersion().String()) + require.True(t, vault.GetAutostart()) + + // Check that the other app settings have been migrated. + require.False(t, vault.GetProxyAllowed()) + require.False(t, vault.GetShowAllMail()) + + // Check that the cookies have been migrated. + jar, err := cookiejar.New(nil) + require.NoError(t, err) + + cookies, err := cookies.NewCookieJar(jar, vault) + require.NoError(t, err) + + url, err := url.Parse("https://api.protonmail.ch") + require.NoError(t, err) + + // There should be a cookie for the API. + require.NotEmpty(t, cookies.Cookies(url)) +} diff --git a/internal/app/testdata/with_keys/protonmail/bridge/cert.pem b/internal/app/testdata/with_keys/protonmail/bridge/cert.pem new file mode 100644 index 00000000..75f3c322 --- /dev/null +++ b/internal/app/testdata/with_keys/protonmail/bridge/cert.pem @@ -0,0 +1 @@ +-----BEGIN CERTIFICATE----- \ No newline at end of file diff --git a/internal/app/testdata/with_keys/protonmail/bridge/key.pem b/internal/app/testdata/with_keys/protonmail/bridge/key.pem new file mode 100644 index 00000000..f05debd2 --- /dev/null +++ b/internal/app/testdata/with_keys/protonmail/bridge/key.pem @@ -0,0 +1 @@ +-----BEGIN RSA PRIVATE KEY----- \ No newline at end of file diff --git a/internal/app/testdata/prefs.json b/internal/app/testdata/with_keys/protonmail/bridge/prefs.json similarity index 100% rename from internal/app/testdata/prefs.json rename to internal/app/testdata/with_keys/protonmail/bridge/prefs.json diff --git a/internal/app/testdata/without_keys/protonmail/bridge/prefs.json b/internal/app/testdata/without_keys/protonmail/bridge/prefs.json new file mode 100644 index 00000000..b6a16d46 --- /dev/null +++ b/internal/app/testdata/without_keys/protonmail/bridge/prefs.json @@ -0,0 +1,31 @@ +{ + "allow_proxy": "false", + "attachment_workers": "16", + "autostart": "true", + "autoupdate": "true", + "cache_compression": "true", + "cache_concurrent_read": "16", + "cache_concurrent_write": "16", + "cache_enabled": "true", + "cache_location": "/home/user/.config/protonmail/bridge/cache/c11/messages", + "cache_min_free_abs": "250000000", + "cache_min_free_rat": "", + "color_scheme": "blablabla", + "cookies": "{\"https://api.protonmail.ch\":[{\"Name\":\"Session-Id\",\"Value\":\"blablablablablablablablabla\",\"Path\":\"/\",\"Domain\":\"protonmail.ch\",\"Expires\":\"2023-02-19T00:20:40.269424437+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":true,\"SameSite\":0,\"Raw\":\"Session-Id=blablablablablablablablabla; Domain=protonmail.ch; Path=/; HttpOnly; Secure; Max-Age=7776000\",\"Unparsed\":null},{\"Name\":\"Tag\",\"Value\":\"default\",\"Path\":\"/\",\"Domain\":\"\",\"Expires\":\"2023-02-19T00:20:40.269428627+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":false,\"SameSite\":0,\"Raw\":\"Tag=default; Path=/; Secure; Max-Age=7776000\",\"Unparsed\":null}],\"https://protonmail.com\":[{\"Name\":\"Session-Id\",\"Value\":\"blablablablablablablablabla\",\"Path\":\"/\",\"Domain\":\"protonmail.com\",\"Expires\":\"2023-02-19T00:20:18.315084712+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":true,\"SameSite\":0,\"Raw\":\"Session-Id=Y3q2Mh-ClvqL6LWeYdfyPgAAABI; Domain=protonmail.com; Path=/; HttpOnly; Secure; Max-Age=7776000\",\"Unparsed\":null},{\"Name\":\"Tag\",\"Value\":\"redirect\",\"Path\":\"/\",\"Domain\":\"\",\"Expires\":\"2023-02-19T00:20:18.315087646+01:00\",\"RawExpires\":\"\",\"MaxAge\":7776000,\"Secure\":true,\"HttpOnly\":false,\"SameSite\":0,\"Raw\":\"Tag=redirect; Path=/; Secure; Max-Age=7776000\",\"Unparsed\":null}]}", + "fetch_workers": "16", + "first_time_start": "false", + "first_time_start_gui": "true", + "imap_workers": "16", + "is_all_mail_visible": "false", + "last_heartbeat": "325", + "last_used_version": "2.3.0+git", + "preferred_keychain": "secret-service", + "rebranding_migrated": "true", + "report_outgoing_email_without_encryption": "false", + "rollout": "0.4849529004202015", + "user_port_api": "1042", + "update_channel": "early", + "user_port_imap": "2143", + "user_port_smtp": "2025", + "user_ssl_smtp": "true" +} \ No newline at end of file diff --git a/internal/vault/certs.go b/internal/vault/certs.go index 75294293..24be5f38 100644 --- a/internal/vault/certs.go +++ b/internal/vault/certs.go @@ -53,6 +53,14 @@ func (vault *Vault) SetBridgeTLSCertPath(certPath, keyPath string) error { }) } +// SetBridgeTLSCertKey sets the path to PEM-encoded certificates for the bridge. +func (vault *Vault) SetBridgeTLSCertKey(cert, key []byte) error { + return vault.mod(func(data *Data) { + data.Certs.Bridge.Cert = cert + data.Certs.Bridge.Key = key + }) +} + func (vault *Vault) GetCertsInstalled() bool { return vault.get().Certs.Installed } From 2166224e910a9753096e80363b8892f984296767 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Wed, 22 Mar 2023 13:19:15 +0100 Subject: [PATCH 119/130] fix(GODT-2513): Scanner Crash in Gluon Gluon MR: https://github.com/ProtonMail/gluon/pull/330 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 389b343d..4f78c989 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.2.0 - github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1 + github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9 github.com/ProtonMail/gopenpgp/v2 v2.5.2 diff --git a/go.sum b/go.sum index 99e41542..d8365eb1 100644 --- a/go.sum +++ b/go.sum @@ -30,6 +30,8 @@ github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkF github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1 h1:zVKqnKO/vTMrVw1dleGsj1JlY9jbhK890X0htvGCbjY= github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546 h1:eJ8gO99EjpuGoUDI0R2VZSzQ7SGPD0ggTbjJaA0xtzE= +github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= From ee87e60239ee2a06305d75c52d26e8a47445e434 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Thu, 23 Mar 2023 13:14:13 +0100 Subject: [PATCH 120/130] fix(GODT-2504): Fix missing attachments in imported message https://github.com/ProtonMail/go-proton-api/pull/64 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 4f78c989..d8a836cf 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.0 github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9 + github.com/ProtonMail/go-proton-api v0.4.1-0.20230323120945-5a6ef5a2ecdd github.com/ProtonMail/gopenpgp/v2 v2.5.2 github.com/PuerkitoBio/goquery v1.8.1 github.com/abiosoft/ishell v2.0.0+incompatible diff --git a/go.sum b/go.sum index d8365eb1..0f43a368 100644 --- a/go.sum +++ b/go.sum @@ -44,6 +44,8 @@ github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 h1:dS7r5z4iGS0q github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9 h1:RyOYt/rc3hQtIKFUDJObah2g8wouIFVTorou5mmIHQI= github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230323120945-5a6ef5a2ecdd h1:Y/XKWw0s7DDJn5R1lJmsREeGyumLcn/RDcvLozYnB88= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230323120945-5a6ef5a2ecdd/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs= github.com/ProtonMail/gopenpgp/v2 v2.5.2 h1:97SjlWNAxXl9P22lgwgrZRshQdiEfAht0g3ZoiA1GCw= From 0a0bcd7b90642b172078d832efb65707670c5282 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Mon, 27 Mar 2023 08:31:47 +0200 Subject: [PATCH 121/130] fix(GODT-2508): Handle Address Updated for none-existing address If we receive an address update and the address does not exist, attempt to create it. --- go.mod | 2 +- go.sum | 4 ++++ internal/bridge/user_event_test.go | 18 ++++++++++++++++++ internal/user/events.go | 15 +++++++++++++-- 4 files changed, 36 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index d8a836cf..931bbcc0 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.0 github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.4.1-0.20230323120945-5a6ef5a2ecdd + github.com/ProtonMail/go-proton-api v0.4.1-0.20230327062918-71c20587e0fc github.com/ProtonMail/gopenpgp/v2 v2.5.2 github.com/PuerkitoBio/goquery v1.8.1 github.com/abiosoft/ishell v2.0.0+incompatible diff --git a/go.sum b/go.sum index 0f43a368..c693df2c 100644 --- a/go.sum +++ b/go.sum @@ -46,6 +46,10 @@ github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9 h1:RyOY github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= github.com/ProtonMail/go-proton-api v0.4.1-0.20230323120945-5a6ef5a2ecdd h1:Y/XKWw0s7DDJn5R1lJmsREeGyumLcn/RDcvLozYnB88= github.com/ProtonMail/go-proton-api v0.4.1-0.20230323120945-5a6ef5a2ecdd/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230324123811-83e98cb35c9a h1:sKcw8YlNxqO9iDDYdbZNVUCqk6Ta6liyfFBUR0Lai7o= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230324123811-83e98cb35c9a/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230327062918-71c20587e0fc h1:D0F4mxNVwIzYcjt8SEuIh4EzJhWgWw1f4eNc1iWrXnQ= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230327062918-71c20587e0fc/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs= github.com/ProtonMail/gopenpgp/v2 v2.5.2 h1:97SjlWNAxXl9P22lgwgrZRshQdiEfAht0g3ZoiA1GCw= diff --git a/internal/bridge/user_event_test.go b/internal/bridge/user_event_test.go index c4404f0b..d48094c7 100644 --- a/internal/bridge/user_event_test.go +++ b/internal/bridge/user_event_test.go @@ -329,6 +329,24 @@ func TestBridge_User_AddressEvents_NoBadEvent(t *testing.T) { }) } +func TestBridge_User_AddressEventUpdatedForAddressThatDoesNotExist_NoBadEvent(t *testing.T) { + withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { + // Create a user. + userID, _, err := s.CreateUser("user", password) + require.NoError(t, err) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, _ *bridge.Mocks) { + userLoginAndSync(ctx, t, bridge, "user", password) + }) + + withBridge(ctx, t, s.GetHostURL(), netCtl, locator, storeKey, func(bridge *bridge.Bridge, _ *bridge.Mocks) { + _, err := s.CreateAddressAsUpdate(userID, "another@pm.me", password) + require.NoError(t, err) + userContinueEventProcess(ctx, t, s, bridge) + }) + }) +} + func TestBridge_User_Network_NoBadEvents(t *testing.T) { withEnv(t, func(ctx context.Context, s *server.Server, netCtl *proton.NetCtl, locator bridge.Locator, storeKey []byte) { retVal := int32(0) diff --git a/internal/user/events.go b/internal/user/events.go index 72131a3b..f980454a 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -170,6 +170,16 @@ func (user *User) handleAddressEvents(ctx context.Context, addressEvents []proto case proton.EventUpdate, proton.EventUpdateFlags: if err := user.handleUpdateAddressEvent(ctx, event); err != nil { + if errors.Is(err, ErrAddressDoesNotExist) { + logrus.Debugf("Address %v does not exist, will try create instead", event.Address.ID) + if createErr := user.handleCreateAddressEvent(ctx, event); createErr != nil { + user.reportError("Failed to apply address update event (with create)", createErr) + return fmt.Errorf("failed to handle update address event (with create): %w", createErr) + } + + return nil + } + user.reportError("Failed to apply address update event", err) return fmt.Errorf("failed to handle update address event: %w", err) } @@ -245,6 +255,8 @@ func (user *User) handleCreateAddressEvent(ctx context.Context, event proton.Add }, user.apiAddrsLock, user.apiLabelsLock, user.updateChLock) } +var ErrAddressDoesNotExist = errors.New("address does not exist") + func (user *User) handleUpdateAddressEvent(_ context.Context, event proton.AddressEvent) error { //nolint:unparam return safe.LockRet(func() error { user.log.WithFields(logrus.Fields{ @@ -254,8 +266,7 @@ func (user *User) handleUpdateAddressEvent(_ context.Context, event proton.Addre oldAddr, ok := user.apiAddrs[event.Address.ID] if !ok { - user.log.Debugf("Address %q does not exist", event.Address.ID) - return nil + return ErrAddressDoesNotExist } user.apiAddrs[event.Address.ID] = event.Address From 7ba523393c0d30bdb66db0578b0ec1a4ed8215fa Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Mon, 27 Mar 2023 09:44:51 +0200 Subject: [PATCH 122/130] fix(GODT-2524): Preserve old vault values Keep the record of old vault settings alive to avoid issues when one downgrades from a 3.1 release to a 3.0.x release. --- internal/vault/types_settings.go | 21 +++++++++++++++++++++ internal/vault/types_user.go | 6 ++++++ 2 files changed, 27 insertions(+) diff --git a/internal/vault/types_settings.go b/internal/vault/types_settings.go index bb6946a3..8f83423f 100644 --- a/internal/vault/types_settings.go +++ b/internal/vault/types_settings.go @@ -19,6 +19,7 @@ package vault import ( "math/rand" + "runtime" "github.com/ProtonMail/proton-bridge/v3/internal/updater" ) @@ -44,11 +45,29 @@ type Settings struct { FirstStart bool MaxSyncMemory uint64 + + // **WARNING**: These entry can't be removed until they vault has proper migration support. + SyncWorkers int + SyncAttPool int } const DefaultMaxSyncMemory = 2 * 1024 * uint64(1024*1024) +func GetDefaultSyncWorkerCount() int { + const minSyncWorkers = 16 + + syncWorkers := runtime.NumCPU() * 4 + + if syncWorkers < minSyncWorkers { + syncWorkers = minSyncWorkers + } + + return syncWorkers +} + func newDefaultSettings(gluonDir string) Settings { + syncWorkers := GetDefaultSyncWorkerCount() + return Settings{ GluonDir: gluonDir, @@ -70,5 +89,7 @@ func newDefaultSettings(gluonDir string) Settings { FirstStart: true, MaxSyncMemory: DefaultMaxSyncMemory, + SyncWorkers: syncWorkers, + SyncAttPool: syncWorkers, } } diff --git a/internal/vault/types_user.go b/internal/vault/types_user.go index af1958e3..a41085fb 100644 --- a/internal/vault/types_user.go +++ b/internal/vault/types_user.go @@ -17,6 +17,8 @@ package vault +import "github.com/ProtonMail/gluon/imap" + // UserData holds information about a single bridge user. // The user may or may not be logged in. type UserData struct { @@ -35,6 +37,9 @@ type UserData struct { SyncStatus SyncStatus EventID string + + // **WARNING**: This value can't be removed until we have vault migration support. + UIDValidity map[string]imap.UID } type AddressMode int @@ -76,6 +81,7 @@ func newDefaultUser(userID, username, primaryEmail, authUID, authRef string, key GluonKey: newRandomToken(32), GluonIDs: make(map[string]string), + UIDValidity: make(map[string]imap.UID), BridgePass: newRandomToken(16), AddressMode: CombinedMode, From 579e996d3adab316b99ed15022d54f9f759fb100 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Mon, 27 Mar 2023 16:07:54 +0200 Subject: [PATCH 123/130] fix(GODT-2514): Apply Retry-After to 503 https://github.com/ProtonMail/go-proton-api/pull/67 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 931bbcc0..2f7d8c93 100644 --- a/go.mod +++ b/go.mod @@ -7,7 +7,7 @@ require ( github.com/Masterminds/semver/v3 v3.2.0 github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.4.1-0.20230327062918-71c20587e0fc + github.com/ProtonMail/go-proton-api v0.4.1-0.20230327135835-2751384cef6f github.com/ProtonMail/gopenpgp/v2 v2.5.2 github.com/PuerkitoBio/goquery v1.8.1 github.com/abiosoft/ishell v2.0.0+incompatible diff --git a/go.sum b/go.sum index c693df2c..909d47fe 100644 --- a/go.sum +++ b/go.sum @@ -50,6 +50,8 @@ github.com/ProtonMail/go-proton-api v0.4.1-0.20230324123811-83e98cb35c9a h1:sKcw github.com/ProtonMail/go-proton-api v0.4.1-0.20230324123811-83e98cb35c9a/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= github.com/ProtonMail/go-proton-api v0.4.1-0.20230327062918-71c20587e0fc h1:D0F4mxNVwIzYcjt8SEuIh4EzJhWgWw1f4eNc1iWrXnQ= github.com/ProtonMail/go-proton-api v0.4.1-0.20230327062918-71c20587e0fc/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230327135835-2751384cef6f h1:lqf3DlFQMvfDi7zGVKTlciyxXfvkoi6CCISu9nx8nak= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230327135835-2751384cef6f/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs= github.com/ProtonMail/gopenpgp/v2 v2.5.2 h1:97SjlWNAxXl9P22lgwgrZRshQdiEfAht0g3ZoiA1GCw= From 9756a7b51ff42b2c2a4de05b08f8d5a9181a6119 Mon Sep 17 00:00:00 2001 From: Leander Beernaert Date: Wed, 29 Mar 2023 14:49:36 +0200 Subject: [PATCH 124/130] fix(GODT-2526): Fix high memory usage with fetch/search https://github.com/ProtonMail/gluon/pull/333 --- go.mod | 2 +- go.sum | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/go.mod b/go.mod index 2f7d8c93..8e93ee44 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.2.0 - github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546 + github.com/ProtonMail/gluon v0.15.1-0.20230329124608-19b8f7b4e7b0 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a github.com/ProtonMail/go-proton-api v0.4.1-0.20230327135835-2751384cef6f github.com/ProtonMail/gopenpgp/v2 v2.5.2 diff --git a/go.sum b/go.sum index 909d47fe..3d09459d 100644 --- a/go.sum +++ b/go.sum @@ -32,6 +32,8 @@ github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1 h1:zVKqnKO/vTM github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546 h1:eJ8gO99EjpuGoUDI0R2VZSzQ7SGPD0ggTbjJaA0xtzE= github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230329124608-19b8f7b4e7b0 h1:FASrdEaNRJSHFjrOZ5WO4CKuYZb2zoCyFNqplrsZmOQ= +github.com/ProtonMail/gluon v0.15.1-0.20230329124608-19b8f7b4e7b0/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= From 9f59e61b146d22520b34708ab6356810370d590a Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Tue, 21 Mar 2023 12:30:23 +0100 Subject: [PATCH 125/130] feat(GODT-2511): add bridge-gui switches to permanently select the QML rendering backend. (cherry picked from commit 03c3e95b344166f970a4843ddbb279b957416cc5) --- .../frontend/bridge-gui/bridge-gui/CommandLine.cpp | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/CommandLine.cpp b/internal/frontend/bridge-gui/bridge-gui/CommandLine.cpp index 5a892da0..420e7901 100644 --- a/internal/frontend/bridge-gui/bridge-gui/CommandLine.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/CommandLine.cpp @@ -18,6 +18,7 @@ #include "Pch.h" #include "CommandLine.h" +#include "Settings.h" using namespace bridgepp; @@ -28,7 +29,10 @@ namespace { QString const launcherFlag = "--launcher"; ///< launcher flag parameter used for bridge. QString const noWindowFlag = "--no-window"; ///< The no-window command-line flag. -QString const softwareRendererFlag = "--software-renderer"; ///< The 'software-renderer' command-line flag. +QString const softwareRendererFlag = "--software-renderer"; ///< The 'software-renderer' command-line flag. enable software rendering for a single execution +QString const setSoftwareRendererFlag = "--set-software-renderer"; ///< The 'set-software-renderer' command-line flag. Software rendering will be used for all subsequent executions of the application. +QString const setHardwareRendererFlag = "--set-hardware-renderer"; ///< The 'set-hardware-renderer' command-line flag. Hardware rendering will be used for all subsequent executions of the application. + //**************************************************************************************************************************************************** /// \brief parse a command-line string argument as expected by go's CLI package. @@ -101,6 +105,14 @@ CommandLineOptions parseCommandLine(int argc, char *argv[]) { options.bridgeGuiArgs.append(arg); options.useSoftwareRenderer = true; } + if (arg == setSoftwareRendererFlag) { + app().settings().setUseSoftwareRenderer(true); + continue; // setting is permanent. no need to keep/pass it to bridge for restart. + } + if (arg == setHardwareRendererFlag) { + app().settings().setUseSoftwareRenderer(false); + continue; // setting is permanent. no need to keep/pass it to bridge for restart. + } if (arg == noWindowFlag) { options.noWindow = true; } From ec92c918cd141de82dc3bf326b445404703f2713 Mon Sep 17 00:00:00 2001 From: Jakub Date: Wed, 22 Mar 2023 17:18:17 +0100 Subject: [PATCH 126/130] feat(GODT-2500): Add panic handlers everywhere. --- go.mod | 2 ++ internal/app/app.go | 16 ++++++------ internal/app/bridge.go | 2 +- internal/app/frontend.go | 2 +- internal/app/migration_test.go | 7 +++--- internal/app/vault.go | 9 ++++--- internal/bridge/api.go | 3 +++ internal/bridge/api_default.go | 4 ++- internal/bridge/api_qa.go | 4 ++- internal/bridge/bridge.go | 21 ++++++++-------- internal/bridge/bridge_test.go | 3 ++- internal/bridge/imap.go | 2 ++ internal/bridge/settings.go | 1 + internal/bridge/sync_test.go | 3 ++- internal/bridge/user.go | 2 +- internal/bridge/user_event_test.go | 5 ++-- internal/clientconfig/applemail.go | 2 ++ internal/dialer/dialer_proxy.go | 16 ++++++++++-- internal/dialer/dialer_proxy_provider.go | 17 ++++++++++++- internal/dialer/dialer_proxy_provider_test.go | 25 ++++++++++--------- internal/dialer/dialer_proxy_test.go | 21 ++++++++-------- internal/focus/focus_test.go | 4 +-- internal/focus/service.go | 22 +++++++++++++--- internal/frontend/cli/frontend.go | 22 ++++++++++++---- internal/frontend/grpc/service.go | 17 +++++++++++-- internal/frontend/grpc/service_methods.go | 25 ++++++++++++------- internal/try/try.go | 20 +++++++++++++-- internal/user/events.go | 8 +++--- internal/user/imap.go | 6 ++--- internal/user/smtp.go | 18 ++++++++----- internal/user/sync.go | 22 +++++++++------- internal/user/types.go | 5 ++-- internal/user/user.go | 23 +++++++++++++---- internal/user/user_test.go | 2 +- internal/vault/migrate_test.go | 3 ++- internal/vault/settings_test.go | 3 ++- internal/vault/vault.go | 15 ++++++++++- internal/vault/vault_bench_test.go | 3 ++- internal/vault/vault_test.go | 15 +++++------ tests/collector_test.go | 6 ++--- tests/ctx_bridge_test.go | 4 +-- tests/ctx_helper_test.go | 3 ++- 42 files changed, 283 insertions(+), 130 deletions(-) diff --git a/go.mod b/go.mod index 8e93ee44..aa13f862 100644 --- a/go.mod +++ b/go.mod @@ -125,6 +125,8 @@ require ( ) replace ( + github.com/ProtonMail/gluon => /home/dev/gopath18/src/gluon + github.com/ProtonMail/go-proton-api => /home/dev/gopath18/src/go-proton-api github.com/docker/docker-credential-helpers => github.com/ProtonMail/docker-credential-helpers v1.1.0 github.com/emersion/go-message => github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 github.com/keybase/go-keychain => github.com/cuthix/go-keychain v0.0.0-20220405075754-31e7cee908fe diff --git a/internal/app/app.go b/internal/app/app.go index 36240e74..4cdbd187 100644 --- a/internal/app/app.go +++ b/internal/app/app.go @@ -185,14 +185,14 @@ func run(c *cli.Context) error { exe = os.Args[0] } - migrationErr := migrateOldVersions() + // Restart the app if requested. + return withRestarter(exe, func(restarter *restarter.Restarter) error { + // Handle crashes with various actions. + return withCrashHandler(restarter, reporter, func(crashHandler *crash.Handler, quitCh <-chan struct{}) error { + migrationErr := migrateOldVersions() - // Run with profiling if requested. - return withProfiler(c, func() error { - // Restart the app if requested. - return withRestarter(exe, func(restarter *restarter.Restarter) error { - // Handle crashes with various actions. - return withCrashHandler(restarter, reporter, func(crashHandler *crash.Handler, quitCh <-chan struct{}) error { + // Run with profiling if requested. + return withProfiler(c, func() error { // Load the locations where we store our files. return WithLocations(func(locations *locations.Locations) error { // Migrate the keychain helper. @@ -215,7 +215,7 @@ func run(c *cli.Context) error { return withSingleInstance(settings, locations.GetLockFile(), version, func() error { // Unlock the encrypted vault. - return WithVault(locations, func(v *vault.Vault, insecure, corrupt bool) error { + return WithVault(locations, crashHandler, func(v *vault.Vault, insecure, corrupt bool) error { // Report insecure vault. if insecure { _ = reporter.ReportMessageWithContext("Vault is insecure", map[string]interface{}{}) diff --git a/internal/app/bridge.go b/internal/app/bridge.go index 6705227a..280d444f 100644 --- a/internal/app/bridge.go +++ b/internal/app/bridge.go @@ -78,7 +78,7 @@ func withBridge( ) // Create a proxy dialer which switches to a proxy if the request fails. - proxyDialer := dialer.NewProxyTLSDialer(pinningDialer, constants.APIHost) + proxyDialer := dialer.NewProxyTLSDialer(pinningDialer, constants.APIHost, crashHandler) // Create the autostarter. autostarter := newAutostarter(exe) diff --git a/internal/app/frontend.go b/internal/app/frontend.go index 4c56d968..6e1bd8fa 100644 --- a/internal/app/frontend.go +++ b/internal/app/frontend.go @@ -46,7 +46,7 @@ func runFrontend( switch { case c.Bool(flagCLI): - return bridgeCLI.New(bridge, restarter, eventCh).Loop() + return bridgeCLI.New(bridge, restarter, eventCh, crashHandler).Loop() case c.Bool(flagNonInteractive): select {} diff --git a/internal/app/migration_test.go b/internal/app/migration_test.go index 02dff7e1..c994ed63 100644 --- a/internal/app/migration_test.go +++ b/internal/app/migration_test.go @@ -25,6 +25,7 @@ import ( "runtime" "testing" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/cookies" @@ -40,7 +41,7 @@ import ( func TestMigratePrefsToVaultWithKeys(t *testing.T) { // Create a new vault. - vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key")) + vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) @@ -61,7 +62,7 @@ func TestMigratePrefsToVaultWithKeys(t *testing.T) { func TestMigratePrefsToVaultWithoutKeys(t *testing.T) { // Create a new vault. - vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key")) + vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) @@ -173,7 +174,7 @@ func TestUserMigration(t *testing.T) { token, err := crypto.RandomToken(32) require.NoError(t, err) - v, corrupt, err := vault.New(settingsFolder, settingsFolder, token) + v, corrupt, err := vault.New(settingsFolder, settingsFolder, token, queue.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) diff --git a/internal/app/vault.go b/internal/app/vault.go index 55b583b1..013653a5 100644 --- a/internal/app/vault.go +++ b/internal/app/vault.go @@ -21,6 +21,7 @@ import ( "fmt" "path" + "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/ProtonMail/proton-bridge/v3/internal/certs" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/locations" @@ -29,12 +30,12 @@ import ( "github.com/sirupsen/logrus" ) -func WithVault(locations *locations.Locations, fn func(*vault.Vault, bool, bool) error) error { +func WithVault(locations *locations.Locations, panicHandler async.PanicHandler, fn func(*vault.Vault, bool, bool) error) error { logrus.Debug("Creating vault") defer logrus.Debug("Vault stopped") // Create the encVault. - encVault, insecure, corrupt, err := newVault(locations) + encVault, insecure, corrupt, err := newVault(locations, panicHandler) if err != nil { return fmt.Errorf("could not create vault: %w", err) } @@ -66,7 +67,7 @@ func WithVault(locations *locations.Locations, fn func(*vault.Vault, bool, bool) return fn(encVault, insecure, corrupt) } -func newVault(locations *locations.Locations) (*vault.Vault, bool, bool, error) { +func newVault(locations *locations.Locations, panicHandler async.PanicHandler) (*vault.Vault, bool, bool, error) { vaultDir, err := locations.ProvideSettingsPath() if err != nil { return nil, false, false, fmt.Errorf("could not get vault dir: %w", err) @@ -93,7 +94,7 @@ func newVault(locations *locations.Locations) (*vault.Vault, bool, bool, error) return nil, false, false, fmt.Errorf("could not provide gluon path: %w", err) } - vault, corrupt, err := vault.New(vaultDir, gluonCacheDir, vaultKey) + vault, corrupt, err := vault.New(vaultDir, gluonCacheDir, vaultKey, panicHandler) if err != nil { return nil, false, false, fmt.Errorf("could not create vault: %w", err) } diff --git a/internal/bridge/api.go b/internal/bridge/api.go index cbe2f2be..f7c3d41a 100644 --- a/internal/bridge/api.go +++ b/internal/bridge/api.go @@ -21,6 +21,7 @@ import ( "net/http" "github.com/Masterminds/semver/v3" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/sirupsen/logrus" @@ -32,6 +33,7 @@ func defaultAPIOptions( version *semver.Version, cookieJar http.CookieJar, transport http.RoundTripper, + panicHandler queue.PanicHandler, ) []proton.Option { return []proton.Option{ proton.WithHostURL(apiURL), @@ -39,5 +41,6 @@ func defaultAPIOptions( proton.WithCookieJar(cookieJar), proton.WithTransport(transport), proton.WithLogger(logrus.StandardLogger()), + proton.WithPanicHandler(panicHandler), } } diff --git a/internal/bridge/api_default.go b/internal/bridge/api_default.go index 6f800d77..cc89fe16 100644 --- a/internal/bridge/api_default.go +++ b/internal/bridge/api_default.go @@ -23,6 +23,7 @@ import ( "net/http" "github.com/Masterminds/semver/v3" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/go-proton-api" ) @@ -32,6 +33,7 @@ func newAPIOptions( version *semver.Version, cookieJar http.CookieJar, transport http.RoundTripper, + panicHandler queue.PanicHandler, ) []proton.Option { - return defaultAPIOptions(apiURL, version, cookieJar, transport) + return defaultAPIOptions(apiURL, version, cookieJar, transport, panicHandler) } diff --git a/internal/bridge/api_qa.go b/internal/bridge/api_qa.go index 618ce42e..a8c5a71a 100644 --- a/internal/bridge/api_qa.go +++ b/internal/bridge/api_qa.go @@ -24,6 +24,7 @@ import ( "os" "github.com/Masterminds/semver/v3" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/go-proton-api" ) @@ -33,8 +34,9 @@ func newAPIOptions( version *semver.Version, cookieJar http.CookieJar, transport http.RoundTripper, + panicHandler queue.PanicHandler, ) []proton.Option { - opt := defaultAPIOptions(apiURL, version, cookieJar, transport) + opt := defaultAPIOptions(apiURL, version, cookieJar, transport, panicHandler) if host := os.Getenv("BRIDGE_API_HOST"); host != "" { opt = append(opt, proton.WithHostURL(host)) diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index 27cde2a4..0eba71fc 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -93,8 +93,8 @@ type Bridge struct { // locator is the bridge's locator. locator Locator - // crashHandler - crashHandler async.PanicHandler + // panicHandler + panicHandler async.PanicHandler // reporter reporter reporter.Reporter @@ -143,7 +143,7 @@ func New( tlsReporter TLSReporter, // the TLS reporter to report TLS errors roundTripper http.RoundTripper, // the round tripper to use for API requests proxyCtl ProxyController, // the DoH controller - crashHandler async.PanicHandler, + panicHandler async.PanicHandler, reporter reporter.Reporter, uidValidityGenerator imap.UIDValidityGenerator, @@ -151,10 +151,10 @@ func New( logSMTP bool, // whether to log SMTP activity ) (*Bridge, <-chan events.Event, error) { // api is the user's API manager. - api := proton.New(newAPIOptions(apiURL, curVersion, cookieJar, roundTripper)...) + api := proton.New(newAPIOptions(apiURL, curVersion, cookieJar, roundTripper, panicHandler)...) // tasks holds all the bridge's background tasks. - tasks := async.NewGroup(context.Background(), crashHandler) + tasks := async.NewGroup(context.Background(), panicHandler) // imapEventCh forwards IMAP events from gluon instances to the bridge for processing. imapEventCh := make(chan imapEvents.Event) @@ -169,7 +169,7 @@ func New( autostarter, updater, curVersion, - crashHandler, + panicHandler, reporter, api, @@ -202,7 +202,7 @@ func newBridge( autostarter Autostarter, updater Updater, curVersion *semver.Version, - crashHandler async.PanicHandler, + panicHandler async.PanicHandler, reporter reporter.Reporter, api *proton.Manager, @@ -248,12 +248,13 @@ func newBridge( imapEventCh, tasks, uidValidityGenerator, + panicHandler, ) if err != nil { return nil, fmt.Errorf("failed to create IMAP server: %w", err) } - focusService, err := focus.NewService(locator, curVersion) + focusService, err := focus.NewService(locator, curVersion, panicHandler) if err != nil { return nil, fmt.Errorf("failed to create focus service: %w", err) } @@ -279,7 +280,7 @@ func newBridge( newVersion: curVersion, newVersionLock: safe.NewRWMutex(), - crashHandler: crashHandler, + panicHandler: panicHandler, reporter: reporter, focusService: focusService, @@ -495,7 +496,7 @@ func (bridge *Bridge) addWatcher(ofType ...events.Event) *watcher.Watcher[events bridge.watchersLock.Lock() defer bridge.watchersLock.Unlock() - watcher := watcher.New(ofType...) + watcher := watcher.New(bridge.panicHandler, ofType...) bridge.watchers = append(bridge.watchers, watcher) diff --git a/internal/bridge/bridge_test.go b/internal/bridge/bridge_test.go index 992d241f..28778cd5 100644 --- a/internal/bridge/bridge_test.go +++ b/internal/bridge/bridge_test.go @@ -31,6 +31,7 @@ import ( "github.com/Masterminds/semver/v3" "github.com/ProtonMail/gluon/imap" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" "github.com/ProtonMail/go-proton-api/server/backend" @@ -699,7 +700,7 @@ func withBridgeNoMocks( require.NoError(t, err) // Create the vault. - vault, _, err := vault.New(vaultDir, t.TempDir(), vaultKey) + vault, _, err := vault.New(vaultDir, t.TempDir(), vaultKey, queue.NoopPanicHandler{}) require.NoError(t, err) // Create a new cookie jar. diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index d6efff44..752155dd 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -299,6 +299,7 @@ func newIMAPServer( eventCh chan<- imapEvents.Event, tasks *async.Group, uidValidityGenerator imap.UIDValidityGenerator, + panicHandler async.PanicHandler, ) (*gluon.Server, error) { gluonCacheDir = ApplyGluonCachePathSuffix(gluonCacheDir) gluonConfigDir = ApplyGluonConfigPathSuffix(gluonConfigDir) @@ -343,6 +344,7 @@ func newIMAPServer( getGluonVersionInfo(version), gluon.WithReporter(reporter), gluon.WithUIDValidityGenerator(uidValidityGenerator), + gluon.WithPanicHandler(panicHandler), ) if err != nil { return nil, err diff --git a/internal/bridge/settings.go b/internal/bridge/settings.go index 0ab4c5a0..8c262cc9 100644 --- a/internal/bridge/settings.go +++ b/internal/bridge/settings.go @@ -157,6 +157,7 @@ func (bridge *Bridge) SetGluonDir(ctx context.Context, newGluonDir string) error bridge.imapEventCh, bridge.tasks, bridge.uidValidityGenerator, + bridge.panicHandler, ) if err != nil { return fmt.Errorf("failed to create new IMAP server: %w", err) diff --git a/internal/bridge/sync_test.go b/internal/bridge/sync_test.go index 182986c2..e0ffe1c8 100644 --- a/internal/bridge/sync_test.go +++ b/internal/bridge/sync_test.go @@ -28,6 +28,7 @@ import ( "testing" "time" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" @@ -428,7 +429,7 @@ func createMessages(ctx context.Context, t *testing.T, c *proton.Client, addrID, keyPass, err := salt.SaltForKey(password, user.Keys.Primary().ID) require.NoError(t, err) - _, addrKRs, err := proton.Unlock(user, addr, keyPass) + _, addrKRs, err := proton.Unlock(user, addr, keyPass, queue.NoopPanicHandler{}) require.NoError(t, err) _, ok := addrKRs[addrID] diff --git a/internal/bridge/user.go b/internal/bridge/user.go index 59f8f00c..4bdb6152 100644 --- a/internal/bridge/user.go +++ b/internal/bridge/user.go @@ -516,7 +516,7 @@ func (bridge *Bridge) addUserWithVault( client, bridge.reporter, apiUser, - bridge.crashHandler, + bridge.panicHandler, bridge.vault.GetShowAllMail(), bridge.vault.GetMaxSyncMemory(), ) diff --git a/internal/bridge/user_event_test.go b/internal/bridge/user_event_test.go index d48094c7..616f492c 100644 --- a/internal/bridge/user_event_test.go +++ b/internal/bridge/user_event_test.go @@ -28,6 +28,7 @@ import ( "testing" "time" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" @@ -474,7 +475,7 @@ func TestBridge_User_UpdateDraftAndCreateOtherMessage(t *testing.T) { keyPass, err := salts.SaltForKey(password, user.Keys.Primary().ID) require.NoError(t, err) - _, addrKRs, err := proton.Unlock(user, addrs, keyPass) + _, addrKRs, err := proton.Unlock(user, addrs, keyPass, queue.NoopPanicHandler{}) require.NoError(t, err) // Create a draft (generating a "create draft message" event). @@ -556,7 +557,7 @@ func TestBridge_User_SendDraftRemoveDraftFlag(t *testing.T) { keyPass, err := salts.SaltForKey(password, user.Keys.Primary().ID) require.NoError(t, err) - _, addrKRs, err := proton.Unlock(user, addrs, keyPass) + _, addrKRs, err := proton.Unlock(user, addrs, keyPass, queue.NoopPanicHandler{}) require.NoError(t, err) // Create a draft (generating a "create draft message" event). diff --git a/internal/clientconfig/applemail.go b/internal/clientconfig/applemail.go index 7eb56922..1a16fdb5 100644 --- a/internal/clientconfig/applemail.go +++ b/internal/clientconfig/applemail.go @@ -98,6 +98,8 @@ func saveConfigTemporarily(mc *mobileconfig.Config) (fname string, err error) { // Make sure the temporary file is deleted. go func() { + defer recover() //nolint:errcheck + <-time.After(10 * time.Minute) _ = os.RemoveAll(dir) }() diff --git a/internal/dialer/dialer_proxy.go b/internal/dialer/dialer_proxy.go index 0ad1474e..0ce2945e 100644 --- a/internal/dialer/dialer_proxy.go +++ b/internal/dialer/dialer_proxy.go @@ -24,6 +24,7 @@ import ( "sync" "time" + "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -40,17 +41,20 @@ type ProxyTLSDialer struct { allowProxy bool proxyProvider *proxyProvider proxyUseDuration time.Duration + + panicHandler async.PanicHandler } // NewProxyTLSDialer constructs a dialer which provides a proxy-managing layer on top of an underlying dialer. -func NewProxyTLSDialer(dialer TLSDialer, hostURL string) *ProxyTLSDialer { +func NewProxyTLSDialer(dialer TLSDialer, hostURL string, panicHandler async.PanicHandler) *ProxyTLSDialer { return &ProxyTLSDialer{ dialer: dialer, locker: sync.RWMutex{}, directAddress: formatAsAddress(hostURL), proxyAddress: formatAsAddress(hostURL), - proxyProvider: newProxyProvider(dialer, hostURL, DoHProviders), + proxyProvider: newProxyProvider(dialer, hostURL, DoHProviders, panicHandler), proxyUseDuration: proxyUseDuration, + panicHandler: panicHandler, } } @@ -75,6 +79,12 @@ func formatAsAddress(rawURL string) string { return net.JoinHostPort(host, port) } +func (d *ProxyTLSDialer) handlePanic() { + if d.panicHandler != nil { + d.panicHandler.HandlePanic() + } +} + // DialTLSContext dials the given network/address. If it fails, it retries using a proxy. func (d *ProxyTLSDialer) DialTLSContext(ctx context.Context, network, address string) (net.Conn, error) { d.locker.RLock() @@ -129,6 +139,8 @@ func (d *ProxyTLSDialer) switchToReachableServer() error { // This means we want to disable it again in 24 hours. if d.proxyAddress == d.directAddress { go func() { + defer d.handlePanic() + <-time.After(d.proxyUseDuration) d.locker.Lock() diff --git a/internal/dialer/dialer_proxy_provider.go b/internal/dialer/dialer_proxy_provider.go index b9cfd2fd..e4006891 100644 --- a/internal/dialer/dialer_proxy_provider.go +++ b/internal/dialer/dialer_proxy_provider.go @@ -24,6 +24,7 @@ import ( "sync" "time" + "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/go-resty/resty/v2" "github.com/miekg/dns" "github.com/pkg/errors" @@ -67,11 +68,13 @@ type proxyProvider struct { canReachTimeout time.Duration lastLookup time.Time // The time at which we last attempted to find a proxy. + + panicHandler async.PanicHandler } // newProxyProvider creates a new proxyProvider that queries the given DoH providers // to retrieve DNS records for the given query string. -func newProxyProvider(dialer TLSDialer, hostURL string, providers []string) (p *proxyProvider) { +func newProxyProvider(dialer TLSDialer, hostURL string, providers []string, panicHandler async.PanicHandler) (p *proxyProvider) { p = &proxyProvider{ dialer: dialer, hostURL: hostURL, @@ -80,6 +83,7 @@ func newProxyProvider(dialer TLSDialer, hostURL string, providers []string) (p * cacheRefreshTimeout: proxyCacheRefreshTimeout, dohTimeout: proxyDoHTimeout, canReachTimeout: proxyCanReachTimeout, + panicHandler: panicHandler, } // Use the default DNS lookup method; this can be overridden if necessary. @@ -88,6 +92,12 @@ func newProxyProvider(dialer TLSDialer, hostURL string, providers []string) (p * return } +func (p *proxyProvider) handlePanic() { + if p.panicHandler != nil { + p.panicHandler.HandlePanic() + } +} + // findReachableServer returns a working API server (either proxy or standard API). func (p *proxyProvider) findReachableServer() (proxy string, err error) { logrus.Debug("Trying to find a reachable server") @@ -109,11 +119,13 @@ func (p *proxyProvider) findReachableServer() (proxy string, err error) { wg.Add(2) go func() { + defer p.handlePanic() defer wg.Done() apiReachable = p.canReach(p.hostURL) }() go func() { + defer p.handlePanic() defer wg.Done() err = p.refreshProxyCache() }() @@ -150,6 +162,8 @@ func (p *proxyProvider) refreshProxyCache() error { resultChan := make(chan []string) go func() { + defer p.handlePanic() + for _, provider := range p.providers { if proxies, err := p.dohLookup(ctx, p.query, provider); err == nil { resultChan <- proxies @@ -203,6 +217,7 @@ func (p *proxyProvider) defaultDoHLookup(ctx context.Context, query, dohProvider dataChan, errChan := make(chan []string), make(chan error) go func() { + defer p.handlePanic() // Build new DNS request in RFC1035 format. dnsRequest := new(dns.Msg).SetQuestion(dns.Fqdn(query), dns.TypeTXT) diff --git a/internal/dialer/dialer_proxy_provider_test.go b/internal/dialer/dialer_proxy_provider_test.go index f322d462..ddd7aed2 100644 --- a/internal/dialer/dialer_proxy_provider_test.go +++ b/internal/dialer/dialer_proxy_provider_test.go @@ -23,6 +23,7 @@ import ( "testing" "time" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/proton-bridge/v3/internal/useragent" r "github.com/stretchr/testify/require" ) @@ -31,7 +32,7 @@ func TestProxyProvider_FindProxy(t *testing.T) { proxy := getTrustedServer() defer closeServer(proxy) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, queue.NoopPanicHandler{}) p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{proxy.URL}, nil } url, err := p.findReachableServer() @@ -47,7 +48,7 @@ func TestProxyProvider_FindProxy_ChooseReachableProxy(t *testing.T) { unreachableProxy := getTrustedServer() closeServer(unreachableProxy) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, queue.NoopPanicHandler{}) p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{reachableProxy.URL, unreachableProxy.URL}, nil } @@ -68,7 +69,7 @@ func TestProxyProvider_FindProxy_ChooseTrustedProxy(t *testing.T) { checker := NewTLSPinChecker(TrustedAPIPins) dialer := NewPinningTLSDialer(NewBasicTLSDialer(""), reporter, checker) - p := newProxyProvider(dialer, "", []string{"not used"}) + p := newProxyProvider(dialer, "", []string{"not used"}, queue.NoopPanicHandler{}) p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{untrustedProxy.URL, trustedProxy.URL}, nil } @@ -85,7 +86,7 @@ func TestProxyProvider_FindProxy_FailIfNoneReachable(t *testing.T) { unreachableProxy2 := getTrustedServer() closeServer(unreachableProxy2) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, queue.NoopPanicHandler{}) p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{unreachableProxy1.URL, unreachableProxy2.URL}, nil } @@ -105,7 +106,7 @@ func TestProxyProvider_FindProxy_FailIfNoneTrusted(t *testing.T) { checker := NewTLSPinChecker(TrustedAPIPins) dialer := NewPinningTLSDialer(NewBasicTLSDialer(""), reporter, checker) - p := newProxyProvider(dialer, "", []string{"not used"}) + p := newProxyProvider(dialer, "", []string{"not used"}, queue.NoopPanicHandler{}) p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{untrustedProxy1.URL, untrustedProxy2.URL}, nil } @@ -115,7 +116,7 @@ func TestProxyProvider_FindProxy_FailIfNoneTrusted(t *testing.T) { } func TestProxyProvider_FindProxy_RefreshCacheTimeout(t *testing.T) { - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, queue.NoopPanicHandler{}) p.cacheRefreshTimeout = 1 * time.Second p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { time.Sleep(2 * time.Second); return nil, nil } @@ -132,7 +133,7 @@ func TestProxyProvider_FindProxy_CanReachTimeout(t *testing.T) { })) defer closeServer(slowProxy) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, queue.NoopPanicHandler{}) p.canReachTimeout = 1 * time.Second p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{slowProxy.URL}, nil } @@ -144,7 +145,7 @@ func TestProxyProvider_FindProxy_CanReachTimeout(t *testing.T) { } func TestProxyProvider_DoHLookup_Quad9(t *testing.T) { - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, queue.NoopPanicHandler{}) records, err := p.dohLookup(context.Background(), proxyQuery, Quad9Provider) r.NoError(t, err) @@ -155,7 +156,7 @@ func TestProxyProvider_DoHLookup_Quad9(t *testing.T) { // port filter. Basic functionality should be covered by other tests. Keeping // code here to be able to run it locally if needed. func DISABLEDTestProxyProviderDoHLookupQuad9Port(t *testing.T) { - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, queue.NoopPanicHandler{}) records, err := p.dohLookup(context.Background(), proxyQuery, Quad9PortProvider) r.NoError(t, err) @@ -163,7 +164,7 @@ func DISABLEDTestProxyProviderDoHLookupQuad9Port(t *testing.T) { } func TestProxyProvider_DoHLookup_Google(t *testing.T) { - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, queue.NoopPanicHandler{}) records, err := p.dohLookup(context.Background(), proxyQuery, GoogleProvider) r.NoError(t, err) @@ -173,7 +174,7 @@ func TestProxyProvider_DoHLookup_Google(t *testing.T) { func TestProxyProvider_DoHLookup_FindProxy(t *testing.T) { skipIfProxyIsSet(t) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, queue.NoopPanicHandler{}) url, err := p.findReachableServer() r.NoError(t, err) @@ -183,7 +184,7 @@ func TestProxyProvider_DoHLookup_FindProxy(t *testing.T) { func TestProxyProvider_DoHLookup_FindProxyFirstProviderUnreachable(t *testing.T) { skipIfProxyIsSet(t) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"https://unreachable", Quad9Provider, GoogleProvider}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"https://unreachable", Quad9Provider, GoogleProvider}, queue.NoopPanicHandler{}) url, err := p.findReachableServer() r.NoError(t, err) diff --git a/internal/dialer/dialer_proxy_test.go b/internal/dialer/dialer_proxy_test.go index 28290aeb..a78b3055 100644 --- a/internal/dialer/dialer_proxy_test.go +++ b/internal/dialer/dialer_proxy_test.go @@ -25,6 +25,7 @@ import ( "testing" "time" + "github.com/ProtonMail/gluon/queue" "github.com/stretchr/testify/require" ) @@ -141,8 +142,8 @@ func TestProxyDialer_UseProxy(t *testing.T) { trustedProxy := getTrustedServer() defer closeServer(trustedProxy) - provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders) - d := NewProxyTLSDialer(NewBasicTLSDialer(""), "") + provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, queue.NoopPanicHandler{}) + d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", queue.NoopPanicHandler{}) d.proxyProvider = provider provider.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{trustedProxy.URL}, nil } @@ -159,8 +160,8 @@ func TestProxyDialer_UseProxy_MultipleTimes(t *testing.T) { proxy3 := getTrustedServer() defer closeServer(proxy3) - provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders) - d := NewProxyTLSDialer(NewBasicTLSDialer(""), "") + provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, queue.NoopPanicHandler{}) + d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", queue.NoopPanicHandler{}) d.proxyProvider = provider provider.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{proxy1.URL}, nil } @@ -189,8 +190,8 @@ func TestProxyDialer_UseProxy_RevertAfterTime(t *testing.T) { trustedProxy := getTrustedServer() defer closeServer(trustedProxy) - provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders) - d := NewProxyTLSDialer(NewBasicTLSDialer(""), "") + provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, queue.NoopPanicHandler{}) + d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", queue.NoopPanicHandler{}) d.proxyProvider = provider d.proxyUseDuration = time.Second @@ -212,8 +213,8 @@ func TestProxyDialer_UseProxy_RevertAfterTime(t *testing.T) { func TestProxyDialer_UseProxy_RevertIfProxyStopsWorkingAndOriginalAPIIsReachable(t *testing.T) { trustedProxy := getTrustedServer() - provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders) - d := NewProxyTLSDialer(NewBasicTLSDialer(""), "") + provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, queue.NoopPanicHandler{}) + d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", queue.NoopPanicHandler{}) d.proxyProvider = provider provider.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{trustedProxy.URL}, nil } @@ -242,8 +243,8 @@ func TestProxyDialer_UseProxy_FindSecondAlternativeIfFirstFailsAndAPIIsStillBloc proxy2 := getTrustedServer() defer closeServer(proxy2) - provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders) - d := NewProxyTLSDialer(NewBasicTLSDialer(""), "") + provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, queue.NoopPanicHandler{}) + d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", queue.NoopPanicHandler{}) d.proxyProvider = provider provider.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{proxy1.URL, proxy2.URL}, nil } diff --git a/internal/focus/focus_test.go b/internal/focus/focus_test.go index 059d243d..101ed389 100644 --- a/internal/focus/focus_test.go +++ b/internal/focus/focus_test.go @@ -30,7 +30,7 @@ func TestFocus_Raise(t *testing.T) { tmpDir := t.TempDir() locations := locations.New(newTestLocationsProvider(tmpDir), "config-name") // Start the focus service. - service, err := NewService(locations, semver.MustParse("1.2.3")) + service, err := NewService(locations, semver.MustParse("1.2.3"), nil) require.NoError(t, err) settingsFolder, err := locations.ProvideSettingsPath() @@ -52,7 +52,7 @@ func TestFocus_Version(t *testing.T) { tmpDir := t.TempDir() locations := locations.New(newTestLocationsProvider(tmpDir), "config-name") // Start the focus service. - _, err := NewService(locations, semver.MustParse("1.2.3")) + _, err := NewService(locations, semver.MustParse("1.2.3"), nil) require.NoError(t, err) settingsFolder, err := locations.ProvideSettingsPath() diff --git a/internal/focus/service.go b/internal/focus/service.go index ab2d0127..ad0395d1 100644 --- a/internal/focus/service.go +++ b/internal/focus/service.go @@ -24,6 +24,7 @@ import ( "net" "github.com/Masterminds/semver/v3" + "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/ProtonMail/proton-bridge/v3/internal/focus/proto" "github.com/ProtonMail/proton-bridge/v3/internal/service" "github.com/sirupsen/logrus" @@ -43,15 +44,18 @@ type Service struct { server *grpc.Server raiseCh chan struct{} version *semver.Version + + panicHandler async.PanicHandler } // NewService creates a new focus service. // It listens on the local host and port 1042 (by default). -func NewService(locator service.Locator, version *semver.Version) (*Service, error) { +func NewService(locator service.Locator, version *semver.Version, panicHandler async.PanicHandler) (*Service, error) { serv := &Service{ - server: grpc.NewServer(), - raiseCh: make(chan struct{}, 1), - version: version, + server: grpc.NewServer(), + raiseCh: make(chan struct{}, 1), + version: version, + panicHandler: panicHandler, } proto.RegisterFocusServer(serv.server, serv) @@ -73,6 +77,8 @@ func NewService(locator service.Locator, version *semver.Version) (*Service, err } go func() { + defer serv.handlePanic() + if err := serv.server.Serve(listener); err != nil { fmt.Printf("failed to serve: %v", err) } @@ -82,6 +88,12 @@ func NewService(locator service.Locator, version *semver.Version) (*Service, err return serv, nil } +func (service *Service) handlePanic() { + if service.panicHandler != nil { + service.panicHandler.HandlePanic() + } +} + // Raise implements the gRPC FocusService interface; it raises the application. func (service *Service) Raise(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { service.raiseCh <- struct{}{} @@ -103,6 +115,8 @@ func (service *Service) GetRaiseCh() <-chan struct{} { // Close closes the service. func (service *Service) Close() { go func() { + defer service.handlePanic() + // we do this in a goroutine, as on Windows, the gRPC shutdown may take minutes if something tries to // interact with it in an invalid way (e.g. HTTP GET request from a Qt QNetworkManager instance). service.server.Stop() diff --git a/internal/frontend/cli/frontend.go b/internal/frontend/cli/frontend.go index 4063f416..94b5414a 100644 --- a/internal/frontend/cli/frontend.go +++ b/internal/frontend/cli/frontend.go @@ -21,6 +21,7 @@ package cli import ( "errors" + "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/events" @@ -39,15 +40,18 @@ type frontendCLI struct { restarter *restarter.Restarter badUserID string + + panicHandler async.PanicHandler } // New returns a new CLI frontend configured with the given options. -func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan events.Event) *frontendCLI { //nolint:revive +func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan events.Event, panicHandler async.PanicHandler) *frontendCLI { //nolint:revive fe := &frontendCLI{ - Shell: ishell.New(), - bridge: bridge, - restarter: restarter, - badUserID: "", + Shell: ishell.New(), + bridge: bridge, + restarter: restarter, + badUserID: "", + panicHandler: panicHandler, } // Clear commands. @@ -285,6 +289,8 @@ func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan e } func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:gocyclo + defer f.handlePanic() + // GODT-1949: Better error events. for _, err := range f.bridge.GetErrors() { switch { @@ -445,6 +451,12 @@ func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:gocyc */ } +func (f *frontendCLI) handlePanic() { + if f.panicHandler != nil { + f.panicHandler.HandlePanic() + } +} + // Loop starts the frontend loop with an interactive shell. func (f *frontendCLI) Loop() error { f.Printf(` diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index 89c6b585..4f308ef3 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -191,6 +191,12 @@ func NewService( return s, nil } +func (s *Service) handlePanic() { + if s.panicHandler != nil { + s.panicHandler.HandlePanic() + } +} + func (s *Service) initAutostart() { s.firstTimeAutostart.Do(func() { shouldAutostartBeOn := s.bridge.GetAutostart() @@ -207,11 +213,14 @@ func (s *Service) Loop() error { if s.parentPID < 0 { s.log.Info("Not monitoring parent PID") } else { - go s.monitorParentPID() + go func() { + defer s.handlePanic() + s.monitorParentPID() + }() } go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() s.watchEvents() }() @@ -221,6 +230,8 @@ func (s *Service) Loop() error { defer close(doneCh) go func() { + defer s.handlePanic() + select { case <-s.quitCh: s.log.Info("Stopping gRPC server") @@ -564,6 +575,8 @@ func (s *Service) monitorParentPID() { s.log.Info("Parent process does not exist anymore. Initiating shutdown") // quit will write to the parentPIDDoneCh, so we launch a goroutine. go func() { + defer s.handlePanic() + if err := s.quit(); err != nil { logrus.WithError(err).Error("Error on quit") } diff --git a/internal/frontend/grpc/service_methods.go b/internal/frontend/grpc/service_methods.go index 251a2d84..be5d7276 100644 --- a/internal/frontend/grpc/service_methods.go +++ b/internal/frontend/grpc/service_methods.go @@ -114,6 +114,8 @@ func (s *Service) Quit(ctx context.Context, empty *emptypb.Empty) (*emptypb.Empt func (s *Service) quit() error { // Windows is notably slow at Quitting. We do it in a goroutine to speed things up a bit. go func() { + defer s.handlePanic() + if s.parentPID >= 0 { s.parentPIDDoneCh <- struct{}{} } @@ -221,7 +223,8 @@ func (s *Service) TriggerReset(ctx context.Context, _ *emptypb.Empty) (*emptypb. s.log.Debug("TriggerReset") go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() + s.triggerReset() }() return &emptypb.Empty{}, nil @@ -316,6 +319,8 @@ func (s *Service) ReportBug(ctx context.Context, report *ReportBugRequest) (*emp }).Debug("ReportBug") go func() { + defer s.handlePanic() + defer func() { _ = s.SendEvent(NewReportBugFinishedEvent()) }() if err := s.bridge.ReportBug( @@ -343,7 +348,7 @@ func (s *Service) ExportTLSCertificates(_ context.Context, folderPath *wrappersp s.log.WithField("folderPath", folderPath).Info("ExportTLSCertificates") go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() cert, key := s.bridge.GetBridgeTLSCert() @@ -379,7 +384,7 @@ func (s *Service) Login(ctx context.Context, login *LoginRequest) (*emptypb.Empt s.log.WithField("username", login.Username).Debug("Login") go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() password, err := base64Decode(login.Password) if err != nil { @@ -435,7 +440,7 @@ func (s *Service) Login2FA(ctx context.Context, login *LoginRequest) (*emptypb.E s.log.WithField("username", login.Username).Debug("Login2FA") go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() if s.auth.UID == "" || s.authClient == nil { s.log.Errorf("Login 2FA: authethication incomplete %s %p", s.auth.UID, s.authClient) @@ -480,7 +485,7 @@ func (s *Service) Login2Passwords(ctx context.Context, login *LoginRequest) (*em s.log.WithField("username", login.Username).Debug("Login2Passwords") go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() password, err := base64Decode(login.Password) if err != nil { @@ -502,7 +507,7 @@ func (s *Service) LoginAbort(ctx context.Context, loginAbort *LoginAbortRequest) s.log.WithField("username", loginAbort.Username).Debug("LoginAbort") go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() s.loginAbort() }() @@ -514,7 +519,7 @@ func (s *Service) CheckUpdate(context.Context, *emptypb.Empty) (*emptypb.Empty, s.log.Debug("CheckUpdate") go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() updateCh, done := s.bridge.GetEvents( events.UpdateAvailable{}, @@ -546,7 +551,7 @@ func (s *Service) InstallUpdate(ctx context.Context, _ *emptypb.Empty) (*emptypb s.log.Debug("InstallUpdate") go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() safe.RLock(func() { s.bridge.InstallUpdate(s.target) @@ -587,6 +592,8 @@ func (s *Service) SetDiskCachePath(ctx context.Context, newPath *wrapperspb.Stri s.log.WithField("path", newPath.Value).Debug("setDiskCachePath") go func() { + defer s.handlePanic() + defer func() { _ = s.SendEvent(NewDiskCachePathChangeFinishedEvent()) }() @@ -652,7 +659,7 @@ func (s *Service) SetMailServerSettings(_ context.Context, settings *ImapSmtpSet Debug("SetConnectionMode") go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() defer func() { _ = s.SendEvent(NewChangeMailServerSettingsFinishedEvent()) }() diff --git a/internal/try/try.go b/internal/try/try.go index 1485c683..c134d5ab 100644 --- a/internal/try/try.go +++ b/internal/try/try.go @@ -21,6 +21,7 @@ import ( "fmt" "sync" + "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/bradenaw/juniper/xerrors" "github.com/sirupsen/logrus" ) @@ -68,17 +69,32 @@ func catch(handlers ...func() error) { } type Group struct { - mu sync.Mutex + mu sync.Mutex + panicHandler async.PanicHandler +} + +func (wg *Group) SetPanicHandler(panicHandler async.PanicHandler) { + wg.panicHandler = panicHandler +} + +func (wg *Group) handlePanic() { + if wg.panicHandler != nil { + wg.panicHandler.HandlePanic() + } } func (wg *Group) GoTry(fn func(bool)) { if wg.mu.TryLock() { go func() { + defer wg.handlePanic() defer wg.mu.Unlock() fn(true) }() } else { - go fn(false) + go func() { + defer wg.handlePanic() + fn(false) + }() } } diff --git a/internal/user/events.go b/internal/user/events.go index f980454a..8f978ed0 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -225,7 +225,7 @@ func (user *User) handleCreateAddressEvent(ctx context.Context, event proton.Add user.updateCh[event.Address.ID] = user.updateCh[primAddr.ID] case vault.SplitMode: - user.updateCh[event.Address.ID] = queue.NewQueuedChannel[imap.Update](0, 0) + user.updateCh[event.Address.ID] = queue.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) } user.eventCh.Enqueue(events.UserAddressCreated{ @@ -284,7 +284,7 @@ func (user *User) handleUpdateAddressEvent(_ context.Context, event proton.Addre user.updateCh[event.Address.ID] = user.updateCh[primAddr.ID] case vault.SplitMode: - user.updateCh[event.Address.ID] = queue.NewQueuedChannel[imap.Update](0, 0) + user.updateCh[event.Address.ID] = queue.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) } user.eventCh.Enqueue(events.UserAddressEnabled{ @@ -594,7 +594,7 @@ func (user *User) handleCreateMessageEvent(ctx context.Context, message proton.M "subject": logging.Sensitive(message.Subject), }).Info("Handling message created event") - full, err := user.client.GetFullMessage(ctx, message.ID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) + full, err := user.client.GetFullMessage(ctx, message.ID, newProtonAPIScheduler(user.panicHandler), proton.NewDefaultAttachmentAllocator()) if err != nil { // If the message is not found, it means that it has been deleted before we could fetch it. if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status == http.StatusUnprocessableEntity { @@ -686,7 +686,7 @@ func (user *User) handleUpdateDraftEvent(ctx context.Context, event proton.Messa "subject": logging.Sensitive(event.Message.Subject), }).Info("Handling draft updated event") - full, err := user.client.GetFullMessage(ctx, event.Message.ID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) + full, err := user.client.GetFullMessage(ctx, event.Message.ID, newProtonAPIScheduler(user.panicHandler), proton.NewDefaultAttachmentAllocator()) if err != nil { // If the message is not found, it means that it has been deleted before we could fetch it. if apiErr := new(proton.APIError); errors.As(err, &apiErr) && apiErr.Status == http.StatusUnprocessableEntity { diff --git a/internal/user/imap.go b/internal/user/imap.go index fb5cdaa3..6e607ddb 100644 --- a/internal/user/imap.go +++ b/internal/user/imap.go @@ -290,7 +290,7 @@ func (conn *imapConnector) CreateMessage( conn.log.WithField("messageID", messageID).Warn("Message already sent") // Query the server-side message. - full, err := conn.client.GetFullMessage(ctx, messageID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) + full, err := conn.client.GetFullMessage(ctx, messageID, newProtonAPIScheduler(conn.panicHandler), proton.NewDefaultAttachmentAllocator()) if err != nil { return imap.Message{}, nil, fmt.Errorf("failed to fetch message: %w", err) } @@ -354,7 +354,7 @@ func (conn *imapConnector) CreateMessage( } func (conn *imapConnector) GetMessageLiteral(ctx context.Context, id imap.MessageID) ([]byte, error) { - msg, err := conn.client.GetFullMessage(ctx, string(id), newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()) + msg, err := conn.client.GetFullMessage(ctx, string(id), newProtonAPIScheduler(conn.panicHandler), proton.NewDefaultAttachmentAllocator()) if err != nil { return nil, err } @@ -572,7 +572,7 @@ func (conn *imapConnector) importMessage( var err error - if full, err = conn.client.GetFullMessage(ctx, messageID, newProtonAPIScheduler(), proton.NewDefaultAttachmentAllocator()); err != nil { + if full, err = conn.client.GetFullMessage(ctx, messageID, newProtonAPIScheduler(conn.panicHandler), proton.NewDefaultAttachmentAllocator()); err != nil { return fmt.Errorf("failed to fetch message: %w", err) } diff --git a/internal/user/smtp.go b/internal/user/smtp.go index 22cc3b66..bcc093f1 100644 --- a/internal/user/smtp.go +++ b/internal/user/smtp.go @@ -48,6 +48,8 @@ import ( // sendMail sends an email from the given address to the given recipients. func (user *User) sendMail(authID string, from string, to []string, r io.Reader) error { + defer user.handlePanic() + return safe.RLockRet(func() error { ctx, cancel := context.WithCancel(context.Background()) defer cancel() @@ -143,7 +145,7 @@ func (user *User) sendMail(authID string, from string, to []string, r io.Reader) } // Send the message using the correct key. - sent, err := sendWithKey( + sent, err := user.sendWithKey( ctx, user.client, user.reporter, @@ -167,7 +169,7 @@ func (user *User) sendMail(authID string, from string, to []string, r io.Reader) } // sendWithKey sends the message with the given address key. -func sendWithKey( +func (user *User) sendWithKey( ctx context.Context, client *proton.Client, sentry reporter.Reporter, @@ -226,12 +228,12 @@ func sendWithKey( return proton.Message{}, fmt.Errorf("failed to create attachments: %w", err) } - attKeys, err := createAttachments(ctx, client, addrKR, draft.ID, message.Attachments) + attKeys, err := user.createAttachments(ctx, client, addrKR, draft.ID, message.Attachments) if err != nil { return proton.Message{}, fmt.Errorf("failed to create attachments: %w", err) } - recipients, err := getRecipients(ctx, client, userKR, settings, draft) + recipients, err := user.getRecipients(ctx, client, userKR, settings, draft) if err != nil { return proton.Message{}, fmt.Errorf("failed to get recipients: %w", err) } @@ -377,7 +379,7 @@ func createDraft( }) } -func createAttachments( +func (user *User) createAttachments( ctx context.Context, client *proton.Client, addrKR *crypto.KeyRing, @@ -390,6 +392,8 @@ func createAttachments( } keys, err := parallel.MapContext(ctx, runtime.NumCPU(), attachments, func(ctx context.Context, att message.Attachment) (attKey, error) { + defer user.handlePanic() + logrus.WithFields(logrus.Fields{ "name": logging.Sensitive(att.Name), "contentID": att.ContentID, @@ -455,7 +459,7 @@ func createAttachments( return attKeys, nil } -func getRecipients( +func (user *User) getRecipients( ctx context.Context, client *proton.Client, userKR *crypto.KeyRing, @@ -467,6 +471,8 @@ func getRecipients( }) prefs, err := parallel.MapContext(ctx, runtime.NumCPU(), addresses, func(ctx context.Context, recipient string) (proton.SendPreferences, error) { + defer user.handlePanic() + pubKeys, recType, err := client.GetPublicKeys(ctx, recipient) if err != nil { return proton.SendPreferences{}, fmt.Errorf("failed to get public key for %v: %w", recipient, err) diff --git a/internal/user/sync.go b/internal/user/sync.go index 215c3b82..6b281386 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -153,7 +153,7 @@ func (user *User) sync(ctx context.Context) error { } // Sync the messages. - if err := syncMessages( + if err := user.syncMessages( ctx, user.ID(), messageIDs, @@ -242,7 +242,7 @@ func toMB(v uint64) float64 { } // nolint:gocyclo -func syncMessages( +func (user *User) syncMessages( ctx context.Context, userID string, messageIDs []string, @@ -370,7 +370,7 @@ func syncMessages( errorCh := make(chan error, maxParallelDownloads*4) // Go routine in charge of downloading message metadata - logging.GoAnnotated(ctx, func(ctx context.Context) { + logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { defer close(downloadCh) const MetadataDataPageSize = 150 @@ -433,14 +433,14 @@ func syncMessages( }, logging.Labels{"sync-stage": "meta-data"}) // Goroutine in charge of downloading and building messages in maxBatchSize batches. - logging.GoAnnotated(ctx, func(ctx context.Context) { + logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { defer close(buildCh) defer close(errorCh) defer func() { logrus.Debugf("sync downloader exit") }() - attachmentDownloader := newAttachmentDownloader(ctx, client, maxParallelDownloads) + attachmentDownloader := user.newAttachmentDownloader(ctx, client, maxParallelDownloads) defer attachmentDownloader.close() for request := range downloadCh { @@ -456,6 +456,8 @@ func syncMessages( } result, err := parallel.MapContext(ctx, maxParallelDownloads, request.ids, func(ctx context.Context, id string) (proton.FullMessage, error) { + defer user.handlePanic() + var result proton.FullMessage msg, err := client.GetMessage(ctx, id) @@ -490,7 +492,7 @@ func syncMessages( }, logging.Labels{"sync-stage": "download"}) // Goroutine which builds messages after they have been downloaded - logging.GoAnnotated(ctx, func(ctx context.Context) { + logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { defer close(flushCh) defer func() { logrus.Debugf("sync builder exit") @@ -509,6 +511,8 @@ func syncMessages( logrus.Debugf("Build request: %v of %v count=%v", index, len(chunks), len(chunk)) result, err := parallel.MapContext(ctx, maxMessagesInParallel, chunk, func(ctx context.Context, msg proton.FullMessage) (*buildRes, error) { + defer user.handlePanic() + return buildRFC822(apiLabels, msg, addrKRs[msg.AddressID], new(bytes.Buffer)), nil }) if err != nil { @@ -526,7 +530,7 @@ func syncMessages( }, logging.Labels{"sync-stage": "builder"}) // Goroutine which converts the messages into updates and builds a waitable structure for progress tracking. - logging.GoAnnotated(ctx, func(ctx context.Context) { + logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { defer close(flushUpdateCh) defer func() { logrus.Debugf("sync flush exit") @@ -771,12 +775,12 @@ func attachmentWorker(ctx context.Context, client *proton.Client, work <-chan at } } -func newAttachmentDownloader(ctx context.Context, client *proton.Client, workerCount int) *attachmentDownloader { +func (user *User) newAttachmentDownloader(ctx context.Context, client *proton.Client, workerCount int) *attachmentDownloader { workerCh := make(chan attachmentJob, (workerCount+2)*workerCount) ctx, cancel := context.WithCancel(ctx) for i := 0; i < workerCount; i++ { workerCh = make(chan attachmentJob) - logging.GoAnnotated(ctx, func(ctx context.Context) { attachmentWorker(ctx, client, workerCh) }, logging.Labels{ + logging.GoAnnotated(ctx, user.panicHandler, func(ctx context.Context) { attachmentWorker(ctx, client, workerCh) }, logging.Labels{ "sync": fmt.Sprintf("att-downloader %v", i), }) } diff --git a/internal/user/types.go b/internal/user/types.go index 09478f5e..3da287fb 100644 --- a/internal/user/types.go +++ b/internal/user/types.go @@ -24,6 +24,7 @@ import ( "strings" "github.com/ProtonMail/go-proton-api" + "github.com/ProtonMail/proton-bridge/v3/internal/async" "golang.org/x/exp/maps" "golang.org/x/exp/slices" ) @@ -93,6 +94,6 @@ func sortSlice[Item any](items []Item, less func(Item, Item) bool) []Item { return sorted } -func newProtonAPIScheduler() proton.Scheduler { - return proton.NewParallelScheduler(runtime.NumCPU() / 2) +func newProtonAPIScheduler(panicHandler async.PanicHandler) proton.Scheduler { + return proton.NewParallelScheduler(runtime.NumCPU()/2, panicHandler) } diff --git a/internal/user/user.go b/internal/user/user.go index 2d0769cb..cd4b14c7 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -91,6 +91,8 @@ type User struct { showAllMail uint32 maxSyncMemory uint64 + + panicHandler async.PanicHandler } // New returns a new user. @@ -127,7 +129,7 @@ func New( reporter: reporter, sendHash: newSendRecorder(sendEntryExpiry), - eventCh: queue.NewQueuedChannel[events.Event](0, 0), + eventCh: queue.NewQueuedChannel[events.Event](0, 0, crashHandler), eventLock: safe.NewRWMutex(), apiUser: apiUser, @@ -148,6 +150,8 @@ func New( showAllMail: b32(showAllMail), maxSyncMemory: maxSyncMemory, + + panicHandler: crashHandler, } // Initialize the user's update channels for its current address mode. @@ -179,7 +183,10 @@ func New( user.goPollAPIEvents = func(wait bool) { doneCh := make(chan struct{}) - go func() { user.pollAPIEventsCh <- doneCh }() + go func() { + defer user.handlePanic() + user.pollAPIEventsCh <- doneCh + }() if wait { <-doneCh @@ -230,6 +237,12 @@ func New( return user, nil } +func (user *User) handlePanic() { + if user.panicHandler != nil { + user.panicHandler.HandlePanic() + } +} + func (user *User) TriggerSync() { user.goSync() } @@ -596,7 +609,7 @@ func (user *User) initUpdateCh(mode vault.AddressMode) { switch mode { case vault.CombinedMode: - primaryUpdateCh := queue.NewQueuedChannel[imap.Update](0, 0) + primaryUpdateCh := queue.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) for addrID := range user.apiAddrs { user.updateCh[addrID] = primaryUpdateCh @@ -604,7 +617,7 @@ func (user *User) initUpdateCh(mode vault.AddressMode) { case vault.SplitMode: for addrID := range user.apiAddrs { - user.updateCh[addrID] = queue.NewQueuedChannel[imap.Update](0, 0) + user.updateCh[addrID] = queue.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) } } } @@ -614,7 +627,7 @@ func (user *User) initUpdateCh(mode vault.AddressMode) { // When we receive an API event, we attempt to handle it. // If successful, we update the event ID in the vault. func (user *User) startEvents(ctx context.Context) { - ticker := proton.NewTicker(EventPeriod, EventJitter) + ticker := proton.NewTicker(EventPeriod, EventJitter, user.panicHandler) defer ticker.Stop() for { diff --git a/internal/user/user_test.go b/internal/user/user_test.go index a9ac6e04..c0888147 100644 --- a/internal/user/user_test.go +++ b/internal/user/user_test.go @@ -119,7 +119,7 @@ func withUser(tb testing.TB, ctx context.Context, _ *server.Server, m *proton.Ma saltedKeyPass, err := salts.SaltForKey([]byte(password), apiUser.Keys.Primary().ID) require.NoError(tb, err) - v, corrupt, err := vault.New(tb.TempDir(), tb.TempDir(), []byte("my secret key")) + v, corrupt, err := vault.New(tb.TempDir(), tb.TempDir(), []byte("my secret key"), nil) require.NoError(tb, err) require.False(tb, corrupt) diff --git a/internal/vault/migrate_test.go b/internal/vault/migrate_test.go index 32af3a19..2d3662e1 100644 --- a/internal/vault/migrate_test.go +++ b/internal/vault/migrate_test.go @@ -25,6 +25,7 @@ import ( "path/filepath" "testing" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/stretchr/testify/require" "github.com/vmihailenco/msgpack/v5" @@ -52,7 +53,7 @@ func TestMigrate(t *testing.T) { require.NoError(t, os.WriteFile(filepath.Join(dir, "vault.enc"), b, 0o600)) // Migrate the vault. - s, corrupt, err := New(dir, "default-gluon-dir", []byte("my secret key")) + s, corrupt, err := New(dir, "default-gluon-dir", []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) diff --git a/internal/vault/settings_test.go b/internal/vault/settings_test.go index 33528fae..e0265798 100644 --- a/internal/vault/settings_test.go +++ b/internal/vault/settings_test.go @@ -22,6 +22,7 @@ import ( "testing" "github.com/Masterminds/semver/v3" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/proton-bridge/v3/internal/updater" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/stretchr/testify/require" @@ -63,7 +64,7 @@ func TestVault_Settings_SMTP(t *testing.T) { func TestVault_Settings_GluonDir(t *testing.T) { // create a new test vault. - s, corrupt, err := vault.New(t.TempDir(), "/path/to/gluon", []byte("my secret key")) + s, corrupt, err := vault.New(t.TempDir(), "/path/to/gluon", []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) diff --git a/internal/vault/vault.go b/internal/vault/vault.go index 4e605e3a..757f5707 100644 --- a/internal/vault/vault.go +++ b/internal/vault/vault.go @@ -29,6 +29,7 @@ import ( "path/filepath" "sync" + "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/bradenaw/juniper/parallel" "github.com/bradenaw/juniper/xslices" "github.com/sirupsen/logrus" @@ -44,10 +45,12 @@ type Vault struct { ref map[string]int refLock sync.Mutex + + panicHandler async.PanicHandler } // New constructs a new encrypted data vault at the given filepath using the given encryption key. -func New(vaultDir, gluonCacheDir string, key []byte) (*Vault, bool, error) { +func New(vaultDir, gluonCacheDir string, key []byte, panicHandler async.PanicHandler) (*Vault, bool, error) { if err := os.MkdirAll(vaultDir, 0o700); err != nil { return nil, false, err } @@ -69,9 +72,17 @@ func New(vaultDir, gluonCacheDir string, key []byte) (*Vault, bool, error) { return nil, false, err } + vault.panicHandler = panicHandler + return vault, corrupt, nil } +func (vault *Vault) handlePanic() { + if vault.panicHandler != nil { + vault.panicHandler.HandlePanic() + } +} + // GetUserIDs returns the user IDs and usernames of all users in the vault. func (vault *Vault) GetUserIDs() []string { return xslices.Map(vault.get().Users, func(user UserData) string { @@ -115,6 +126,8 @@ func (vault *Vault) ForUser(parallelism int, fn func(*User) error) error { userIDs := vault.GetUserIDs() return parallel.DoContext(context.Background(), parallelism, len(userIDs), func(_ context.Context, idx int) error { + defer vault.handlePanic() + user, err := vault.NewUser(userIDs[idx]) if err != nil { return err diff --git a/internal/vault/vault_bench_test.go b/internal/vault/vault_bench_test.go index d4410bc5..c5903ceb 100644 --- a/internal/vault/vault_bench_test.go +++ b/internal/vault/vault_bench_test.go @@ -22,6 +22,7 @@ import ( "runtime" "testing" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/google/uuid" "github.com/stretchr/testify/require" @@ -31,7 +32,7 @@ func BenchmarkVault(b *testing.B) { vaultDir, gluonDir := b.TempDir(), b.TempDir() // Create a new vault. - s, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key")) + s, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(b, err) require.False(b, corrupt) diff --git a/internal/vault/vault_test.go b/internal/vault/vault_test.go index 07b2b329..12fea53d 100644 --- a/internal/vault/vault_test.go +++ b/internal/vault/vault_test.go @@ -22,6 +22,7 @@ import ( "path/filepath" "testing" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/stretchr/testify/require" ) @@ -30,19 +31,19 @@ func TestVault_Corrupt(t *testing.T) { vaultDir, gluonDir := t.TempDir(), t.TempDir() { - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key")) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) } { - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key")) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) } { - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("bad key")) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("bad key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.True(t, corrupt) } @@ -52,13 +53,13 @@ func TestVault_Corrupt_JunkData(t *testing.T) { vaultDir, gluonDir := t.TempDir(), t.TempDir() { - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key")) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) } { - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key")) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) } @@ -71,7 +72,7 @@ func TestVault_Corrupt_JunkData(t *testing.T) { _, err = f.Write([]byte("junk data")) require.NoError(t, err) - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key")) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.True(t, corrupt) } @@ -99,7 +100,7 @@ func TestVault_Reset(t *testing.T) { func newVault(t *testing.T) *vault.Vault { t.Helper() - s, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key")) + s, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"), queue.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) diff --git a/tests/collector_test.go b/tests/collector_test.go index 7df7d7b8..cfcd62f6 100644 --- a/tests/collector_test.go +++ b/tests/collector_test.go @@ -44,7 +44,7 @@ func (c *eventCollector) collectFrom(eventCh <-chan events.Event) <-chan events. c.lock.Lock() defer c.lock.Unlock() - fwdCh := queue.NewQueuedChannel[events.Event](0, 0) + fwdCh := queue.NewQueuedChannel[events.Event](0, 0, queue.NoopPanicHandler{}) c.fwdCh = append(c.fwdCh, fwdCh) @@ -87,7 +87,7 @@ func (c *eventCollector) push(event events.Event) { defer c.lock.Unlock() if _, ok := c.events[reflect.TypeOf(event)]; !ok { - c.events[reflect.TypeOf(event)] = queue.NewQueuedChannel[events.Event](0, 0) + c.events[reflect.TypeOf(event)] = queue.NewQueuedChannel[events.Event](0, 0, queue.NoopPanicHandler{}) } c.events[reflect.TypeOf(event)].Enqueue(event) @@ -102,7 +102,7 @@ func (c *eventCollector) getEventCh(ofType events.Event) <-chan events.Event { defer c.lock.Unlock() if _, ok := c.events[reflect.TypeOf(ofType)]; !ok { - c.events[reflect.TypeOf(ofType)] = queue.NewQueuedChannel[events.Event](0, 0) + c.events[reflect.TypeOf(ofType)] = queue.NewQueuedChannel[events.Event](0, 0, queue.NoopPanicHandler{}) } return c.events[reflect.TypeOf(ofType)].GetChannel() diff --git a/tests/ctx_bridge_test.go b/tests/ctx_bridge_test.go index cb0a2446..7a6edf66 100644 --- a/tests/ctx_bridge_test.go +++ b/tests/ctx_bridge_test.go @@ -108,7 +108,7 @@ func (t *testCtx) initBridge() (<-chan events.Event, error) { } // Create the vault. - vault, corrupt, err := vault.New(vaultDir, gluonCacheDir, t.storeKey) + vault, corrupt, err := vault.New(vaultDir, gluonCacheDir, t.storeKey, queue.NoopPanicHandler{}) if err != nil { return nil, fmt.Errorf("could not create vault: %w", err) } else if corrupt { @@ -301,7 +301,7 @@ func (t *testCtx) initFrontendClient() error { return fmt.Errorf("could not start event stream: %w", err) } - eventCh := queue.NewQueuedChannel[*frontend.StreamEvent](0, 0) + eventCh := queue.NewQueuedChannel[*frontend.StreamEvent](0, 0, queue.NoopPanicHandler{}) go func() { defer eventCh.CloseAndDiscardQueued() diff --git a/tests/ctx_helper_test.go b/tests/ctx_helper_test.go index 04c4c51b..05c5b0a4 100644 --- a/tests/ctx_helper_test.go +++ b/tests/ctx_helper_test.go @@ -23,6 +23,7 @@ import ( "os" "runtime" + "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/bradenaw/juniper/stream" @@ -113,7 +114,7 @@ func (t *testCtx) withAddrKR( return err } - _, addrKRs, err := proton.Unlock(user, addr, keyPass) + _, addrKRs, err := proton.Unlock(user, addr, keyPass, queue.NoopPanicHandler{}) if err != nil { return err } From de5fd07a22cb358f2fac1064beef66630c719bb0 Mon Sep 17 00:00:00 2001 From: Jakub Date: Thu, 30 Mar 2023 17:50:40 +0200 Subject: [PATCH 127/130] feat(GODT-2500): Reorganise async methods. --- Makefile | 2 +- go.mod | 6 +- go.sum | 20 +- internal/app/migration_test.go | 8 +- internal/app/vault.go | 2 +- internal/async/context.go | 82 ------ internal/async/group.go | 233 ------------------ internal/bridge/api.go | 4 +- internal/bridge/api_default.go | 4 +- internal/bridge/api_qa.go | 4 +- internal/bridge/bridge.go | 2 +- internal/bridge/bridge_test.go | 4 +- internal/bridge/imap.go | 2 +- internal/bridge/sync_test.go | 4 +- internal/bridge/user.go | 2 +- internal/bridge/user_event_test.go | 6 +- internal/dialer/dialer_proxy.go | 10 +- internal/dialer/dialer_proxy_provider.go | 16 +- internal/dialer/dialer_proxy_provider_test.go | 26 +- internal/dialer/dialer_proxy_test.go | 22 +- internal/focus/service.go | 12 +- internal/frontend/cli/frontend.go | 10 +- internal/frontend/grpc/service.go | 5 +- internal/frontend/grpc/service_stream.go | 2 +- internal/frontend/grpc/service_user.go | 6 +- internal/try/try.go | 16 +- internal/user/events.go | 6 +- internal/user/smtp.go | 7 +- internal/user/sync.go | 14 +- internal/user/sync_reporter.go | 6 +- internal/user/types.go | 2 +- internal/user/user.go | 25 +- internal/vault/migrate_test.go | 4 +- internal/vault/settings_test.go | 4 +- internal/vault/vault.go | 10 +- internal/vault/vault_bench_test.go | 4 +- internal/vault/vault_test.go | 16 +- tests/collector_test.go | 14 +- tests/ctx_bridge_test.go | 12 +- tests/ctx_helper_test.go | 4 +- tests/ctx_test.go | 4 +- utils/vault-editor/main.go | 5 +- 42 files changed, 136 insertions(+), 511 deletions(-) delete mode 100644 internal/async/context.go delete mode 100644 internal/async/group.go diff --git a/Makefile b/Makefile index c08dfb35..b5715507 100644 --- a/Makefile +++ b/Makefile @@ -253,7 +253,7 @@ coverage: test mocks: mockgen --package mocks github.com/ProtonMail/proton-bridge/v3/internal/bridge TLSReporter,ProxyController,Autostarter > tmp mv tmp internal/bridge/mocks/mocks.go - mockgen --package mocks github.com/ProtonMail/proton-bridge/v3/internal/async PanicHandler > internal/bridge/mocks/async_mocks.go + mockgen --package mocks github.com/ProtonMail/gluon/async PanicHandler > internal/bridge/mocks/async_mocks.go mockgen --package mocks github.com/ProtonMail/gluon/reporter Reporter > internal/bridge/mocks/gluon_mocks.go mockgen --package mocks github.com/ProtonMail/proton-bridge/v3/internal/updater Downloader,Installer > internal/updater/mocks/mocks.go diff --git a/go.mod b/go.mod index aa13f862..66927c0d 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,9 @@ go 1.18 require ( github.com/0xAX/notificator v0.0.0-20220220101646-ee9b8921e557 github.com/Masterminds/semver/v3 v3.2.0 - github.com/ProtonMail/gluon v0.15.1-0.20230329124608-19b8f7b4e7b0 + github.com/ProtonMail/gluon v0.15.1-0.20230331095629-e23a7a1be2a8 github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a - github.com/ProtonMail/go-proton-api v0.4.1-0.20230327135835-2751384cef6f + github.com/ProtonMail/go-proton-api v0.4.1-0.20230331115846-7ba084061eaa github.com/ProtonMail/gopenpgp/v2 v2.5.2 github.com/PuerkitoBio/goquery v1.8.1 github.com/abiosoft/ishell v2.0.0+incompatible @@ -125,8 +125,6 @@ require ( ) replace ( - github.com/ProtonMail/gluon => /home/dev/gopath18/src/gluon - github.com/ProtonMail/go-proton-api => /home/dev/gopath18/src/go-proton-api github.com/docker/docker-credential-helpers => github.com/ProtonMail/docker-credential-helpers v1.1.0 github.com/emersion/go-message => github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 github.com/keybase/go-keychain => github.com/cuthix/go-keychain v0.0.0-20220405075754-31e7cee908fe diff --git a/go.sum b/go.sum index 3d09459d..1466ca35 100644 --- a/go.sum +++ b/go.sum @@ -28,12 +28,8 @@ github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf h1:yc9daCCYUefEs github.com/ProtonMail/bcrypt v0.0.0-20211005172633-e235017c1baf/go.mod h1:o0ESU9p83twszAU8LBeJKFAAMX14tISa0yk4Oo5TOqo= github.com/ProtonMail/docker-credential-helpers v1.1.0 h1:+kvUIpwWcbtP3WFv5sSvkFn/XLzSqPOB5AAthuk9xPk= github.com/ProtonMail/docker-credential-helpers v1.1.0/go.mod h1:mK0aBveCxhnQ756AmaTfXMZDeULvheYVhF/MWMErN5g= -github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1 h1:zVKqnKO/vTMrVw1dleGsj1JlY9jbhK890X0htvGCbjY= -github.com/ProtonMail/gluon v0.15.1-0.20230321074233-2d09826346c1/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= -github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546 h1:eJ8gO99EjpuGoUDI0R2VZSzQ7SGPD0ggTbjJaA0xtzE= -github.com/ProtonMail/gluon v0.15.1-0.20230322121010-574da2df3546/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= -github.com/ProtonMail/gluon v0.15.1-0.20230329124608-19b8f7b4e7b0 h1:FASrdEaNRJSHFjrOZ5WO4CKuYZb2zoCyFNqplrsZmOQ= -github.com/ProtonMail/gluon v0.15.1-0.20230329124608-19b8f7b4e7b0/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= +github.com/ProtonMail/gluon v0.15.1-0.20230331095629-e23a7a1be2a8 h1:USMR8imbxkP4Ailch4ceV3hCZTaANMIGHhb5rpZFYn4= +github.com/ProtonMail/gluon v0.15.1-0.20230331095629-e23a7a1be2a8/go.mod h1:yA4hk6CJw0BMo+YL8Y3ckCYs5L20sysu9xseshwY3QI= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a h1:D+aZah+k14Gn6kmL7eKxoo/4Dr/lK3ChBcwce2+SQP4= github.com/ProtonMail/go-autostart v0.0.0-20210130080809-00ed301c8e9a/go.mod h1:oTGdE7/DlWIr23G0IKW3OXK9wZ5Hw1GGiaJFccTvZi4= github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo= @@ -44,16 +40,8 @@ github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753 h1:I8IsYA297 github.com/ProtonMail/go-message v0.0.0-20210611055058-fabeff2ec753/go.mod h1:NBAn21zgCJ/52WLDyed18YvYFm5tEoeDauubFqLokM4= github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08 h1:dS7r5z4iGS0qCjM7UwWdsEMzQesUQbGcXdSm2/tWboA= github.com/ProtonMail/go-mime v0.0.0-20221031134845-8fd9bc37cf08/go.mod h1:qRZgbeASl2a9OwmsV85aWwRqic0NHPh+9ewGAzb4cgM= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9 h1:RyOYt/rc3hQtIKFUDJObah2g8wouIFVTorou5mmIHQI= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230321105122-1945ba8a46f9/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230323120945-5a6ef5a2ecdd h1:Y/XKWw0s7DDJn5R1lJmsREeGyumLcn/RDcvLozYnB88= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230323120945-5a6ef5a2ecdd/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230324123811-83e98cb35c9a h1:sKcw8YlNxqO9iDDYdbZNVUCqk6Ta6liyfFBUR0Lai7o= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230324123811-83e98cb35c9a/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230327062918-71c20587e0fc h1:D0F4mxNVwIzYcjt8SEuIh4EzJhWgWw1f4eNc1iWrXnQ= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230327062918-71c20587e0fc/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230327135835-2751384cef6f h1:lqf3DlFQMvfDi7zGVKTlciyxXfvkoi6CCISu9nx8nak= -github.com/ProtonMail/go-proton-api v0.4.1-0.20230327135835-2751384cef6f/go.mod h1:4AXhqhB+AGVasVIlift9Lr1Btxg5S83xXPiyiT7mKUc= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230331115846-7ba084061eaa h1:0JKWkz/gIYf+eky0dCFeBWrjEDLf59lS8HOlXtvn6Nk= +github.com/ProtonMail/go-proton-api v0.4.1-0.20230331115846-7ba084061eaa/go.mod h1:RfpLBcTIhfjOIcBhh7f36LtAOEi0mqPd3t8gyLWmCZM= github.com/ProtonMail/go-srp v0.0.5 h1:xhUioxZgDbCnpo9JehyFhwwsn9JLWkUGfB0oiKXgiGg= github.com/ProtonMail/go-srp v0.0.5/go.mod h1:06iYHtLXW8vjLtccWj++x3MKy65sIT8yZd7nrJF49rs= github.com/ProtonMail/gopenpgp/v2 v2.5.2 h1:97SjlWNAxXl9P22lgwgrZRshQdiEfAht0g3ZoiA1GCw= diff --git a/internal/app/migration_test.go b/internal/app/migration_test.go index c994ed63..e25f2a59 100644 --- a/internal/app/migration_test.go +++ b/internal/app/migration_test.go @@ -25,7 +25,7 @@ import ( "runtime" "testing" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/cookies" @@ -41,7 +41,7 @@ import ( func TestMigratePrefsToVaultWithKeys(t *testing.T) { // Create a new vault. - vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"), queue.NoopPanicHandler{}) + vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) @@ -62,7 +62,7 @@ func TestMigratePrefsToVaultWithKeys(t *testing.T) { func TestMigratePrefsToVaultWithoutKeys(t *testing.T) { // Create a new vault. - vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"), queue.NoopPanicHandler{}) + vault, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) @@ -174,7 +174,7 @@ func TestUserMigration(t *testing.T) { token, err := crypto.RandomToken(32) require.NoError(t, err) - v, corrupt, err := vault.New(settingsFolder, settingsFolder, token, queue.NoopPanicHandler{}) + v, corrupt, err := vault.New(settingsFolder, settingsFolder, token, async.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) diff --git a/internal/app/vault.go b/internal/app/vault.go index 013653a5..b194fcae 100644 --- a/internal/app/vault.go +++ b/internal/app/vault.go @@ -21,7 +21,7 @@ import ( "fmt" "path" - "github.com/ProtonMail/proton-bridge/v3/internal/async" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/proton-bridge/v3/internal/certs" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/locations" diff --git a/internal/async/context.go b/internal/async/context.go deleted file mode 100644 index becf9426..00000000 --- a/internal/async/context.go +++ /dev/null @@ -1,82 +0,0 @@ -// Copyright (c) 2023 Proton AG -// -// This file is part of Proton Mail Bridge. -// -// Proton Mail Bridge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Proton Mail Bridge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Proton Mail Bridge. If not, see . - -package async - -import ( - "context" - "sync" -) - -// Abortable collects groups of functions that can be aborted by calling Abort. -type Abortable struct { - abortFunc []context.CancelFunc - abortLock sync.RWMutex -} - -func (a *Abortable) Do(ctx context.Context, fn func(context.Context)) { - fn(a.newCancelCtx(ctx)) -} - -func (a *Abortable) Abort() { - a.abortLock.RLock() - defer a.abortLock.RUnlock() - - for _, fn := range a.abortFunc { - fn() - } -} - -func (a *Abortable) newCancelCtx(ctx context.Context) context.Context { - a.abortLock.Lock() - defer a.abortLock.Unlock() - - ctx, cancel := context.WithCancel(ctx) - - a.abortFunc = append(a.abortFunc, cancel) - - return ctx -} - -// RangeContext iterates over the given channel until the context is canceled or the -// channel is closed. -func RangeContext[T any](ctx context.Context, ch <-chan T, fn func(T)) { - for { - select { - case v, ok := <-ch: - if !ok { - return - } - - fn(v) - - case <-ctx.Done(): - return - } - } -} - -// ForwardContext forwards all values from the src channel to the dst channel until the -// context is canceled or the src channel is closed. -func ForwardContext[T any](ctx context.Context, dst chan<- T, src <-chan T) { - RangeContext(ctx, src, func(v T) { - select { - case dst <- v: - case <-ctx.Done(): - } - }) -} diff --git a/internal/async/group.go b/internal/async/group.go deleted file mode 100644 index 1479ab89..00000000 --- a/internal/async/group.go +++ /dev/null @@ -1,233 +0,0 @@ -// Copyright (c) 2023 Proton AG -// -// This file is part of Proton Mail Bridge. -// -// Proton Mail Bridge is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Proton Mail Bridge is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Proton Mail Bridge. If not, see . - -package async - -import ( - "context" - "math/rand" - "sync" - "time" -) - -type PanicHandler interface { - HandlePanic() -} - -// Group is forked and improved version of "github.com/bradenaw/juniper/xsync.Group". -// -// It manages a group of goroutines. The main change to original is posibility -// to wait passed function to finish without canceling it's context and adding -// PanicHandler. -type Group struct { - baseCtx context.Context - ctx context.Context - jobCtx context.Context - cancel context.CancelFunc - finish context.CancelFunc - wg sync.WaitGroup - - panicHandler PanicHandler -} - -// NewGroup returns a Group ready for use. The context passed to any of the f functions will be a -// descendant of ctx. -func NewGroup(ctx context.Context, panicHandler PanicHandler) *Group { - bgCtx, cancel := context.WithCancel(ctx) - jobCtx, finish := context.WithCancel(ctx) - return &Group{ - baseCtx: ctx, - ctx: bgCtx, - jobCtx: jobCtx, - cancel: cancel, - finish: finish, - panicHandler: panicHandler, - } -} - -// Once calls f once from another goroutine. -func (g *Group) Once(f func(ctx context.Context)) { - g.wg.Add(1) - go func() { - defer g.handlePanic() - - f(g.ctx) - g.wg.Done() - }() -} - -// jitterDuration returns a random duration in [d - jitter, d + jitter]. -func jitterDuration(d time.Duration, jitter time.Duration) time.Duration { - return d + time.Duration(float64(jitter)*((rand.Float64()*2)-1)) //nolint:gosec -} - -// Periodic spawns a goroutine that calls f once per interval +/- jitter. -func (g *Group) Periodic( - interval time.Duration, - jitter time.Duration, - f func(ctx context.Context), -) { - g.wg.Add(1) - go func() { - defer g.handlePanic() - - defer g.wg.Done() - - t := time.NewTimer(jitterDuration(interval, jitter)) - defer t.Stop() - - for { - if g.ctx.Err() != nil { - return - } - - select { - case <-g.jobCtx.Done(): - return - case <-t.C: - } - - t.Reset(jitterDuration(interval, jitter)) - f(g.ctx) - } - }() -} - -// Trigger spawns a goroutine which calls f whenever the returned function is called. If f is -// already running when triggered, f will run again immediately when it finishes. -func (g *Group) Trigger(f func(ctx context.Context)) func() { - c := make(chan struct{}, 1) - g.wg.Add(1) - go func() { - defer g.handlePanic() - - defer g.wg.Done() - - for { - if g.ctx.Err() != nil { - return - } - select { - case <-g.jobCtx.Done(): - return - case <-c: - } - f(g.ctx) - } - }() - - return func() { - select { - case c <- struct{}{}: - default: - } - } -} - -// PeriodicOrTrigger spawns a goroutine which calls f whenever the returned function is called. If -// f is already running when triggered, f will run again immediately when it finishes. Also calls f -// when it has been interval+/-jitter since the last trigger. -func (g *Group) PeriodicOrTrigger( - interval time.Duration, - jitter time.Duration, - f func(ctx context.Context), -) func() { - c := make(chan struct{}, 1) - g.wg.Add(1) - go func() { - defer g.handlePanic() - - defer g.wg.Done() - - t := time.NewTimer(jitterDuration(interval, jitter)) - defer t.Stop() - - for { - if g.ctx.Err() != nil { - return - } - select { - case <-g.jobCtx.Done(): - return - case <-t.C: - t.Reset(jitterDuration(interval, jitter)) - case <-c: - if !t.Stop() { - <-t.C - } - t.Reset(jitterDuration(interval, jitter)) - } - f(g.ctx) - } - }() - - return func() { - select { - case c <- struct{}{}: - default: - } - } -} - -func (g *Group) resetCtx() { - g.jobCtx, g.finish = context.WithCancel(g.baseCtx) - g.ctx, g.cancel = context.WithCancel(g.baseCtx) -} - -// Cancel is send to all of the spawn goroutines and ends periodic -// or trigger routines. -func (g *Group) Cancel() { - g.cancel() - g.finish() - g.resetCtx() -} - -// Finish will ends all periodic or polls routines. It will let -// currently running functions to finish (cancel is not sent). -// -// It is not safe to call Wait concurrently with any other method on g. -func (g *Group) Finish() { - g.finish() - g.jobCtx, g.finish = context.WithCancel(g.baseCtx) -} - -// CancelAndWait cancels the context passed to any of the spawned goroutines and waits for all spawned -// goroutines to exit. -// -// It is not safe to call Wait concurrently with any other method on g. -func (g *Group) CancelAndWait() { - g.finish() - g.cancel() - g.wg.Wait() - g.resetCtx() -} - -// WaitToFinish will ends all periodic or polls routines. It will wait for -// currently running functions to finish (cancel is not sent). -// -// It is not safe to call Wait concurrently with any other method on g. -func (g *Group) WaitToFinish() { - g.finish() - g.wg.Wait() - g.jobCtx, g.finish = context.WithCancel(g.baseCtx) -} - -func (g *Group) handlePanic() { - if g.panicHandler != nil { - g.panicHandler.HandlePanic() - } -} diff --git a/internal/bridge/api.go b/internal/bridge/api.go index f7c3d41a..dd397992 100644 --- a/internal/bridge/api.go +++ b/internal/bridge/api.go @@ -21,7 +21,7 @@ import ( "net/http" "github.com/Masterminds/semver/v3" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/sirupsen/logrus" @@ -33,7 +33,7 @@ func defaultAPIOptions( version *semver.Version, cookieJar http.CookieJar, transport http.RoundTripper, - panicHandler queue.PanicHandler, + panicHandler async.PanicHandler, ) []proton.Option { return []proton.Option{ proton.WithHostURL(apiURL), diff --git a/internal/bridge/api_default.go b/internal/bridge/api_default.go index cc89fe16..244543f8 100644 --- a/internal/bridge/api_default.go +++ b/internal/bridge/api_default.go @@ -23,7 +23,7 @@ import ( "net/http" "github.com/Masterminds/semver/v3" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/go-proton-api" ) @@ -33,7 +33,7 @@ func newAPIOptions( version *semver.Version, cookieJar http.CookieJar, transport http.RoundTripper, - panicHandler queue.PanicHandler, + panicHandler async.PanicHandler, ) []proton.Option { return defaultAPIOptions(apiURL, version, cookieJar, transport, panicHandler) } diff --git a/internal/bridge/api_qa.go b/internal/bridge/api_qa.go index a8c5a71a..db342811 100644 --- a/internal/bridge/api_qa.go +++ b/internal/bridge/api_qa.go @@ -24,7 +24,7 @@ import ( "os" "github.com/Masterminds/semver/v3" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/go-proton-api" ) @@ -34,7 +34,7 @@ func newAPIOptions( version *semver.Version, cookieJar http.CookieJar, transport http.RoundTripper, - panicHandler queue.PanicHandler, + panicHandler async.PanicHandler, ) []proton.Option { opt := defaultAPIOptions(apiURL, version, cookieJar, transport, panicHandler) diff --git a/internal/bridge/bridge.go b/internal/bridge/bridge.go index 0eba71fc..f675cbe7 100644 --- a/internal/bridge/bridge.go +++ b/internal/bridge/bridge.go @@ -30,12 +30,12 @@ import ( "github.com/Masterminds/semver/v3" "github.com/ProtonMail/gluon" + "github.com/ProtonMail/gluon/async" imapEvents "github.com/ProtonMail/gluon/events" "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/gluon/watcher" "github.com/ProtonMail/go-proton-api" - "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/focus" diff --git a/internal/bridge/bridge_test.go b/internal/bridge/bridge_test.go index 28778cd5..b6191a3d 100644 --- a/internal/bridge/bridge_test.go +++ b/internal/bridge/bridge_test.go @@ -30,8 +30,8 @@ import ( "time" "github.com/Masterminds/semver/v3" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/imap" - "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" "github.com/ProtonMail/go-proton-api/server/backend" @@ -700,7 +700,7 @@ func withBridgeNoMocks( require.NoError(t, err) // Create the vault. - vault, _, err := vault.New(vaultDir, t.TempDir(), vaultKey, queue.NoopPanicHandler{}) + vault, _, err := vault.New(vaultDir, t.TempDir(), vaultKey, async.NoopPanicHandler{}) require.NoError(t, err) // Create a new cookie jar. diff --git a/internal/bridge/imap.go b/internal/bridge/imap.go index 752155dd..bdd51845 100644 --- a/internal/bridge/imap.go +++ b/internal/bridge/imap.go @@ -27,12 +27,12 @@ import ( "github.com/Masterminds/semver/v3" "github.com/ProtonMail/gluon" + "github.com/ProtonMail/gluon/async" imapEvents "github.com/ProtonMail/gluon/events" "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/gluon/store" "github.com/ProtonMail/gluon/store/fallback_v0" - "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/logging" diff --git a/internal/bridge/sync_test.go b/internal/bridge/sync_test.go index e0ffe1c8..a83dac42 100644 --- a/internal/bridge/sync_test.go +++ b/internal/bridge/sync_test.go @@ -28,7 +28,7 @@ import ( "testing" "time" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" @@ -429,7 +429,7 @@ func createMessages(ctx context.Context, t *testing.T, c *proton.Client, addrID, keyPass, err := salt.SaltForKey(password, user.Keys.Primary().ID) require.NoError(t, err) - _, addrKRs, err := proton.Unlock(user, addr, keyPass, queue.NoopPanicHandler{}) + _, addrKRs, err := proton.Unlock(user, addr, keyPass, async.NoopPanicHandler{}) require.NoError(t, err) _, ok := addrKRs[addrID] diff --git a/internal/bridge/user.go b/internal/bridge/user.go index 4bdb6152..5f2a2f1e 100644 --- a/internal/bridge/user.go +++ b/internal/bridge/user.go @@ -23,10 +23,10 @@ import ( "fmt" "runtime" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/go-proton-api" - "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/logging" "github.com/ProtonMail/proton-bridge/v3/internal/safe" diff --git a/internal/bridge/user_event_test.go b/internal/bridge/user_event_test.go index 616f492c..2cc777d2 100644 --- a/internal/bridge/user_event_test.go +++ b/internal/bridge/user_event_test.go @@ -28,7 +28,7 @@ import ( "testing" "time" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/rfc822" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" @@ -475,7 +475,7 @@ func TestBridge_User_UpdateDraftAndCreateOtherMessage(t *testing.T) { keyPass, err := salts.SaltForKey(password, user.Keys.Primary().ID) require.NoError(t, err) - _, addrKRs, err := proton.Unlock(user, addrs, keyPass, queue.NoopPanicHandler{}) + _, addrKRs, err := proton.Unlock(user, addrs, keyPass, async.NoopPanicHandler{}) require.NoError(t, err) // Create a draft (generating a "create draft message" event). @@ -557,7 +557,7 @@ func TestBridge_User_SendDraftRemoveDraftFlag(t *testing.T) { keyPass, err := salts.SaltForKey(password, user.Keys.Primary().ID) require.NoError(t, err) - _, addrKRs, err := proton.Unlock(user, addrs, keyPass, queue.NoopPanicHandler{}) + _, addrKRs, err := proton.Unlock(user, addrs, keyPass, async.NoopPanicHandler{}) require.NoError(t, err) // Create a draft (generating a "create draft message" event). diff --git a/internal/dialer/dialer_proxy.go b/internal/dialer/dialer_proxy.go index 0ce2945e..453c9d05 100644 --- a/internal/dialer/dialer_proxy.go +++ b/internal/dialer/dialer_proxy.go @@ -24,7 +24,7 @@ import ( "sync" "time" - "github.com/ProtonMail/proton-bridge/v3/internal/async" + "github.com/ProtonMail/gluon/async" "github.com/pkg/errors" "github.com/sirupsen/logrus" ) @@ -79,12 +79,6 @@ func formatAsAddress(rawURL string) string { return net.JoinHostPort(host, port) } -func (d *ProxyTLSDialer) handlePanic() { - if d.panicHandler != nil { - d.panicHandler.HandlePanic() - } -} - // DialTLSContext dials the given network/address. If it fails, it retries using a proxy. func (d *ProxyTLSDialer) DialTLSContext(ctx context.Context, network, address string) (net.Conn, error) { d.locker.RLock() @@ -139,7 +133,7 @@ func (d *ProxyTLSDialer) switchToReachableServer() error { // This means we want to disable it again in 24 hours. if d.proxyAddress == d.directAddress { go func() { - defer d.handlePanic() + defer async.HandlePanic(d.panicHandler) <-time.After(d.proxyUseDuration) diff --git a/internal/dialer/dialer_proxy_provider.go b/internal/dialer/dialer_proxy_provider.go index e4006891..244b437a 100644 --- a/internal/dialer/dialer_proxy_provider.go +++ b/internal/dialer/dialer_proxy_provider.go @@ -24,7 +24,7 @@ import ( "sync" "time" - "github.com/ProtonMail/proton-bridge/v3/internal/async" + "github.com/ProtonMail/gluon/async" "github.com/go-resty/resty/v2" "github.com/miekg/dns" "github.com/pkg/errors" @@ -92,12 +92,6 @@ func newProxyProvider(dialer TLSDialer, hostURL string, providers []string, pani return } -func (p *proxyProvider) handlePanic() { - if p.panicHandler != nil { - p.panicHandler.HandlePanic() - } -} - // findReachableServer returns a working API server (either proxy or standard API). func (p *proxyProvider) findReachableServer() (proxy string, err error) { logrus.Debug("Trying to find a reachable server") @@ -119,13 +113,13 @@ func (p *proxyProvider) findReachableServer() (proxy string, err error) { wg.Add(2) go func() { - defer p.handlePanic() + defer async.HandlePanic(p.panicHandler) defer wg.Done() apiReachable = p.canReach(p.hostURL) }() go func() { - defer p.handlePanic() + defer async.HandlePanic(p.panicHandler) defer wg.Done() err = p.refreshProxyCache() }() @@ -162,7 +156,7 @@ func (p *proxyProvider) refreshProxyCache() error { resultChan := make(chan []string) go func() { - defer p.handlePanic() + defer async.HandlePanic(p.panicHandler) for _, provider := range p.providers { if proxies, err := p.dohLookup(ctx, p.query, provider); err == nil { @@ -217,7 +211,7 @@ func (p *proxyProvider) defaultDoHLookup(ctx context.Context, query, dohProvider dataChan, errChan := make(chan []string), make(chan error) go func() { - defer p.handlePanic() + defer async.HandlePanic(p.panicHandler) // Build new DNS request in RFC1035 format. dnsRequest := new(dns.Msg).SetQuestion(dns.Fqdn(query), dns.TypeTXT) diff --git a/internal/dialer/dialer_proxy_provider_test.go b/internal/dialer/dialer_proxy_provider_test.go index ddd7aed2..5c25c4bb 100644 --- a/internal/dialer/dialer_proxy_provider_test.go +++ b/internal/dialer/dialer_proxy_provider_test.go @@ -23,7 +23,7 @@ import ( "testing" "time" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/proton-bridge/v3/internal/useragent" r "github.com/stretchr/testify/require" ) @@ -32,7 +32,7 @@ func TestProxyProvider_FindProxy(t *testing.T) { proxy := getTrustedServer() defer closeServer(proxy) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, queue.NoopPanicHandler{}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, async.NoopPanicHandler{}) p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{proxy.URL}, nil } url, err := p.findReachableServer() @@ -48,7 +48,7 @@ func TestProxyProvider_FindProxy_ChooseReachableProxy(t *testing.T) { unreachableProxy := getTrustedServer() closeServer(unreachableProxy) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, queue.NoopPanicHandler{}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, async.NoopPanicHandler{}) p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{reachableProxy.URL, unreachableProxy.URL}, nil } @@ -69,7 +69,7 @@ func TestProxyProvider_FindProxy_ChooseTrustedProxy(t *testing.T) { checker := NewTLSPinChecker(TrustedAPIPins) dialer := NewPinningTLSDialer(NewBasicTLSDialer(""), reporter, checker) - p := newProxyProvider(dialer, "", []string{"not used"}, queue.NoopPanicHandler{}) + p := newProxyProvider(dialer, "", []string{"not used"}, async.NoopPanicHandler{}) p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{untrustedProxy.URL, trustedProxy.URL}, nil } @@ -86,7 +86,7 @@ func TestProxyProvider_FindProxy_FailIfNoneReachable(t *testing.T) { unreachableProxy2 := getTrustedServer() closeServer(unreachableProxy2) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, queue.NoopPanicHandler{}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, async.NoopPanicHandler{}) p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{unreachableProxy1.URL, unreachableProxy2.URL}, nil } @@ -106,7 +106,7 @@ func TestProxyProvider_FindProxy_FailIfNoneTrusted(t *testing.T) { checker := NewTLSPinChecker(TrustedAPIPins) dialer := NewPinningTLSDialer(NewBasicTLSDialer(""), reporter, checker) - p := newProxyProvider(dialer, "", []string{"not used"}, queue.NoopPanicHandler{}) + p := newProxyProvider(dialer, "", []string{"not used"}, async.NoopPanicHandler{}) p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{untrustedProxy1.URL, untrustedProxy2.URL}, nil } @@ -116,7 +116,7 @@ func TestProxyProvider_FindProxy_FailIfNoneTrusted(t *testing.T) { } func TestProxyProvider_FindProxy_RefreshCacheTimeout(t *testing.T) { - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, queue.NoopPanicHandler{}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, async.NoopPanicHandler{}) p.cacheRefreshTimeout = 1 * time.Second p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { time.Sleep(2 * time.Second); return nil, nil } @@ -133,7 +133,7 @@ func TestProxyProvider_FindProxy_CanReachTimeout(t *testing.T) { })) defer closeServer(slowProxy) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, queue.NoopPanicHandler{}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"not used"}, async.NoopPanicHandler{}) p.canReachTimeout = 1 * time.Second p.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{slowProxy.URL}, nil } @@ -145,7 +145,7 @@ func TestProxyProvider_FindProxy_CanReachTimeout(t *testing.T) { } func TestProxyProvider_DoHLookup_Quad9(t *testing.T) { - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, queue.NoopPanicHandler{}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, async.NoopPanicHandler{}) records, err := p.dohLookup(context.Background(), proxyQuery, Quad9Provider) r.NoError(t, err) @@ -156,7 +156,7 @@ func TestProxyProvider_DoHLookup_Quad9(t *testing.T) { // port filter. Basic functionality should be covered by other tests. Keeping // code here to be able to run it locally if needed. func DISABLEDTestProxyProviderDoHLookupQuad9Port(t *testing.T) { - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, queue.NoopPanicHandler{}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, async.NoopPanicHandler{}) records, err := p.dohLookup(context.Background(), proxyQuery, Quad9PortProvider) r.NoError(t, err) @@ -164,7 +164,7 @@ func DISABLEDTestProxyProviderDoHLookupQuad9Port(t *testing.T) { } func TestProxyProvider_DoHLookup_Google(t *testing.T) { - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, queue.NoopPanicHandler{}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, async.NoopPanicHandler{}) records, err := p.dohLookup(context.Background(), proxyQuery, GoogleProvider) r.NoError(t, err) @@ -174,7 +174,7 @@ func TestProxyProvider_DoHLookup_Google(t *testing.T) { func TestProxyProvider_DoHLookup_FindProxy(t *testing.T) { skipIfProxyIsSet(t) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, queue.NoopPanicHandler{}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{Quad9Provider, GoogleProvider}, async.NoopPanicHandler{}) url, err := p.findReachableServer() r.NoError(t, err) @@ -184,7 +184,7 @@ func TestProxyProvider_DoHLookup_FindProxy(t *testing.T) { func TestProxyProvider_DoHLookup_FindProxyFirstProviderUnreachable(t *testing.T) { skipIfProxyIsSet(t) - p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"https://unreachable", Quad9Provider, GoogleProvider}, queue.NoopPanicHandler{}) + p := newProxyProvider(NewBasicTLSDialer(""), "", []string{"https://unreachable", Quad9Provider, GoogleProvider}, async.NoopPanicHandler{}) url, err := p.findReachableServer() r.NoError(t, err) diff --git a/internal/dialer/dialer_proxy_test.go b/internal/dialer/dialer_proxy_test.go index a78b3055..3fe72b12 100644 --- a/internal/dialer/dialer_proxy_test.go +++ b/internal/dialer/dialer_proxy_test.go @@ -25,7 +25,7 @@ import ( "testing" "time" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/stretchr/testify/require" ) @@ -142,8 +142,8 @@ func TestProxyDialer_UseProxy(t *testing.T) { trustedProxy := getTrustedServer() defer closeServer(trustedProxy) - provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, queue.NoopPanicHandler{}) - d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", queue.NoopPanicHandler{}) + provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, async.NoopPanicHandler{}) + d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", async.NoopPanicHandler{}) d.proxyProvider = provider provider.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{trustedProxy.URL}, nil } @@ -160,8 +160,8 @@ func TestProxyDialer_UseProxy_MultipleTimes(t *testing.T) { proxy3 := getTrustedServer() defer closeServer(proxy3) - provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, queue.NoopPanicHandler{}) - d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", queue.NoopPanicHandler{}) + provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, async.NoopPanicHandler{}) + d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", async.NoopPanicHandler{}) d.proxyProvider = provider provider.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{proxy1.URL}, nil } @@ -190,8 +190,8 @@ func TestProxyDialer_UseProxy_RevertAfterTime(t *testing.T) { trustedProxy := getTrustedServer() defer closeServer(trustedProxy) - provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, queue.NoopPanicHandler{}) - d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", queue.NoopPanicHandler{}) + provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, async.NoopPanicHandler{}) + d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", async.NoopPanicHandler{}) d.proxyProvider = provider d.proxyUseDuration = time.Second @@ -213,8 +213,8 @@ func TestProxyDialer_UseProxy_RevertAfterTime(t *testing.T) { func TestProxyDialer_UseProxy_RevertIfProxyStopsWorkingAndOriginalAPIIsReachable(t *testing.T) { trustedProxy := getTrustedServer() - provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, queue.NoopPanicHandler{}) - d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", queue.NoopPanicHandler{}) + provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, async.NoopPanicHandler{}) + d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", async.NoopPanicHandler{}) d.proxyProvider = provider provider.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{trustedProxy.URL}, nil } @@ -243,8 +243,8 @@ func TestProxyDialer_UseProxy_FindSecondAlternativeIfFirstFailsAndAPIIsStillBloc proxy2 := getTrustedServer() defer closeServer(proxy2) - provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, queue.NoopPanicHandler{}) - d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", queue.NoopPanicHandler{}) + provider := newProxyProvider(NewBasicTLSDialer(""), "", DoHProviders, async.NoopPanicHandler{}) + d := NewProxyTLSDialer(NewBasicTLSDialer(""), "", async.NoopPanicHandler{}) d.proxyProvider = provider provider.dohLookup = func(ctx context.Context, q, p string) ([]string, error) { return []string{proxy1.URL, proxy2.URL}, nil } diff --git a/internal/focus/service.go b/internal/focus/service.go index ad0395d1..a4f7b885 100644 --- a/internal/focus/service.go +++ b/internal/focus/service.go @@ -24,7 +24,7 @@ import ( "net" "github.com/Masterminds/semver/v3" - "github.com/ProtonMail/proton-bridge/v3/internal/async" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/proton-bridge/v3/internal/focus/proto" "github.com/ProtonMail/proton-bridge/v3/internal/service" "github.com/sirupsen/logrus" @@ -77,7 +77,7 @@ func NewService(locator service.Locator, version *semver.Version, panicHandler a } go func() { - defer serv.handlePanic() + defer async.HandlePanic(serv.panicHandler) if err := serv.server.Serve(listener); err != nil { fmt.Printf("failed to serve: %v", err) @@ -88,12 +88,6 @@ func NewService(locator service.Locator, version *semver.Version, panicHandler a return serv, nil } -func (service *Service) handlePanic() { - if service.panicHandler != nil { - service.panicHandler.HandlePanic() - } -} - // Raise implements the gRPC FocusService interface; it raises the application. func (service *Service) Raise(context.Context, *emptypb.Empty) (*emptypb.Empty, error) { service.raiseCh <- struct{}{} @@ -115,7 +109,7 @@ func (service *Service) GetRaiseCh() <-chan struct{} { // Close closes the service. func (service *Service) Close() { go func() { - defer service.handlePanic() + defer async.HandlePanic(service.panicHandler) // we do this in a goroutine, as on Windows, the gRPC shutdown may take minutes if something tries to // interact with it in an invalid way (e.g. HTTP GET request from a Qt QNetworkManager instance). diff --git a/internal/frontend/cli/frontend.go b/internal/frontend/cli/frontend.go index 94b5414a..b753c337 100644 --- a/internal/frontend/cli/frontend.go +++ b/internal/frontend/cli/frontend.go @@ -21,7 +21,7 @@ package cli import ( "errors" - "github.com/ProtonMail/proton-bridge/v3/internal/async" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/events" @@ -289,7 +289,7 @@ func New(bridge *bridge.Bridge, restarter *restarter.Restarter, eventCh <-chan e } func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:gocyclo - defer f.handlePanic() + defer async.HandlePanic(f.panicHandler) // GODT-1949: Better error events. for _, err := range f.bridge.GetErrors() { @@ -451,12 +451,6 @@ func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:gocyc */ } -func (f *frontendCLI) handlePanic() { - if f.panicHandler != nil { - f.panicHandler.HandlePanic() - } -} - // Loop starts the frontend loop with an interactive shell. func (f *frontendCLI) Loop() error { f.Printf(` diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index 4f308ef3..d2747769 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -33,6 +33,7 @@ import ( "sync" "time" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/certs" @@ -192,9 +193,7 @@ func NewService( } func (s *Service) handlePanic() { - if s.panicHandler != nil { - s.panicHandler.HandlePanic() - } + async.HandlePanic(s.panicHandler) } func (s *Service) initAutostart() { diff --git a/internal/frontend/grpc/service_stream.go b/internal/frontend/grpc/service_stream.go index c7243523..4b5462da 100644 --- a/internal/frontend/grpc/service_stream.go +++ b/internal/frontend/grpc/service_stream.go @@ -49,7 +49,7 @@ func (s *Service) RunEventStream(request *EventStreamRequest, server Bridge_RunE // if events occurred before streaming started, they've been queued. Now that the stream channel is available // we can flush the queued go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() s.eventQueueMutex.Lock() defer s.eventQueueMutex.Unlock() diff --git a/internal/frontend/grpc/service_user.go b/internal/frontend/grpc/service_user.go index 7b9d3142..e3290c33 100644 --- a/internal/frontend/grpc/service_user.go +++ b/internal/frontend/grpc/service_user.go @@ -70,7 +70,7 @@ func (s *Service) SetUserSplitMode(ctx context.Context, splitMode *UserSplitMode } go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() defer func() { _ = s.SendEvent(NewUserToggleSplitModeFinishedEvent(splitMode.UserID)) }() var targetMode vault.AddressMode @@ -121,7 +121,7 @@ func (s *Service) LogoutUser(ctx context.Context, userID *wrapperspb.StringValue } go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() if err := s.bridge.LogoutUser(context.Background(), userID.Value); err != nil { s.log.WithError(err).Error("Failed to log user out") @@ -135,7 +135,7 @@ func (s *Service) RemoveUser(ctx context.Context, userID *wrapperspb.StringValue s.log.WithField("UserID", userID.Value).Debug("RemoveUser") go func() { - defer s.panicHandler.HandlePanic() + defer s.handlePanic() // remove preferences if err := s.bridge.DeleteUser(context.Background(), userID.Value); err != nil { diff --git a/internal/try/try.go b/internal/try/try.go index c134d5ab..7cdccc48 100644 --- a/internal/try/try.go +++ b/internal/try/try.go @@ -21,7 +21,7 @@ import ( "fmt" "sync" - "github.com/ProtonMail/proton-bridge/v3/internal/async" + "github.com/ProtonMail/gluon/async" "github.com/bradenaw/juniper/xerrors" "github.com/sirupsen/logrus" ) @@ -73,26 +73,20 @@ type Group struct { panicHandler async.PanicHandler } -func (wg *Group) SetPanicHandler(panicHandler async.PanicHandler) { - wg.panicHandler = panicHandler -} - -func (wg *Group) handlePanic() { - if wg.panicHandler != nil { - wg.panicHandler.HandlePanic() - } +func MakeGroup(panicHandler async.PanicHandler) Group { + return Group{panicHandler: panicHandler} } func (wg *Group) GoTry(fn func(bool)) { if wg.mu.TryLock() { go func() { - defer wg.handlePanic() + defer async.HandlePanic(wg.panicHandler) defer wg.mu.Unlock() fn(true) }() } else { go func() { - defer wg.handlePanic() + defer async.HandlePanic(wg.panicHandler) fn(false) }() } diff --git a/internal/user/events.go b/internal/user/events.go index 8f978ed0..c2ed3db1 100644 --- a/internal/user/events.go +++ b/internal/user/events.go @@ -25,8 +25,8 @@ import ( "net/http" "github.com/ProtonMail/gluon" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/imap" - "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/gopenpgp/v2/crypto" @@ -225,7 +225,7 @@ func (user *User) handleCreateAddressEvent(ctx context.Context, event proton.Add user.updateCh[event.Address.ID] = user.updateCh[primAddr.ID] case vault.SplitMode: - user.updateCh[event.Address.ID] = queue.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) + user.updateCh[event.Address.ID] = async.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) } user.eventCh.Enqueue(events.UserAddressCreated{ @@ -284,7 +284,7 @@ func (user *User) handleUpdateAddressEvent(_ context.Context, event proton.Addre user.updateCh[event.Address.ID] = user.updateCh[primAddr.ID] case vault.SplitMode: - user.updateCh[event.Address.ID] = queue.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) + user.updateCh[event.Address.ID] = async.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) } user.eventCh.Enqueue(events.UserAddressEnabled{ diff --git a/internal/user/smtp.go b/internal/user/smtp.go index bcc093f1..9e237474 100644 --- a/internal/user/smtp.go +++ b/internal/user/smtp.go @@ -29,6 +29,7 @@ import ( "strings" "time" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/gluon/rfc5322" "github.com/ProtonMail/gluon/rfc822" @@ -48,7 +49,7 @@ import ( // sendMail sends an email from the given address to the given recipients. func (user *User) sendMail(authID string, from string, to []string, r io.Reader) error { - defer user.handlePanic() + defer async.HandlePanic(user.panicHandler) return safe.RLockRet(func() error { ctx, cancel := context.WithCancel(context.Background()) @@ -392,7 +393,7 @@ func (user *User) createAttachments( } keys, err := parallel.MapContext(ctx, runtime.NumCPU(), attachments, func(ctx context.Context, att message.Attachment) (attKey, error) { - defer user.handlePanic() + defer async.HandlePanic(user.panicHandler) logrus.WithFields(logrus.Fields{ "name": logging.Sensitive(att.Name), @@ -471,7 +472,7 @@ func (user *User) getRecipients( }) prefs, err := parallel.MapContext(ctx, runtime.NumCPU(), addresses, func(ctx context.Context, recipient string) (proton.SendPreferences, error) { - defer user.handlePanic() + defer async.HandlePanic(user.panicHandler) pubKeys, recType, err := client.GetPublicKeys(ctx, recipient) if err != nil { diff --git a/internal/user/sync.go b/internal/user/sync.go index 6b281386..6c40cd46 100644 --- a/internal/user/sync.go +++ b/internal/user/sync.go @@ -25,9 +25,9 @@ import ( "strings" "time" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/imap" "github.com/ProtonMail/gluon/logging" - "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/gopenpgp/v2/crypto" @@ -184,7 +184,7 @@ func (user *User) sync(ctx context.Context) error { } // nolint:exhaustive -func syncLabels(ctx context.Context, apiLabels map[string]proton.Label, updateCh ...*queue.QueuedChannel[imap.Update]) error { +func syncLabels(ctx context.Context, apiLabels map[string]proton.Label, updateCh ...*async.QueuedChannel[imap.Update]) error { var updates []imap.Update // Create placeholder Folders/Labels mailboxes with the \Noselect attribute. @@ -251,8 +251,8 @@ func (user *User) syncMessages( vault *vault.User, apiLabels map[string]proton.Label, addrKRs map[string]*crypto.KeyRing, - updateCh map[string]*queue.QueuedChannel[imap.Update], - eventCh *queue.QueuedChannel[events.Event], + updateCh map[string]*async.QueuedChannel[imap.Update], + eventCh *async.QueuedChannel[events.Event], maxSyncMemory uint64, ) error { ctx, cancel := context.WithCancel(ctx) @@ -456,7 +456,7 @@ func (user *User) syncMessages( } result, err := parallel.MapContext(ctx, maxParallelDownloads, request.ids, func(ctx context.Context, id string) (proton.FullMessage, error) { - defer user.handlePanic() + defer async.HandlePanic(user.panicHandler) var result proton.FullMessage @@ -511,7 +511,7 @@ func (user *User) syncMessages( logrus.Debugf("Build request: %v of %v count=%v", index, len(chunks), len(chunk)) result, err := parallel.MapContext(ctx, maxMessagesInParallel, chunk, func(ctx context.Context, msg proton.FullMessage) (*buildRes, error) { - defer user.handlePanic() + defer async.HandlePanic(user.panicHandler) return buildRFC822(apiLabels, msg, addrKRs[msg.AddressID], new(bytes.Buffer)), nil }) @@ -538,7 +538,7 @@ func (user *User) syncMessages( type updateTargetInfo struct { queueIndex int - ch *queue.QueuedChannel[imap.Update] + ch *async.QueuedChannel[imap.Update] } pendingUpdates := make([][]*imap.MessageCreated, len(updateCh)) diff --git a/internal/user/sync_reporter.go b/internal/user/sync_reporter.go index 51a73663..91d296f7 100644 --- a/internal/user/sync_reporter.go +++ b/internal/user/sync_reporter.go @@ -20,13 +20,13 @@ package user import ( "time" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/proton-bridge/v3/internal/events" ) type syncReporter struct { userID string - eventCh *queue.QueuedChannel[events.Event] + eventCh *async.QueuedChannel[events.Event] start time.Time total int @@ -36,7 +36,7 @@ type syncReporter struct { freq time.Duration } -func newSyncReporter(userID string, eventCh *queue.QueuedChannel[events.Event], total int, freq time.Duration) *syncReporter { +func newSyncReporter(userID string, eventCh *async.QueuedChannel[events.Event], total int, freq time.Duration) *syncReporter { return &syncReporter{ userID: userID, eventCh: eventCh, diff --git a/internal/user/types.go b/internal/user/types.go index 3da287fb..fc6a2286 100644 --- a/internal/user/types.go +++ b/internal/user/types.go @@ -23,8 +23,8 @@ import ( "runtime" "strings" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/go-proton-api" - "github.com/ProtonMail/proton-bridge/v3/internal/async" "golang.org/x/exp/maps" "golang.org/x/exp/slices" ) diff --git a/internal/user/user.go b/internal/user/user.go index cd4b14c7..71a46236 100644 --- a/internal/user/user.go +++ b/internal/user/user.go @@ -29,13 +29,12 @@ import ( "sync/atomic" "time" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/connector" "github.com/ProtonMail/gluon/imap" - "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/gluon/reporter" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/proton-bridge/v3/internal" - "github.com/ProtonMail/proton-bridge/v3/internal/async" "github.com/ProtonMail/proton-bridge/v3/internal/events" "github.com/ProtonMail/proton-bridge/v3/internal/logging" "github.com/ProtonMail/proton-bridge/v3/internal/safe" @@ -65,7 +64,7 @@ type User struct { reporter reporter.Reporter sendHash *sendRecorder - eventCh *queue.QueuedChannel[events.Event] + eventCh *async.QueuedChannel[events.Event] eventLock safe.RWMutex apiUser proton.User @@ -77,7 +76,7 @@ type User struct { apiLabels map[string]proton.Label apiLabelsLock safe.RWMutex - updateCh map[string]*queue.QueuedChannel[imap.Update] + updateCh map[string]*async.QueuedChannel[imap.Update] updateChLock safe.RWMutex tasks *async.Group @@ -129,7 +128,7 @@ func New( reporter: reporter, sendHash: newSendRecorder(sendEntryExpiry), - eventCh: queue.NewQueuedChannel[events.Event](0, 0, crashHandler), + eventCh: async.NewQueuedChannel[events.Event](0, 0, crashHandler), eventLock: safe.NewRWMutex(), apiUser: apiUser, @@ -141,7 +140,7 @@ func New( apiLabels: groupBy(apiLabels, func(label proton.Label) string { return label.ID }), apiLabelsLock: safe.NewRWMutex(), - updateCh: make(map[string]*queue.QueuedChannel[imap.Update]), + updateCh: make(map[string]*async.QueuedChannel[imap.Update]), updateChLock: safe.NewRWMutex(), tasks: async.NewGroup(context.Background(), crashHandler), @@ -184,7 +183,7 @@ func New( doneCh := make(chan struct{}) go func() { - defer user.handlePanic() + defer async.HandlePanic(user.panicHandler) user.pollAPIEventsCh <- doneCh }() @@ -237,12 +236,6 @@ func New( return user, nil } -func (user *User) handlePanic() { - if user.panicHandler != nil { - user.panicHandler.HandlePanic() - } -} - func (user *User) TriggerSync() { user.goSync() } @@ -605,11 +598,11 @@ func (user *User) initUpdateCh(mode vault.AddressMode) { updateCh.CloseAndDiscardQueued() } - user.updateCh = make(map[string]*queue.QueuedChannel[imap.Update]) + user.updateCh = make(map[string]*async.QueuedChannel[imap.Update]) switch mode { case vault.CombinedMode: - primaryUpdateCh := queue.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) + primaryUpdateCh := async.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) for addrID := range user.apiAddrs { user.updateCh[addrID] = primaryUpdateCh @@ -617,7 +610,7 @@ func (user *User) initUpdateCh(mode vault.AddressMode) { case vault.SplitMode: for addrID := range user.apiAddrs { - user.updateCh[addrID] = queue.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) + user.updateCh[addrID] = async.NewQueuedChannel[imap.Update](0, 0, user.panicHandler) } } } diff --git a/internal/vault/migrate_test.go b/internal/vault/migrate_test.go index 2d3662e1..c69fe000 100644 --- a/internal/vault/migrate_test.go +++ b/internal/vault/migrate_test.go @@ -25,7 +25,7 @@ import ( "path/filepath" "testing" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/stretchr/testify/require" "github.com/vmihailenco/msgpack/v5" @@ -53,7 +53,7 @@ func TestMigrate(t *testing.T) { require.NoError(t, os.WriteFile(filepath.Join(dir, "vault.enc"), b, 0o600)) // Migrate the vault. - s, corrupt, err := New(dir, "default-gluon-dir", []byte("my secret key"), queue.NoopPanicHandler{}) + s, corrupt, err := New(dir, "default-gluon-dir", []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) diff --git a/internal/vault/settings_test.go b/internal/vault/settings_test.go index e0265798..cc4e1b77 100644 --- a/internal/vault/settings_test.go +++ b/internal/vault/settings_test.go @@ -22,7 +22,7 @@ import ( "testing" "github.com/Masterminds/semver/v3" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/proton-bridge/v3/internal/updater" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/stretchr/testify/require" @@ -64,7 +64,7 @@ func TestVault_Settings_SMTP(t *testing.T) { func TestVault_Settings_GluonDir(t *testing.T) { // create a new test vault. - s, corrupt, err := vault.New(t.TempDir(), "/path/to/gluon", []byte("my secret key"), queue.NoopPanicHandler{}) + s, corrupt, err := vault.New(t.TempDir(), "/path/to/gluon", []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) diff --git a/internal/vault/vault.go b/internal/vault/vault.go index 757f5707..0b1c7002 100644 --- a/internal/vault/vault.go +++ b/internal/vault/vault.go @@ -29,7 +29,7 @@ import ( "path/filepath" "sync" - "github.com/ProtonMail/proton-bridge/v3/internal/async" + "github.com/ProtonMail/gluon/async" "github.com/bradenaw/juniper/parallel" "github.com/bradenaw/juniper/xslices" "github.com/sirupsen/logrus" @@ -77,12 +77,6 @@ func New(vaultDir, gluonCacheDir string, key []byte, panicHandler async.PanicHan return vault, corrupt, nil } -func (vault *Vault) handlePanic() { - if vault.panicHandler != nil { - vault.panicHandler.HandlePanic() - } -} - // GetUserIDs returns the user IDs and usernames of all users in the vault. func (vault *Vault) GetUserIDs() []string { return xslices.Map(vault.get().Users, func(user UserData) string { @@ -126,7 +120,7 @@ func (vault *Vault) ForUser(parallelism int, fn func(*User) error) error { userIDs := vault.GetUserIDs() return parallel.DoContext(context.Background(), parallelism, len(userIDs), func(_ context.Context, idx int) error { - defer vault.handlePanic() + defer async.HandlePanic(vault.panicHandler) user, err := vault.NewUser(userIDs[idx]) if err != nil { diff --git a/internal/vault/vault_bench_test.go b/internal/vault/vault_bench_test.go index c5903ceb..d6e96f2c 100644 --- a/internal/vault/vault_bench_test.go +++ b/internal/vault/vault_bench_test.go @@ -22,7 +22,7 @@ import ( "runtime" "testing" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/google/uuid" "github.com/stretchr/testify/require" @@ -32,7 +32,7 @@ func BenchmarkVault(b *testing.B) { vaultDir, gluonDir := b.TempDir(), b.TempDir() // Create a new vault. - s, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) + s, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(b, err) require.False(b, corrupt) diff --git a/internal/vault/vault_test.go b/internal/vault/vault_test.go index 12fea53d..25772074 100644 --- a/internal/vault/vault_test.go +++ b/internal/vault/vault_test.go @@ -22,7 +22,7 @@ import ( "path/filepath" "testing" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/proton-bridge/v3/internal/vault" "github.com/stretchr/testify/require" ) @@ -31,19 +31,19 @@ func TestVault_Corrupt(t *testing.T) { vaultDir, gluonDir := t.TempDir(), t.TempDir() { - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) } { - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) } { - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("bad key"), queue.NoopPanicHandler{}) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("bad key"), async.NoopPanicHandler{}) require.NoError(t, err) require.True(t, corrupt) } @@ -53,13 +53,13 @@ func TestVault_Corrupt_JunkData(t *testing.T) { vaultDir, gluonDir := t.TempDir(), t.TempDir() { - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) } { - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) } @@ -72,7 +72,7 @@ func TestVault_Corrupt_JunkData(t *testing.T) { _, err = f.Write([]byte("junk data")) require.NoError(t, err) - _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), queue.NoopPanicHandler{}) + _, corrupt, err := vault.New(vaultDir, gluonDir, []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(t, err) require.True(t, corrupt) } @@ -100,7 +100,7 @@ func TestVault_Reset(t *testing.T) { func newVault(t *testing.T) *vault.Vault { t.Helper() - s, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"), queue.NoopPanicHandler{}) + s, corrupt, err := vault.New(t.TempDir(), t.TempDir(), []byte("my secret key"), async.NoopPanicHandler{}) require.NoError(t, err) require.False(t, corrupt) diff --git a/tests/collector_test.go b/tests/collector_test.go index cfcd62f6..f11e149a 100644 --- a/tests/collector_test.go +++ b/tests/collector_test.go @@ -23,20 +23,20 @@ import ( "sync" "time" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/proton-bridge/v3/internal/events" ) type eventCollector struct { - events map[reflect.Type]*queue.QueuedChannel[events.Event] - fwdCh []*queue.QueuedChannel[events.Event] + events map[reflect.Type]*async.QueuedChannel[events.Event] + fwdCh []*async.QueuedChannel[events.Event] lock sync.Mutex wg sync.WaitGroup } func newEventCollector() *eventCollector { return &eventCollector{ - events: make(map[reflect.Type]*queue.QueuedChannel[events.Event]), + events: make(map[reflect.Type]*async.QueuedChannel[events.Event]), } } @@ -44,7 +44,7 @@ func (c *eventCollector) collectFrom(eventCh <-chan events.Event) <-chan events. c.lock.Lock() defer c.lock.Unlock() - fwdCh := queue.NewQueuedChannel[events.Event](0, 0, queue.NoopPanicHandler{}) + fwdCh := async.NewQueuedChannel[events.Event](0, 0, async.NoopPanicHandler{}) c.fwdCh = append(c.fwdCh, fwdCh) @@ -87,7 +87,7 @@ func (c *eventCollector) push(event events.Event) { defer c.lock.Unlock() if _, ok := c.events[reflect.TypeOf(event)]; !ok { - c.events[reflect.TypeOf(event)] = queue.NewQueuedChannel[events.Event](0, 0, queue.NoopPanicHandler{}) + c.events[reflect.TypeOf(event)] = async.NewQueuedChannel[events.Event](0, 0, async.NoopPanicHandler{}) } c.events[reflect.TypeOf(event)].Enqueue(event) @@ -102,7 +102,7 @@ func (c *eventCollector) getEventCh(ofType events.Event) <-chan events.Event { defer c.lock.Unlock() if _, ok := c.events[reflect.TypeOf(ofType)]; !ok { - c.events[reflect.TypeOf(ofType)] = queue.NewQueuedChannel[events.Event](0, 0, queue.NoopPanicHandler{}) + c.events[reflect.TypeOf(ofType)] = async.NewQueuedChannel[events.Event](0, 0, async.NoopPanicHandler{}) } return c.events[reflect.TypeOf(ofType)].GetChannel() diff --git a/tests/ctx_bridge_test.go b/tests/ctx_bridge_test.go index 7a6edf66..92cdf0e1 100644 --- a/tests/ctx_bridge_test.go +++ b/tests/ctx_bridge_test.go @@ -29,8 +29,8 @@ import ( "runtime" "time" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/gluon/imap" - "github.com/ProtonMail/gluon/queue" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" "github.com/ProtonMail/proton-bridge/v3/internal/constants" "github.com/ProtonMail/proton-bridge/v3/internal/cookies" @@ -108,7 +108,7 @@ func (t *testCtx) initBridge() (<-chan events.Event, error) { } // Create the vault. - vault, corrupt, err := vault.New(vaultDir, gluonCacheDir, t.storeKey, queue.NoopPanicHandler{}) + vault, corrupt, err := vault.New(vaultDir, gluonCacheDir, t.storeKey, async.NoopPanicHandler{}) if err != nil { return nil, fmt.Errorf("could not create vault: %w", err) } else if corrupt { @@ -200,7 +200,7 @@ func (t *testCtx) initFrontendService(eventCh <-chan events.Event) error { t.mocks.Autostarter.EXPECT().IsEnabled().AnyTimes() service, err := frontend.NewService( - new(mockCrashHandler), + &async.NoopPanicHandler{}, new(mockRestarter), t.locator, t.bridge, @@ -301,7 +301,7 @@ func (t *testCtx) initFrontendClient() error { return fmt.Errorf("could not start event stream: %w", err) } - eventCh := queue.NewQueuedChannel[*frontend.StreamEvent](0, 0, queue.NoopPanicHandler{}) + eventCh := async.NewQueuedChannel[*frontend.StreamEvent](0, 0, async.NoopPanicHandler{}) go func() { defer eventCh.CloseAndDiscardQueued() @@ -343,10 +343,6 @@ func (t *testCtx) closeFrontendClient() error { return nil } -type mockCrashHandler struct{} - -func (m *mockCrashHandler) HandlePanic() {} - type mockRestarter struct{} func (m *mockRestarter) Set(restart, crash bool) {} diff --git a/tests/ctx_helper_test.go b/tests/ctx_helper_test.go index 05c5b0a4..38641c39 100644 --- a/tests/ctx_helper_test.go +++ b/tests/ctx_helper_test.go @@ -23,7 +23,7 @@ import ( "os" "runtime" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/gopenpgp/v2/crypto" "github.com/bradenaw/juniper/stream" @@ -114,7 +114,7 @@ func (t *testCtx) withAddrKR( return err } - _, addrKRs, err := proton.Unlock(user, addr, keyPass, queue.NoopPanicHandler{}) + _, addrKRs, err := proton.Unlock(user, addr, keyPass, async.NoopPanicHandler{}) if err != nil { return err } diff --git a/tests/ctx_test.go b/tests/ctx_test.go index fd6be67c..13bff820 100644 --- a/tests/ctx_test.go +++ b/tests/ctx_test.go @@ -29,7 +29,7 @@ import ( "testing" "github.com/Masterminds/semver/v3" - "github.com/ProtonMail/gluon/queue" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/go-proton-api" "github.com/ProtonMail/go-proton-api/server" "github.com/ProtonMail/proton-bridge/v3/internal/bridge" @@ -141,7 +141,7 @@ type testCtx struct { // client holds the gRPC frontend client under test. client frontend.BridgeClient clientConn *grpc.ClientConn - clientEventCh *queue.QueuedChannel[*frontend.StreamEvent] + clientEventCh *async.QueuedChannel[*frontend.StreamEvent] // These maps hold test objects created during the test. userByID map[string]*testUser diff --git a/utils/vault-editor/main.go b/utils/vault-editor/main.go index a396a05f..20a535d9 100644 --- a/utils/vault-editor/main.go +++ b/utils/vault-editor/main.go @@ -24,6 +24,7 @@ import ( "io" "os" + "github.com/ProtonMail/gluon/async" "github.com/ProtonMail/proton-bridge/v3/internal/app" "github.com/ProtonMail/proton-bridge/v3/internal/locations" "github.com/ProtonMail/proton-bridge/v3/internal/vault" @@ -49,7 +50,7 @@ func main() { func readAction(c *cli.Context) error { return app.WithLocations(func(locations *locations.Locations) error { - return app.WithVault(locations, func(vault *vault.Vault, insecure, corrupt bool) error { + return app.WithVault(locations, async.NoopPanicHandler{}, func(vault *vault.Vault, insecure, corrupt bool) error { if _, err := os.Stdout.Write(vault.ExportJSON()); err != nil { return fmt.Errorf("failed to write vault: %w", err) } @@ -61,7 +62,7 @@ func readAction(c *cli.Context) error { func writeAction(c *cli.Context) error { return app.WithLocations(func(locations *locations.Locations) error { - return app.WithVault(locations, func(vault *vault.Vault, insecure, corrupt bool) error { + return app.WithVault(locations, async.NoopPanicHandler{}, func(vault *vault.Vault, insecure, corrupt bool) error { b, err := io.ReadAll(os.Stdin) if err != nil { return fmt.Errorf("failed to read vault: %w", err) From 9bbeabcf50d231cb833642088d2baee729f71e6b Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Thu, 23 Mar 2023 16:55:35 +0100 Subject: [PATCH 128/130] feat(GODT-2523): use software QML rendering backend by default on Windows. (cherry picked from commit 934749b278e95a9d69818ddf6b45ee7bb896af03) --- internal/frontend/bridge-gui/bridge-gui/Settings.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/internal/frontend/bridge-gui/bridge-gui/Settings.cpp b/internal/frontend/bridge-gui/bridge-gui/Settings.cpp index e7acb259..270ac1dd 100644 --- a/internal/frontend/bridge-gui/bridge-gui/Settings.cpp +++ b/internal/frontend/bridge-gui/bridge-gui/Settings.cpp @@ -44,7 +44,7 @@ Settings::Settings() /// \return The value for the 'Use software renderer' setting. //**************************************************************************************************************************************************** bool Settings::useSoftwareRenderer() const { - return settings_.value(keyUseSoftwareRenderer, false).toBool(); + return settings_.value(keyUseSoftwareRenderer, onWindows()).toBool(); } From 8b80938e4960a30989039021f80a0668080f8787 Mon Sep 17 00:00:00 2001 From: Xavier Michelon Date: Wed, 22 Mar 2023 13:33:32 +0100 Subject: [PATCH 129/130] fix(GODT-2516): log error when the vault key cannot be created/loaded from the keychain. Backported from release/perth-narrows. --- internal/app/vault.go | 1 + 1 file changed, 1 insertion(+) diff --git a/internal/app/vault.go b/internal/app/vault.go index b194fcae..042e89f2 100644 --- a/internal/app/vault.go +++ b/internal/app/vault.go @@ -81,6 +81,7 @@ func newVault(locations *locations.Locations, panicHandler async.PanicHandler) ( ) if key, err := loadVaultKey(vaultDir); err != nil { + logrus.WithError(err).Error("Could not load/create vault key") insecure = true // We store the insecure vault in a separate directory From 7d8e71c9ea680067d1295a0ad39f708c6485eef0 Mon Sep 17 00:00:00 2001 From: Jakub Date: Mon, 20 Mar 2023 17:02:37 +0100 Subject: [PATCH 130/130] fix(GODT-2505): show notification only for cases when user needs to do actions. --- internal/bridge/user_events.go | 8 ++++---- internal/frontend/cli/frontend.go | 8 -------- internal/frontend/grpc/service.go | 5 ++++- 3 files changed, 8 insertions(+), 13 deletions(-) diff --git a/internal/bridge/user_events.go b/internal/bridge/user_events.go index 5873de8c..d5a310df 100644 --- a/internal/bridge/user_events.go +++ b/internal/bridge/user_events.go @@ -71,7 +71,7 @@ func (bridge *Bridge) handleUserEvent(ctx context.Context, user *user.User, even } func (bridge *Bridge) handleUserAddressCreated(ctx context.Context, user *user.User, event events.UserAddressCreated) error { - if user.GetAddressMode() != vault.SplitMode { + if user.GetAddressMode() == vault.CombinedMode { return nil } @@ -92,7 +92,7 @@ func (bridge *Bridge) handleUserAddressCreated(ctx context.Context, user *user.U } func (bridge *Bridge) handleUserAddressEnabled(ctx context.Context, user *user.User, event events.UserAddressEnabled) error { - if user.GetAddressMode() != vault.SplitMode { + if user.GetAddressMode() == vault.CombinedMode { return nil } @@ -109,7 +109,7 @@ func (bridge *Bridge) handleUserAddressEnabled(ctx context.Context, user *user.U } func (bridge *Bridge) handleUserAddressDisabled(ctx context.Context, user *user.User, event events.UserAddressDisabled) error { - if user.GetAddressMode() != vault.SplitMode { + if user.GetAddressMode() == vault.CombinedMode { return nil } @@ -130,7 +130,7 @@ func (bridge *Bridge) handleUserAddressDisabled(ctx context.Context, user *user. } func (bridge *Bridge) handleUserAddressDeleted(ctx context.Context, user *user.User, event events.UserAddressDeleted) error { - if user.GetAddressMode() != vault.SplitMode { + if user.GetAddressMode() == vault.CombinedMode { return nil } diff --git a/internal/frontend/cli/frontend.go b/internal/frontend/cli/frontend.go index b753c337..d71f053a 100644 --- a/internal/frontend/cli/frontend.go +++ b/internal/frontend/cli/frontend.go @@ -352,14 +352,6 @@ func (f *frontendCLI) watchEvents(eventCh <-chan events.Event) { // nolint:gocyc f.Printf("An address for %s was enabled. You may need to reconfigure your email client.\n", user.Username) - case events.UserAddressUpdated: - user, err := f.bridge.GetUserInfo(event.UserID) - if err != nil { - return - } - - f.Printf("Address changed for %s. You may need to reconfigure your email client.\n", user.Username) - case events.UserAddressDisabled: user, err := f.bridge.GetUserInfo(event.UserID) if err != nil { diff --git a/internal/frontend/grpc/service.go b/internal/frontend/grpc/service.go index d2747769..e22d66ad 100644 --- a/internal/frontend/grpc/service.go +++ b/internal/frontend/grpc/service.go @@ -288,9 +288,12 @@ func (s *Service) watchEvents() { case events.UserAddressCreated: _ = s.SendEvent(NewMailAddressChangeEvent(event.Email)) - case events.UserAddressUpdated: + case events.UserAddressEnabled: _ = s.SendEvent(NewMailAddressChangeEvent(event.Email)) + case events.UserAddressDisabled: + _ = s.SendEvent(NewMailAddressChangeLogoutEvent(event.Email)) + case events.UserAddressDeleted: _ = s.SendEvent(NewMailAddressChangeLogoutEvent(event.Email))