client: improve disconnection detection
Signed-off-by: Sumner Evans <sumner.evans@automattic.com>
This commit is contained in:
+37
-13
@@ -47,6 +47,7 @@ type TelegramClient struct {
|
|||||||
userLogin *bridgev2.UserLogin
|
userLogin *bridgev2.UserLogin
|
||||||
client *telegram.Client
|
client *telegram.Client
|
||||||
updatesManager *updates.Manager
|
updatesManager *updates.Manager
|
||||||
|
clientCtx context.Context
|
||||||
clientCancel context.CancelFunc
|
clientCancel context.CancelFunc
|
||||||
|
|
||||||
appConfigLock sync.Mutex
|
appConfigLock sync.Mutex
|
||||||
@@ -225,7 +226,7 @@ func NewTelegramClient(ctx context.Context, tc *TelegramConnector, login *bridge
|
|||||||
OnDead: client.onDead,
|
OnDead: client.onDead,
|
||||||
OnSession: client.onConnectionStateChange("session"),
|
OnSession: client.onConnectionStateChange("session"),
|
||||||
OnConnected: client.onConnectionStateChange("connected"),
|
OnConnected: client.onConnectionStateChange("connected"),
|
||||||
PingCallback: client.onConnectionStateChange("ping"),
|
PingCallback: client.onPing,
|
||||||
OnAuthError: func(err error) { client.onAuthError(context.Background(), err) },
|
OnAuthError: func(err error) { client.onAuthError(context.Background(), err) },
|
||||||
PingTimeout: time.Duration(tc.Config.Ping.TimeoutSeconds) * time.Second,
|
PingTimeout: time.Duration(tc.Config.Ping.TimeoutSeconds) * time.Second,
|
||||||
PingInterval: time.Duration(tc.Config.Ping.IntervalSeconds) * time.Second,
|
PingInterval: time.Duration(tc.Config.Ping.IntervalSeconds) * time.Second,
|
||||||
@@ -412,6 +413,14 @@ func (t *TelegramClient) sendBadCredentialsOrUnknownError(err error) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t *TelegramClient) onPing() {
|
||||||
|
if t.userLogin.BridgeState.GetPrev().StateEvent == status.StateConnected {
|
||||||
|
t.main.Bridge.Log.Info().Msg("Got ping, not checking connectivity because we are already connected")
|
||||||
|
} else {
|
||||||
|
t.onConnectionStateChange("ping while not connected")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func (t *TelegramClient) onConnectionStateChange(reason string) func() {
|
func (t *TelegramClient) onConnectionStateChange(reason string) func() {
|
||||||
return func() {
|
return func() {
|
||||||
log := t.main.Bridge.Log.With().
|
log := t.main.Bridge.Log.With().
|
||||||
@@ -423,15 +432,21 @@ func (t *TelegramClient) onConnectionStateChange(reason string) func() {
|
|||||||
ctx := log.WithContext(context.Background())
|
ctx := log.WithContext(context.Background())
|
||||||
|
|
||||||
if t.client == nil {
|
if t.client == nil {
|
||||||
|
log.Warn().Msg("client is nil")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
authStatus, err := t.client.Auth().Status(ctx)
|
authStatus, err := t.client.Auth().Status(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, syscall.EPIPE) {
|
if errors.Is(err, syscall.EPIPE) {
|
||||||
// This is a pipe error, try reconnecting
|
// This is a pipe error, try disconnecting which will force the
|
||||||
|
// updatesManager to fail and cause the client to reconnect.
|
||||||
|
t.userLogin.BridgeState.Send(status.BridgeState{
|
||||||
|
StateEvent: status.StateTransientDisconnect,
|
||||||
|
Error: "pipe-error",
|
||||||
|
Message: humanise.Error(err),
|
||||||
|
})
|
||||||
t.Disconnect()
|
t.Disconnect()
|
||||||
t.Connect(t.main.Bridge.Log.WithContext(context.Background()))
|
|
||||||
} else {
|
} else {
|
||||||
t.sendBadCredentialsOrUnknownError(err)
|
t.sendBadCredentialsOrUnknownError(err)
|
||||||
}
|
}
|
||||||
@@ -460,15 +475,15 @@ func (t *TelegramClient) Connect(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
ctx, t.clientCancel, err = connectTelegramClient(ctx, t.client)
|
t.clientCtx, t.clientCancel, err = connectTelegramClient(ctx, t.client)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.sendBadCredentialsOrUnknownError(err)
|
t.sendBadCredentialsOrUnknownError(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
err = t.updatesManager.Run(ctx, t.client.API(), t.telegramUserID, updates.AuthOptions{})
|
err = t.updatesManager.Run(t.clientCtx, t.client.API(), t.telegramUserID, updates.AuthOptions{})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
zerolog.Ctx(ctx).Err(err).Msg("failed to run updates manager")
|
zerolog.Ctx(t.clientCtx).Err(err).Msg("failed to run updates manager")
|
||||||
t.Disconnect()
|
t.Disconnect()
|
||||||
t.Connect(t.main.Bridge.Log.WithContext(context.Background()))
|
t.Connect(t.main.Bridge.Log.WithContext(context.Background()))
|
||||||
}
|
}
|
||||||
@@ -476,9 +491,9 @@ func (t *TelegramClient) Connect(ctx context.Context) {
|
|||||||
|
|
||||||
// Update the logged-in user's ghost info (this also updates the user
|
// Update the logged-in user's ghost info (this also updates the user
|
||||||
// login's remote name and profile).
|
// login's remote name and profile).
|
||||||
if me, err := t.client.Self(ctx); err != nil {
|
if me, err := t.client.Self(t.clientCtx); err != nil {
|
||||||
t.sendBadCredentialsOrUnknownError(err)
|
t.sendBadCredentialsOrUnknownError(err)
|
||||||
} else if _, err := t.updateGhost(ctx, t.telegramUserID, me); err != nil {
|
} else if _, err := t.updateGhost(t.clientCtx, t.telegramUserID, me); err != nil {
|
||||||
t.sendBadCredentialsOrUnknownError(err)
|
t.sendBadCredentialsOrUnknownError(err)
|
||||||
} else {
|
} else {
|
||||||
t.userLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected})
|
t.userLogin.BridgeState.Send(status.BridgeState{StateEvent: status.StateConnected})
|
||||||
@@ -496,6 +511,7 @@ func (t *TelegramClient) Connect(ctx context.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (t *TelegramClient) Disconnect() {
|
func (t *TelegramClient) Disconnect() {
|
||||||
|
t.userLogin.Log.Info().Msg("disconnecting client")
|
||||||
if t.clientCancel != nil {
|
if t.clientCancel != nil {
|
||||||
t.clientCancel()
|
t.clientCancel()
|
||||||
}
|
}
|
||||||
@@ -642,11 +658,19 @@ func (t *TelegramClient) IsLoggedIn() bool {
|
|||||||
if t == nil {
|
if t == nil {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
t.main.Bridge.Log.Debug().
|
select {
|
||||||
Bool("has_client", t.client != nil).
|
case <-t.clientCtx.Done():
|
||||||
Bool("has_auth_key", t.userLogin.Metadata.(*UserLoginMetadata).Session.HasAuthKey()).
|
t.main.Bridge.Log.Debug().
|
||||||
Msg("Checking if user is logged in")
|
Bool("client_context_done", true).
|
||||||
return t.client != nil && t.userLogin.Metadata.(*UserLoginMetadata).Session.HasAuthKey()
|
Msg("Checking if user is logged in")
|
||||||
|
return false
|
||||||
|
default:
|
||||||
|
t.main.Bridge.Log.Debug().
|
||||||
|
Bool("has_client", t.client != nil).
|
||||||
|
Bool("has_auth_key", t.userLogin.Metadata.(*UserLoginMetadata).Session.HasAuthKey()).
|
||||||
|
Msg("Checking if user is logged in")
|
||||||
|
return t.client != nil && t.userLogin.Metadata.(*UserLoginMetadata).Session.HasAuthKey()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TelegramClient) LogoutRemote(ctx context.Context) {
|
func (t *TelegramClient) LogoutRemote(ctx context.Context) {
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ func (p *PhoneLogin) SubmitUserInput(ctx context.Context, input map[string]strin
|
|||||||
})
|
})
|
||||||
var err error
|
var err error
|
||||||
authClientContext, _ := context.WithTimeoutCause(log.WithContext(context.Background()), time.Hour, errors.New("phone login took over one hour"))
|
authClientContext, _ := context.WithTimeoutCause(log.WithContext(context.Background()), time.Hour, errors.New("phone login took over one hour"))
|
||||||
_, p.authClientCancel, err = connectTelegramClient(authClientContext, p.authClient)
|
ctx, p.authClientCancel, err = connectTelegramClient(authClientContext, p.authClient)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user