diff options
Diffstat (limited to 'src/gnunet/service/gns/block_handler.go')
-rw-r--r-- | src/gnunet/service/gns/block_handler.go | 172 |
1 files changed, 113 insertions, 59 deletions
diff --git a/src/gnunet/service/gns/block_handler.go b/src/gnunet/service/gns/block_handler.go index 860b4a7..bf65e95 100644 --- a/src/gnunet/service/gns/block_handler.go +++ b/src/gnunet/service/gns/block_handler.go | |||
@@ -6,6 +6,7 @@ import ( | |||
6 | 6 | ||
7 | "gnunet/enums" | 7 | "gnunet/enums" |
8 | "gnunet/message" | 8 | "gnunet/message" |
9 | "gnunet/util" | ||
9 | 10 | ||
10 | "github.com/bfix/gospel/crypto/ed25519" | 11 | "github.com/bfix/gospel/crypto/ed25519" |
11 | "github.com/bfix/gospel/logger" | 12 | "github.com/bfix/gospel/logger" |
@@ -16,17 +17,22 @@ type HdlrInst func(*message.GNSResourceRecord, []string) (BlockHandler, error) | |||
16 | 17 | ||
17 | // Error codes | 18 | // Error codes |
18 | var ( | 19 | var ( |
19 | ErrInvalidRecordMix = fmt.Errorf("Invalid mix of RR types in block") | 20 | ErrInvalidRecordType = fmt.Errorf("Invalid resource record type") |
20 | ErrBlockHandler = fmt.Errorf("Internal block handler failure") | 21 | ErrInvalidRecordBody = fmt.Errorf("Invalid resource record body") |
22 | ErrInvalidPKEY = fmt.Errorf("Invalid PKEY resource record") | ||
23 | ErrInvalidCNAME = fmt.Errorf("Invalid CNAME resource record") | ||
24 | ErrInvalidRecordMix = fmt.Errorf("Invalid mix of RR types in block") | ||
25 | ErrBlockHandler = fmt.Errorf("Internal block handler failure") | ||
21 | ) | 26 | ) |
22 | 27 | ||
23 | // Mapping of RR types to BlockHandler instanciation functions | 28 | // Mapping of RR types to BlockHandler instanciation functions |
24 | var ( | 29 | var ( |
25 | customHandler = map[int]HdlrInst{ | 30 | customHandler = map[int]HdlrInst{ |
26 | enums.GNS_TYPE_PKEY: NewPkeyHandler, | 31 | enums.GNS_TYPE_PKEY: NewPkeyHandler, |
27 | enums.GNS_TYPE_GNS2DNS: NewGns2DnsHandler, | 32 | enums.GNS_TYPE_GNS2DNS: NewGns2DnsHandler, |
28 | enums.GNS_TYPE_BOX: NewBoxHandler, | 33 | enums.GNS_TYPE_BOX: NewBoxHandler, |
29 | enums.GNS_TYPE_LEHO: NewLehoHandler, | 34 | enums.GNS_TYPE_LEHO: NewLehoHandler, |
35 | enums.GNS_TYPE_DNS_CNAME: NewCnameHandler, | ||
30 | } | 36 | } |
31 | ) | 37 | ) |
32 | 38 | ||
@@ -39,17 +45,17 @@ var ( | |||
39 | 45 | ||
40 | // BlockHandler interface. | 46 | // BlockHandler interface. |
41 | type BlockHandler interface { | 47 | type BlockHandler interface { |
42 | // AddRecord inserts a RR into the BlockHandler for (later) processing. | 48 | // AddRecord inserts an associated RR into the BlockHandler for (later) |
43 | // The handler can inspect the remaining labels in a path if required. | 49 | // processing. The handler can inspect the remaining labels in a path |
44 | // It returns an error if a record is not accepted by the block handler. | 50 | // if required. The method returns an error if a record is not accepted |
51 | // by the block handler (RR not of required type). | ||
45 | AddRecord(rr *message.GNSResourceRecord, labels []string) error | 52 | AddRecord(rr *message.GNSResourceRecord, labels []string) error |
46 | 53 | ||
47 | // TypeAction returns a flag indicating how a resource record of a | 54 | // Coexist checks if a custom block handler can co-exist with other |
48 | // given type is to be treated by a custom block handler: | 55 | // resource records in the same block. 'cm' maps the resource type |
49 | // = -1: Record is not allowed | 56 | // to an integer count (how many records of a type are present in the |
50 | // = 0: Record is allowed but will be ignored | 57 | // GNS block). |
51 | // = 1: Record is allowed and will be processed | 58 | Coexist(cm util.CounterMap) bool |
52 | TypeAction(t int) int | ||
53 | 59 | ||
54 | // Records returns a list of RR of the given types associated with | 60 | // Records returns a list of RR of the given types associated with |
55 | // the custom handler | 61 | // the custom handler |
@@ -69,7 +75,8 @@ type BlockHandler interface { | |||
69 | 75 | ||
70 | // BlockHandlerList is a list of block handlers instantiated. | 76 | // BlockHandlerList is a list of block handlers instantiated. |
71 | type BlockHandlerList struct { | 77 | type BlockHandlerList struct { |
72 | list map[int]BlockHandler // list of handler instances | 78 | list map[int]BlockHandler // list of handler instances |
79 | counts util.CounterMap // count number of RRs by type | ||
73 | } | 80 | } |
74 | 81 | ||
75 | // NewBlockHandlerList instantiates an a list of active block handlers | 82 | // NewBlockHandlerList instantiates an a list of active block handlers |
@@ -77,24 +84,21 @@ type BlockHandlerList struct { | |||
77 | func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) (*BlockHandlerList, error) { | 84 | func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) (*BlockHandlerList, error) { |
78 | // initialize block handler list | 85 | // initialize block handler list |
79 | hl := &BlockHandlerList{ | 86 | hl := &BlockHandlerList{ |
80 | list: make(map[int]BlockHandler), | 87 | list: make(map[int]BlockHandler), |
88 | counts: make(util.CounterMap), | ||
81 | } | 89 | } |
82 | // build a list of record types that are handled by a custom handler. | ||
83 | rrList := NewRRTypeList( | ||
84 | enums.GNS_TYPE_PKEY, | ||
85 | enums.GNS_TYPE_GNS2DNS, | ||
86 | enums.GNS_TYPE_BOX, | ||
87 | enums.GNS_TYPE_LEHO) | ||
88 | 90 | ||
89 | // Traverse record list and build list of handler instances | 91 | // Traverse record list and build list of handler instances |
90 | for _, rec := range records { | 92 | for _, rec := range records { |
91 | // check for custom handler type | 93 | // update counter map |
92 | rrType := int(rec.Type) | 94 | rrType := int(rec.Type) |
93 | if rrList.HasType(rrType) { | 95 | hl.counts.Add(rrType) |
96 | |||
97 | // check for custom handler type | ||
98 | if creat, ok := customHandler[rrType]; ok { | ||
94 | // check if a handler for given type already exists | 99 | // check if a handler for given type already exists |
95 | var ( | 100 | var ( |
96 | hdlr BlockHandler | 101 | hdlr BlockHandler |
97 | ok bool | ||
98 | err error | 102 | err error |
99 | ) | 103 | ) |
100 | if hdlr, ok = hl.list[rrType]; ok { | 104 | if hdlr, ok = hl.list[rrType]; ok { |
@@ -105,23 +109,22 @@ func NewBlockHandlerList(records []*message.GNSResourceRecord, labels []string) | |||
105 | continue | 109 | continue |
106 | } | 110 | } |
107 | // create a new handler instance | 111 | // create a new handler instance |
108 | switch rrType { | 112 | if hdlr, err = creat(rec, labels); err != nil { |
109 | case enums.GNS_TYPE_PKEY: | ||
110 | hdlr, err = NewPkeyHandler(rec, labels) | ||
111 | case enums.GNS_TYPE_GNS2DNS: | ||
112 | hdlr, err = NewGns2DnsHandler(rec, labels) | ||
113 | case enums.GNS_TYPE_BOX: | ||
114 | hdlr, err = NewBoxHandler(rec, labels) | ||
115 | case enums.GNS_TYPE_LEHO: | ||
116 | hdlr, err = NewLehoHandler(rec, labels) | ||
117 | } | ||
118 | if err != nil { | ||
119 | return nil, err | 113 | return nil, err |
120 | } | 114 | } |
121 | // store handler in list | 115 | // store handler in list |
122 | hl.list[rrType] = hdlr | 116 | hl.list[rrType] = hdlr |
123 | } | 117 | } |
124 | } | 118 | } |
119 | |||
120 | // Check if all registered handlers in list can co-exist with | ||
121 | // all the other records of varying type | ||
122 | for _, hdlr := range hl.list { | ||
123 | if !hdlr.Coexist(hl.counts) { | ||
124 | return nil, ErrInvalidRecordMix | ||
125 | } | ||
126 | } | ||
127 | // return assembled handler list | ||
125 | return hl, nil | 128 | return hl, nil |
126 | } | 129 | } |
127 | 130 | ||
@@ -179,14 +182,11 @@ func (h *PkeyHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) | |||
179 | return nil | 182 | return nil |
180 | } | 183 | } |
181 | 184 | ||
182 | // TypeAction return a flag indicating how a resource record of a given type | 185 | // Coexist return a flag indicating how a resource record of a given type |
183 | // is to be treated (see BlockHandler interface) | 186 | // is to be treated (see BlockHandler interface) |
184 | func (h *PkeyHandler) TypeAction(t int) int { | 187 | func (h *PkeyHandler) Coexist(cm util.CounterMap) bool { |
185 | // no other resource record type is not allowed | 188 | // only one type (GNS_TYPE_PKEY) is present |
186 | if t == enums.GNS_TYPE_PKEY { | 189 | return len(cm) == 1 && cm.Num(enums.GNS_TYPE_PKEY) == 1 |
187 | return 1 | ||
188 | } | ||
189 | return -1 | ||
190 | } | 190 | } |
191 | 191 | ||
192 | // Records returns a list of RR of the given type associated with this handler | 192 | // Records returns a list of RR of the given type associated with this handler |
@@ -252,11 +252,11 @@ func (h *Gns2DnsHandler) AddRecord(rec *message.GNSResourceRecord, labels []stri | |||
252 | return nil | 252 | return nil |
253 | } | 253 | } |
254 | 254 | ||
255 | // TypeAction return a flag indicating how a resource record of a given type | 255 | // Coexist return a flag indicating how a resource record of a given type |
256 | // is to be treated (see BlockHandler interface) | 256 | // is to be treated (see BlockHandler interface) |
257 | func (h *Gns2DnsHandler) TypeAction(t int) int { | 257 | func (h *Gns2DnsHandler) Coexist(cm util.CounterMap) bool { |
258 | // anything goes... | 258 | // only one type (GNS_TYPE_GNS2DNS) is present |
259 | return 1 | 259 | return len(cm) == 1 && cm.Num(enums.GNS_TYPE_GNS2DNS) > 0 |
260 | } | 260 | } |
261 | 261 | ||
262 | // Records returns a list of RR of the given type associated with this handler | 262 | // Records returns a list of RR of the given type associated with this handler |
@@ -317,11 +317,11 @@ func (h *BoxHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) | |||
317 | return nil | 317 | return nil |
318 | } | 318 | } |
319 | 319 | ||
320 | // TypeAction return a flag indicating how a resource record of a given type | 320 | // Coexist return a flag indicating how a resource record of a given type |
321 | // is to be treated (see BlockHandler interface) | 321 | // is to be treated (see BlockHandler interface) |
322 | func (h *BoxHandler) TypeAction(t int) int { | 322 | func (h *BoxHandler) Coexist(cm util.CounterMap) bool { |
323 | // anything goes... | 323 | // anything goes... |
324 | return 1 | 324 | return true |
325 | } | 325 | } |
326 | 326 | ||
327 | // Records returns a list of RR of the given type associated with this handler | 327 | // Records returns a list of RR of the given type associated with this handler |
@@ -376,16 +376,17 @@ func (h *LehoHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) | |||
376 | return nil | 376 | return nil |
377 | } | 377 | } |
378 | 378 | ||
379 | // TypeAction return a flag indicating how a resource record of a given type | 379 | // Coexist return a flag indicating how a resource record of a given type |
380 | // is to be treated (see BlockHandler interface) | 380 | // is to be treated (see BlockHandler interface) |
381 | func (h *LehoHandler) TypeAction(t int) int { | 381 | func (h *LehoHandler) Coexist(cm util.CounterMap) bool { |
382 | // only A and AAAA records allowed beside LEHO | 382 | // requires exactly one A/AAAA record alongside single LEHO |
383 | switch t { | 383 | if len(cm) != 2 { |
384 | case enums.GNS_TYPE_LEHO, enums.GNS_TYPE_DNS_A, enums.GNS_TYPE_DNS_AAAA: | 384 | return false |
385 | return 1 | ||
386 | default: | ||
387 | return -1 | ||
388 | } | 385 | } |
386 | if cm.Num(enums.GNS_TYPE_LEHO) != 1 { | ||
387 | return false | ||
388 | } | ||
389 | return cm.Num(enums.GNS_TYPE_DNS_A) == 1 || cm.Num(enums.GNS_TYPE_DNS_AAAA) == 1 | ||
389 | } | 390 | } |
390 | 391 | ||
391 | // Records returns a list of RR of the given type associated with this handler | 392 | // Records returns a list of RR of the given type associated with this handler |
@@ -396,3 +397,56 @@ func (h *LehoHandler) Records(kind RRTypeList) *GNSRecordSet { | |||
396 | } | 397 | } |
397 | return rs | 398 | return rs |
398 | } | 399 | } |
400 | |||
401 | //---------------------------------------------------------------------- | ||
402 | // CNAME handler | ||
403 | //---------------------------------------------------------------------- | ||
404 | |||
405 | // CnameHandler implementing the BlockHandler interface | ||
406 | type CnameHandler struct { | ||
407 | name string | ||
408 | rec *message.GNSResourceRecord | ||
409 | } | ||
410 | |||
411 | // NewCnameHandler returns a new BlockHandler instance | ||
412 | func NewCnameHandler(rec *message.GNSResourceRecord, labels []string) (BlockHandler, error) { | ||
413 | if int(rec.Type) != enums.GNS_TYPE_DNS_CNAME { | ||
414 | return nil, ErrInvalidRecordType | ||
415 | } | ||
416 | h := &CnameHandler{ | ||
417 | name: "", | ||
418 | } | ||
419 | if err := h.AddRecord(rec, labels); err != nil { | ||
420 | return nil, err | ||
421 | } | ||
422 | return h, nil | ||
423 | } | ||
424 | |||
425 | // AddRecord inserts a CNAME record into the handler. | ||
426 | func (h *CnameHandler) AddRecord(rec *message.GNSResourceRecord, labels []string) error { | ||
427 | if int(rec.Type) != enums.GNS_TYPE_DNS_CNAME { | ||
428 | return ErrInvalidRecordType | ||
429 | } | ||
430 | if h.rec != nil { | ||
431 | return ErrInvalidCNAME | ||
432 | } | ||
433 | _, h.name = DNSNameFromBytes(rec.Data, 0) | ||
434 | h.rec = rec | ||
435 | return nil | ||
436 | } | ||
437 | |||
438 | // Coexist return a flag indicating how a resource record of a given type | ||
439 | // is to be treated (see BlockHandler interface) | ||
440 | func (h *CnameHandler) Coexist(cm util.CounterMap) bool { | ||
441 | // anything goes | ||
442 | return true | ||
443 | } | ||
444 | |||
445 | // Records returns a list of RR of the given type associated with this handler | ||
446 | func (h *CnameHandler) Records(kind RRTypeList) *GNSRecordSet { | ||
447 | rs := NewGNSRecordSet() | ||
448 | if kind.HasType(enums.GNS_TYPE_DNS_CNAME) { | ||
449 | rs.AddRecord(h.rec) | ||
450 | } | ||
451 | return rs | ||
452 | } | ||