Skip to content

Commit bc9436f

Browse files
committed
message, retry: include error code in retry receipt
1 parent 65f6143 commit bc9436f

3 files changed

Lines changed: 53 additions & 5 deletions

File tree

internals.go

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

message.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -379,16 +379,19 @@ func (cli *Client) decryptMessages(ctx context.Context, info *types.MessageInfo,
379379
return
380380
}
381381
isUnavailable := encType == "skmsg" && !containsDirectMsg && errors.Is(err, signalerror.ErrNoSenderKeyForUser)
382+
383+
retryReason := getRetryReasonFromError(err)
384+
382385
if encType == "msmsg" {
383386
cli.backgroundIfAsyncAck(func() {
384387
cli.sendAck(node, NackMissingMessageSecret)
385388
})
386389
} else if cli.SynchronousAck {
387-
cli.sendRetryReceipt(ctx, node, info, isUnavailable)
390+
cli.sendRetryReceipt(ctx, node, info, isUnavailable, retryReason)
388391
// TODO this probably isn't supposed to ack
389392
cli.sendAck(node, 0)
390393
} else {
391-
go cli.sendRetryReceipt(context.WithoutCancel(ctx), node, info, isUnavailable)
394+
go cli.sendRetryReceipt(context.WithoutCancel(ctx), node, info, isUnavailable, retryReason)
392395
go cli.sendAck(node, 0)
393396
}
394397
cli.dispatchEvent(&events.UndecryptableMessage{

retry.go

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@ import (
1111
"crypto/hmac"
1212
"crypto/sha256"
1313
"encoding/binary"
14+
"errors"
1415
"fmt"
16+
"go.mau.fi/libsignal/signalerror"
1517
"time"
1618

1719
"go.mau.fi/libsignal/ecc"
@@ -43,6 +45,48 @@ type RecentMessage struct {
4345
fb *waMsgApplication.MessageApplication
4446
}
4547

48+
var (
49+
RetryReasonUnknownError = 0
50+
RetryReasonSignalErrorNoSession = 1
51+
RetryReasonSignalErrorInvalidKey = 2
52+
RetryReasonSignalErrorInvalidKeyId = 3
53+
RetryReasonSignalErrorInvalidMessage = 4
54+
RetryReasonSignalErrorInvalidSignature = 5
55+
RetryReasonSignalErrorFutureMessage = 6
56+
RetryReasonSignalErrorBadMac = 7
57+
RetryReasonSignalErrorInvalidSession = 8
58+
RetryReasonSignalErrorInvalidMsgKey = 9
59+
RetryReasonBadBroadcastEphemeralSetting = 10
60+
RetryReasonUnknownCompanionNoPrekey = 11
61+
RetryReasonAdvFailure = 12
62+
RetryReasonStatusRevokeDelay = 13
63+
)
64+
65+
func getRetryReasonFromError(err error) int {
66+
switch {
67+
case errors.Is(err, signalerror.ErrBadMAC):
68+
return RetryReasonSignalErrorBadMac
69+
case errors.Is(err, signalerror.ErrNoSessionForUser):
70+
case errors.Is(err, signalerror.ErrNoSenderKeyForUser):
71+
return RetryReasonSignalErrorNoSession
72+
case errors.Is(err, signalerror.ErrWrongMessageVersion):
73+
case errors.Is(err, signalerror.ErrOldMessageVersion):
74+
case errors.Is(err, signalerror.ErrUnknownMessageVersion):
75+
case errors.Is(err, signalerror.ErrIncompleteMessage):
76+
return RetryReasonSignalErrorInvalidMessage
77+
case errors.Is(err, signalerror.ErrInvalidSignature):
78+
case errors.Is(err, signalerror.ErrSenderKeyStateVerificationFailed):
79+
return RetryReasonSignalErrorInvalidSignature
80+
case errors.Is(err, signalerror.ErrNoSignedPreKey):
81+
return RetryReasonSignalErrorInvalidKey
82+
case errors.Is(err, signalerror.ErrNoSenderKeyStateForID):
83+
return RetryReasonSignalErrorInvalidKeyId
84+
case errors.Is(err, signalerror.ErrTooFarIntoFuture):
85+
return RetryReasonSignalErrorFutureMessage
86+
}
87+
return RetryReasonUnknownError
88+
}
89+
4690
func (rm RecentMessage) IsEmpty() bool {
4791
return rm.wa == nil && rm.fb == nil
4892
}
@@ -376,7 +420,7 @@ func (cli *Client) clearDelayedMessageRequests() {
376420
}
377421

378422
// sendRetryReceipt sends a retry receipt for an incoming message.
379-
func (cli *Client) sendRetryReceipt(ctx context.Context, node *waBinary.Node, info *types.MessageInfo, forceIncludeIdentity bool) {
423+
func (cli *Client) sendRetryReceipt(ctx context.Context, node *waBinary.Node, info *types.MessageInfo, forceIncludeIdentity bool, errorCode int) {
380424
id, _ := node.Attrs["id"].(string)
381425
children := node.GetChildren()
382426
var retryCountInMsg int
@@ -421,6 +465,7 @@ func (cli *Client) sendRetryReceipt(ctx context.Context, node *waBinary.Node, in
421465
"id": id,
422466
"t": node.Attrs["t"],
423467
"v": 1,
468+
"error": errorCode, // this can be 0 for the case of Unknown reason
424469
}},
425470
{Tag: "registration", Content: registrationIDBytes[:]},
426471
},

0 commit comments

Comments
 (0)