From bc01e93330fe873642d1a4128432e9c0b7d8cb3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=BA=90=E6=96=87=E9=9B=A8?= <41315874+fumiama@users.noreply.github.com> Date: Thu, 27 Oct 2022 16:33:55 +0800 Subject: [PATCH] add method cat & md5 --- cmd_test.go | 2 +- go.mod | 2 + go.sum | 2 + reg.go | 108 +++++++++++++++++++++++++++++++++++++++++++++++----- reg_test.go | 31 ++++++++++++++- storage.go | 16 ++++++++ 6 files changed, 149 insertions(+), 12 deletions(-) create mode 100644 storage.go diff --git a/cmd_test.go b/cmd_test.go index 187b5d1..3a5a2a2 100644 --- a/cmd_test.go +++ b/cmd_test.go @@ -6,7 +6,7 @@ import ( ) func TestRegedit(t *testing.T) { - reg := NewRegedit("127.0.0.1:8888", "testpwd", "testsps") + reg := NewRegedit("127.0.0.1:8888", "testpwd", "testsps", 127, 127) err := reg.Connect() if err != nil { t.Fatal(err) diff --git a/go.mod b/go.mod index 2fe1502..968e950 100644 --- a/go.mod +++ b/go.mod @@ -3,3 +3,5 @@ module github.com/fumiama/go-registry go 1.17 require github.com/fumiama/gofastTEA v0.0.10 + +require github.com/fumiama/go-simple-protobuf v0.1.0 diff --git a/go.sum b/go.sum index 9882633..222163b 100644 --- a/go.sum +++ b/go.sum @@ -1,2 +1,4 @@ +github.com/fumiama/go-simple-protobuf v0.1.0 h1:rLzJgNqB6LHNDVMl81yyNt6ZKziWtVfu+ioF0edlEVw= +github.com/fumiama/go-simple-protobuf v0.1.0/go.mod h1:5yYNapXq1tQMOZg9bOIVhQlZk9pQqpuFIO4DZLbsdy4= github.com/fumiama/gofastTEA v0.0.10 h1:JJJ+brWD4kie+mmK2TkspDXKzqq0IjXm89aGYfoGhhQ= github.com/fumiama/gofastTEA v0.0.10/go.mod h1:RIdbYZyB4MbH6ZBlPymRaXn3cD6SedlCu5W/HHfMPBk= diff --git a/reg.go b/reg.go index 7a0ba08..5ac24d6 100644 --- a/reg.go +++ b/reg.go @@ -1,12 +1,16 @@ package registry import ( + "bytes" + "crypto/md5" "errors" "io" "net" + "strconv" "sync" "time" + spb "github.com/fumiama/go-simple-protobuf" tea "github.com/fumiama/gofastTEA" ) @@ -19,18 +23,21 @@ var ( ErrSetValTooLong = errors.New("set val too long") ErrUnknownAck = errors.New("unknown ack error") ErrNoSuchKey = errors.New("no such key") + ErrRawDataTooLong = errors.New("raw data too long") + ErrMd5NotEqual = errors.New("md5 not equal") ) type Regedit struct { sync.Mutex - conn net.Conn - addr string - tp tea.TEA - ts *tea.TEA - seq byte + conn net.Conn + addr string + tp tea.TEA + ts *tea.TEA + dksz, ddsz int + seq byte } -func NewRegedit(addr, pwd, sps string) *Regedit { +func NewRegedit(addr, pwd, sps string, dksz, ddsz int) *Regedit { var tp, ts [16]byte if len(pwd) > 15 { pwd = pwd[:15] @@ -41,16 +48,16 @@ func NewRegedit(addr, pwd, sps string) *Regedit { copy(tp[:], StringToBytes(pwd)) copy(ts[:], StringToBytes(sps)) s := tea.NewTeaCipherLittleEndian(ts[:]) - return &Regedit{addr: addr, tp: tea.NewTeaCipherLittleEndian(tp[:]), ts: &s} + return &Regedit{addr: addr, tp: tea.NewTeaCipherLittleEndian(tp[:]), ts: &s, dksz: dksz, ddsz: ddsz} } -func NewRegReader(addr, pwd string) *Regedit { +func NewRegReader(addr, pwd string, dksz, ddsz int) *Regedit { var tp [16]byte if len(pwd) > 15 { pwd = pwd[:15] } copy(tp[:], StringToBytes(pwd)) - return &Regedit{addr: addr, tp: tea.NewTeaCipherLittleEndian(tp[:])} + return &Regedit{addr: addr, tp: tea.NewTeaCipherLittleEndian(tp[:]), dksz: dksz, ddsz: ddsz} } func (r *Regedit) Connect() (err error) { @@ -116,6 +123,89 @@ func (r *Regedit) Get(key string) (string, error) { return a, nil } +func (r *Regedit) Cat() (*Storage, error) { + p := NewCmdPacket(CMDCAT, []byte("fill"), &r.tp) + defer p.Put() + r.Lock() + r.conn.Write(p.Encrypt(r.seq)) + r.seq++ + seq := r.seq + r.seq++ + r.Unlock() + var buf [64]byte + i := 0 + for { + _, err := r.conn.Read(buf[i : i+1]) + if err != nil { + return nil, err + } + if buf[i] == '$' { + break + } + i++ + if i >= 64 { + return nil, ErrRawDataTooLong + } + } + n, err := strconv.ParseUint(BytesToString(buf[:i]), 10, 64) + if err != nil { + return nil, err + } + data := make([]byte, n) + _, err = r.conn.Read(data) + if err != nil { + return nil, err + } + setseq(&r.tp, seq) + data = r.tp.DecryptLittleEndian(data, sumtable) + s := new(Storage) + s.m = make(map[string]string, 256) + s.Md5 = md5.Sum(data) + rd := bytes.NewReader(data) + for i = 0; i < len(data); { + sp, err := spb.NewSimplePB(rd) + if err == io.EOF { + break + } + if err != nil { + return nil, err + } + s.m[BytesToString(sp.Target[0])] = BytesToString(sp.Target[1]) + i += int(sp.RealLen) + } + return s, nil +} + +func (r *Regedit) IsMd5Equal(m [md5.Size]byte) (bool, error) { + p := NewCmdPacket(CMDMD5, m[:], &r.tp) + defer p.Put() + r.Lock() + r.conn.Write(p.Encrypt(r.seq)) + r.seq++ + err := r.ack(p) + if err != nil { + r.Unlock() + return false, err + } + err = p.Decrypt(r.seq) + r.seq++ + r.Unlock() + if err != nil { + return false, ErrDecAck + } + a := string(p.Data) + if a == "erro" && p.cmd == ACKERRO { + return false, ErrInternalServer + } + if a == "nequ" && p.cmd == ACKNEQU { + return false, ErrNoSuchKey + } + if a == "null" && p.cmd == ACKNULL { + return true, nil + } + return false, ErrUnknownAck +} + func (r *Regedit) Set(key, value string) error { if r.ts == nil { return ErrPermissionDenied diff --git a/reg_test.go b/reg_test.go index 5b8819f..6ef3069 100644 --- a/reg_test.go +++ b/reg_test.go @@ -5,7 +5,7 @@ import ( ) func TestReg(t *testing.T) { - r := NewRegedit("127.0.0.1:8888", "testpwd", "testsps") + r := NewRegedit("127.0.0.1:8888", "testpwd", "testsps", 127, 127) err := r.Connect() if err != nil { t.Fatal(err) @@ -33,6 +33,33 @@ func TestReg(t *testing.T) { if err != ErrNoSuchKey { t.Fatal(err) } + err = r.Set("test", "测试") + if err != nil { + t.Fatal(err) + } + s, err := r.Cat() + if err != nil { + t.Fatal(err) + } + v, err = s.Get("test") + if err != nil { + t.Fatal(err) + } + if v != "测试" { + t.Fatal("invalid test key value in store") + } + _, err = r.IsMd5Equal(s.Md5) + if err != nil { + t.Fatal(err) + } + err = r.Del("test") + if err != nil { + t.Fatal(err) + } + _, err = r.IsMd5Equal(s.Md5) + if err == nil { + t.Fatal("md5 has not been renewed") + } err = r.Close() if err != nil { t.Fatal(err) @@ -40,7 +67,7 @@ func TestReg(t *testing.T) { } func TestPush(t *testing.T) { - r := NewRegedit("reilia.fumiama.top:32664", "fumiama", "--") + r := NewRegedit("reilia.fumiama.top:32664", "fumiama", "--", 127, 127) err := r.Connect() if err != nil { t.Fatal(err) diff --git a/storage.go b/storage.go new file mode 100644 index 0000000..fe4ead6 --- /dev/null +++ b/storage.go @@ -0,0 +1,16 @@ +package registry + +import "crypto/md5" + +type Storage struct { + Md5 [md5.Size]byte + m map[string]string +} + +func (s *Storage) Get(key string) (string, error) { + v, ok := s.m[key] + if ok { + return v, nil + } + return "", ErrNoSuchKey +}