rpc/server: add notification filters

And check state string correctness on unmarshaling.
This commit is contained in:
Roman Khimov 2020-05-13 17:13:33 +03:00
parent 2dc16c0694
commit 393ce1c230
5 changed files with 284 additions and 39 deletions

View file

@ -366,8 +366,8 @@ requestloop:
s.subsLock.Lock()
delete(s.subscribers, subscr)
for _, e := range subscr.feeds {
if e != response.InvalidEventID {
s.unsubscribeFromChannel(e)
if e.event != response.InvalidEventID {
s.unsubscribeFromChannel(e.event)
}
}
s.subsLock.Unlock()
@ -1145,6 +1145,31 @@ func (s *Server) subscribe(reqParams request.Params, sub *subscriber) (interface
if err != nil || event == response.MissedEventID {
return nil, response.ErrInvalidParams
}
// Optional filter.
var filter interface{}
p, ok = reqParams.Value(1)
if ok {
switch event {
case response.BlockEventID:
if p.Type != request.BlockFilterT {
return nil, response.ErrInvalidParams
}
case response.TransactionEventID:
if p.Type != request.TxFilterT {
return nil, response.ErrInvalidParams
}
case response.NotificationEventID:
if p.Type != request.NotificationFilterT {
return nil, response.ErrInvalidParams
}
case response.ExecutionEventID:
if p.Type != request.ExecutionFilterT {
return nil, response.ErrInvalidParams
}
}
filter = p.Value
}
s.subsLock.Lock()
defer s.subsLock.Unlock()
select {
@ -1154,14 +1179,15 @@ func (s *Server) subscribe(reqParams request.Params, sub *subscriber) (interface
}
var id int
for ; id < len(sub.feeds); id++ {
if sub.feeds[id] == response.InvalidEventID {
if sub.feeds[id].event == response.InvalidEventID {
break
}
}
if id == len(sub.feeds) {
return nil, response.NewInternalServerError("maximum number of subscriptions is reached", nil)
}
sub.feeds[id] = event
sub.feeds[id].event = event
sub.feeds[id].filter = filter
s.subscribeToChannel(event)
return strconv.FormatInt(int64(id), 10), nil
}
@ -1206,11 +1232,12 @@ func (s *Server) unsubscribe(reqParams request.Params, sub *subscriber) (interfa
}
s.subsLock.Lock()
defer s.subsLock.Unlock()
if len(sub.feeds) <= id || sub.feeds[id] == response.InvalidEventID {
if len(sub.feeds) <= id || sub.feeds[id].event == response.InvalidEventID {
return nil, response.ErrInvalidParams
}
event := sub.feeds[id]
sub.feeds[id] = response.InvalidEventID
event := sub.feeds[id].event
sub.feeds[id].event = response.InvalidEventID
sub.feeds[id].filter = nil
s.unsubscribeFromChannel(event)
return true, nil
}
@ -1287,8 +1314,8 @@ chloop:
if sub.overflown.Load() {
continue
}
for _, subID := range sub.feeds {
if subID == resp.Event {
for i := range sub.feeds {
if sub.feeds[i].Matches(&resp) {
if msg == nil {
b, err = json.Marshal(resp)
if err != nil {