Add timeout for starting google account pairing
This commit is contained in:
parent
847b9a3a90
commit
cf698ed7d6
3 changed files with 45 additions and 10 deletions
|
@ -160,6 +160,7 @@ func fnLoginGoogle(ce *WrappedCommandEvent) {
|
||||||
|
|
||||||
const (
|
const (
|
||||||
pairingErrMsgNoDevices = "No devices found. Make sure you've enabled account pairing in the Google Messages app on your phone."
|
pairingErrMsgNoDevices = "No devices found. Make sure you've enabled account pairing in the Google Messages app on your phone."
|
||||||
|
pairingErrPhoneNotResponding = "Phone not responding. Make sure your phone is connected to the internet and that account pairing is enabled in the Google Messages app."
|
||||||
pairingErrMsgIncorrectEmoji = "Incorrect emoji chosen on phone, please try again"
|
pairingErrMsgIncorrectEmoji = "Incorrect emoji chosen on phone, please try again"
|
||||||
pairingErrMsgCancelled = "Pairing cancelled on phone"
|
pairingErrMsgCancelled = "Pairing cancelled on phone"
|
||||||
pairingErrMsgTimeout = "Pairing timed out, please try again"
|
pairingErrMsgTimeout = "Pairing timed out, please try again"
|
||||||
|
@ -194,6 +195,8 @@ func fnLoginGoogleCookies(ce *WrappedCommandEvent) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if errors.Is(err, libgm.ErrNoDevicesFound) {
|
if errors.Is(err, libgm.ErrNoDevicesFound) {
|
||||||
ce.Reply(pairingErrMsgNoDevices)
|
ce.Reply(pairingErrMsgNoDevices)
|
||||||
|
} else if errors.Is(err, libgm.ErrPairingInitTimeout) {
|
||||||
|
ce.Reply(pairingErrPhoneNotResponding)
|
||||||
} else if errors.Is(err, libgm.ErrIncorrectEmoji) {
|
} else if errors.Is(err, libgm.ErrIncorrectEmoji) {
|
||||||
ce.Reply(pairingErrMsgIncorrectEmoji)
|
ce.Reply(pairingErrMsgIncorrectEmoji)
|
||||||
} else if errors.Is(err, libgm.ErrPairingCancelled) {
|
} else if errors.Is(err, libgm.ErrPairingCancelled) {
|
||||||
|
|
|
@ -33,6 +33,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
"github.com/rs/zerolog"
|
||||||
"go.mau.fi/util/random"
|
"go.mau.fi/util/random"
|
||||||
"golang.org/x/crypto/hkdf"
|
"golang.org/x/crypto/hkdf"
|
||||||
"google.golang.org/protobuf/proto"
|
"google.golang.org/protobuf/proto"
|
||||||
|
@ -242,8 +243,11 @@ var (
|
||||||
ErrIncorrectEmoji = errors.New("user chose incorrect emoji on phone")
|
ErrIncorrectEmoji = errors.New("user chose incorrect emoji on phone")
|
||||||
ErrPairingCancelled = errors.New("user cancelled pairing on phone")
|
ErrPairingCancelled = errors.New("user cancelled pairing on phone")
|
||||||
ErrPairingTimeout = errors.New("pairing timed out")
|
ErrPairingTimeout = errors.New("pairing timed out")
|
||||||
|
ErrPairingInitTimeout = errors.New("client init timed out")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const GaiaInitTimeout = 15 * time.Second
|
||||||
|
|
||||||
func (c *Client) DoGaiaPairing(ctx context.Context, emojiCallback func(string)) error {
|
func (c *Client) DoGaiaPairing(ctx context.Context, emojiCallback func(string)) error {
|
||||||
if len(c.AuthData.Cookies) == 0 {
|
if len(c.AuthData.Cookies) == 0 {
|
||||||
return ErrNoCookies
|
return ErrNoCookies
|
||||||
|
@ -277,12 +281,25 @@ func (c *Client) DoGaiaPairing(ctx context.Context, emojiCallback func(string))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("failed to prepare pairing payloads: %w", err)
|
return fmt.Errorf("failed to prepare pairing payloads: %w", err)
|
||||||
}
|
}
|
||||||
serverInit, err := c.sendGaiaPairingMessage(ctx, ps, gmproto.ActionType_CREATE_GAIA_PAIRING_CLIENT_INIT, clientInit)
|
initCtx, cancel := context.WithTimeout(ctx, GaiaInitTimeout)
|
||||||
|
serverInit, err := c.sendGaiaPairingMessage(initCtx, ps, gmproto.ActionType_CREATE_GAIA_PAIRING_CLIENT_INIT, clientInit)
|
||||||
|
cancel()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
cancelErr := c.cancelGaiaPairing(ps)
|
||||||
|
if cancelErr != nil {
|
||||||
|
zerolog.Ctx(ctx).Warn().Err(err).Msg("Failed to send gaia pairing cancel request after init timeout")
|
||||||
|
}
|
||||||
|
if errors.Is(err, context.DeadlineExceeded) {
|
||||||
|
return ErrPairingInitTimeout
|
||||||
|
}
|
||||||
return fmt.Errorf("failed to send client init: %w", err)
|
return fmt.Errorf("failed to send client init: %w", err)
|
||||||
}
|
}
|
||||||
pairingEmoji, err := ps.ProcessServerInit(serverInit)
|
pairingEmoji, err := ps.ProcessServerInit(serverInit)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
cancelErr := c.cancelGaiaPairing(ps)
|
||||||
|
if cancelErr != nil {
|
||||||
|
zerolog.Ctx(ctx).Warn().Err(err).Msg("Failed to send gaia pairing cancel request after error processing server init")
|
||||||
|
}
|
||||||
return fmt.Errorf("error processing server init: %w", err)
|
return fmt.Errorf("error processing server init: %w", err)
|
||||||
}
|
}
|
||||||
emojiCallback(pairingEmoji)
|
emojiCallback(pairingEmoji)
|
||||||
|
@ -317,6 +334,16 @@ func (c *Client) DoGaiaPairing(ctx context.Context, emojiCallback func(string))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) cancelGaiaPairing(sess PairingSession) error {
|
||||||
|
return c.sessionHandler.sendMessageNoResponse(SendMessageParams{
|
||||||
|
Action: gmproto.ActionType_CANCEL_GAIA_PAIRING,
|
||||||
|
RequestID: sess.UUID.String(),
|
||||||
|
DontEncrypt: true,
|
||||||
|
CustomTTL: (300 * time.Second).Microseconds(),
|
||||||
|
MessageType: gmproto.MessageType_GAIA_2,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
func (c *Client) sendGaiaPairingMessage(ctx context.Context, sess PairingSession, action gmproto.ActionType, msg []byte) (*gmproto.GaiaPairingResponseContainer, error) {
|
func (c *Client) sendGaiaPairingMessage(ctx context.Context, sess PairingSession, action gmproto.ActionType, msg []byte) (*gmproto.GaiaPairingResponseContainer, error) {
|
||||||
respCh, err := c.sessionHandler.sendAsyncMessage(SendMessageParams{
|
respCh, err := c.sessionHandler.sendAsyncMessage(SendMessageParams{
|
||||||
Action: action,
|
Action: action,
|
||||||
|
|
|
@ -356,6 +356,11 @@ func (prov *ProvisioningAPI) GoogleLoginStart(w http.ResponseWriter, r *http.Req
|
||||||
Error: pairingErrMsgNoDevices,
|
Error: pairingErrMsgNoDevices,
|
||||||
ErrCode: "no-devices-found",
|
ErrCode: "no-devices-found",
|
||||||
})
|
})
|
||||||
|
case errors.Is(err, libgm.ErrPairingInitTimeout):
|
||||||
|
jsonResponse(w, http.StatusBadRequest, Error{
|
||||||
|
Error: pairingErrPhoneNotResponding,
|
||||||
|
ErrCode: "timeout",
|
||||||
|
})
|
||||||
default:
|
default:
|
||||||
jsonResponse(w, http.StatusInternalServerError, Error{
|
jsonResponse(w, http.StatusInternalServerError, Error{
|
||||||
Error: "Failed to start login",
|
Error: "Failed to start login",
|
||||||
|
|
Loading…
Reference in a new issue