diff --git a/client/status/common.go b/client/status/common.go index 9b7ff77..92025dd 100644 --- a/client/status/common.go +++ b/client/status/common.go @@ -1,6 +1,8 @@ package apistatus import ( + "encoding/binary" + "github.com/nspcc-dev/neofs-api-go/v2/status" ) @@ -53,3 +55,71 @@ func (x ServerInternal) Message() string { func WriteInternalServerErr(x *ServerInternal, err error) { x.SetMessage(err.Error()) } + +// WrongMagicNumber describes failure status related to incorrect network magic. +// Instances provide Status and StatusV2 interfaces. +type WrongMagicNumber struct { + v2 status.Status +} + +func (x WrongMagicNumber) Error() string { + return errMessageStatusV2( + globalizeCodeV2(status.WrongMagicNumber, status.GlobalizeCommonFail), + x.v2.Message(), + ) +} + +// implements method of the FromStatusV2 local interface. +func (x *WrongMagicNumber) fromStatusV2(st *status.Status) { + x.v2 = *st +} + +// ToStatusV2 implements StatusV2 interface method. +// If the value was returned by FromStatusV2, returns the source message. +// Otherwise, returns message with +// * code: WRONG_MAGIC_NUMBER; +// * string message: empty; +// * details: empty. +func (x WrongMagicNumber) ToStatusV2() *status.Status { + x.v2.SetCode(globalizeCodeV2(status.WrongMagicNumber, status.GlobalizeCommonFail)) + return &x.v2 +} + +// WriteCorrectMagic writes correct network magic. +func (x *WrongMagicNumber) WriteCorrectMagic(magic uint64) { + // serialize the number + buf := make([]byte, 8) + + binary.BigEndian.PutUint64(buf, magic) + + // create corresponding detail + var d status.Detail + + d.SetID(status.DetailIDCorrectMagic) + d.SetValue(buf) + + // attach the detail + x.v2.AppendDetails(&d) +} + +// CorrectMagic returns network magic returned by the server. +// Second value indicates presence status: +// * -1 if number is presented in incorrect format +// * 0 if number is not presented +// * +1 otherwise +func (x WrongMagicNumber) CorrectMagic() (magic uint64, ok int8) { + x.v2.IterateDetails(func(d *status.Detail) bool { + if d.ID() == status.DetailIDCorrectMagic { + if val := d.Value(); len(val) == 8 { + magic = binary.BigEndian.Uint64(val) + ok = 1 + } else { + ok = -1 + } + } + + return ok != 0 + }) + + return +} diff --git a/client/status/common_test.go b/client/status/common_test.go index f32effa..7328cdd 100644 --- a/client/status/common_test.go +++ b/client/status/common_test.go @@ -3,6 +3,7 @@ package apistatus_test import ( "testing" + "github.com/nspcc-dev/neofs-api-go/v2/status" apistatus "github.com/nspcc-dev/neofs-sdk-go/client/status" "github.com/stretchr/testify/require" ) @@ -24,3 +25,28 @@ func TestServerInternal_Message(t *testing.T) { require.Equal(t, msg, res) require.Equal(t, msg, resv2) } + +func TestWrongMagicNumber_CorrectMagic(t *testing.T) { + const magic = 1337 + + var st apistatus.WrongMagicNumber + + res, ok := st.CorrectMagic() + require.Zero(t, res) + require.Zero(t, ok) + + st.WriteCorrectMagic(magic) + + res, ok = st.CorrectMagic() + require.EqualValues(t, magic, res) + require.EqualValues(t, 1, ok) + + // corrupt the value + apistatus.ToStatusV2(st).IterateDetails(func(d *status.Detail) bool { + d.SetValue([]byte{1, 2, 3}) // any slice with len != 8 + return true + }) + + _, ok = st.CorrectMagic() + require.EqualValues(t, -1, ok) +} diff --git a/client/status/v2.go b/client/status/v2.go index c918738..7ef0c8e 100644 --- a/client/status/v2.go +++ b/client/status/v2.go @@ -44,6 +44,8 @@ func FromStatusV2(st *status.Status) Status { switch status.LocalizeCommonFail(&code); code { case status.Internal: decoder = new(ServerInternal) + case status.WrongMagicNumber: + decoder = new(WrongMagicNumber) } } diff --git a/client/status/v2_test.go b/client/status/v2_test.go index 7847112..ebcab1d 100644 --- a/client/status/v2_test.go +++ b/client/status/v2_test.go @@ -49,6 +49,16 @@ func TestToStatusV2(t *testing.T) { }), codeV2: 1024, }, + { + status: (statusConstructor)(func() apistatus.Status { + var st apistatus.WrongMagicNumber + + st.WriteCorrectMagic(322) + + return st + }), + codeV2: 1025, + }, } { var st apistatus.Status @@ -117,6 +127,16 @@ func TestFromStatusV2(t *testing.T) { }), codeV2: 1024, }, + { + status: (statusConstructor)(func() apistatus.Status { + var st apistatus.WrongMagicNumber + + st.WriteCorrectMagic(322) + + return st + }), + codeV2: 1025, + }, } { var st apistatus.Status diff --git a/go.mod b/go.mod index be65912..50dc751 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/mr-tron/base58 v1.2.0 github.com/nspcc-dev/hrw v1.0.9 github.com/nspcc-dev/neo-go v0.98.0 - github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220114101721-227a871a04ac + github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220127135316-32dd0bb3f9c5 github.com/nspcc-dev/neofs-crypto v0.3.0 github.com/stretchr/testify v1.7.0 go.uber.org/zap v1.18.1 diff --git a/go.sum b/go.sum index 166500a..45e1fa2 100644 --- a/go.sum +++ b/go.sum @@ -177,8 +177,8 @@ github.com/nspcc-dev/neo-go v0.73.1-pre.0.20200303142215-f5a1b928ce09/go.mod h1: github.com/nspcc-dev/neo-go v0.98.0 h1:yyW4sgY88/pLf0949qmgfkQXzRKC3CI/WyhqXNnwMd8= github.com/nspcc-dev/neo-go v0.98.0/go.mod h1:E3cc1x6RXSXrJb2nDWXTXjnXk3rIqVN8YdFyWv+FrqM= github.com/nspcc-dev/neofs-api-go/v2 v2.11.0-pre.0.20211201134523-3604d96f3fe1/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220114101721-227a871a04ac h1:65C4z7pybLT2HjtY96abZj6kbgVp34AbrApn5DD+ZxY= -github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220114101721-227a871a04ac/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= +github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220127135316-32dd0bb3f9c5 h1:y9tbmUYhcr052QXsa4/IfUKAi2cx3TGDsEZUAow3P/Y= +github.com/nspcc-dev/neofs-api-go/v2 v2.11.2-0.20220127135316-32dd0bb3f9c5/go.mod h1:oS8dycEh8PPf2Jjp6+8dlwWyEv2Dy77h/XhhcdxYEFs= github.com/nspcc-dev/neofs-crypto v0.2.0/go.mod h1:F/96fUzPM3wR+UGsPi3faVNmFlA9KAEAUQR7dMxZmNA= github.com/nspcc-dev/neofs-crypto v0.2.3/go.mod h1:8w16GEJbH6791ktVqHN9YRNH3s9BEEKYxGhlFnp0cDw= github.com/nspcc-dev/neofs-crypto v0.3.0 h1:zlr3pgoxuzrmGCxc5W8dGVfA9Rro8diFvVnBg0L4ifM=