1 /** @file
2     WCCP (v2) support for Apache Traffic Server.
3 
4     @section license License
5 
6     Licensed to the Apache Software Foundation (ASF) under one
7     or more contributor license agreements.  See the NOTICE file
8     distributed with this work for additional information
9     regarding copyright ownership.  The ASF licenses this file
10     to you under the Apache License, Version 2.0 (the
11     "License"); you may not use this file except in compliance
12     with the License.  You may obtain a copy of the License at
13 
14     http://www.apache.org/licenses/LICENSE-2.0
15 
16     Unless required by applicable law or agreed to in writing, software
17     distributed under the License is distributed on an "AS IS" BASIS,
18     WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19     See the License for the specific language governing permissions and
20     limitations under the License.
21  */
22 
23 #pragma once
24 
25 #include "wccp/Wccp.h"
26 #include "WccpUtil.h"
27 #include "ts/apidefs.h"
28 #include "tscore/Errata.h"
29 // Needed for template use of byte ordering functions.
30 #include <netinet/in.h>
31 #include <memory.h>
32 #include <map>
33 #include <string_view>
34 
35 namespace YAML
36 {
37 class Node;
38 };
39 
40 namespace wccp
41 {
42 // Forward declares
43 namespace detail
44 {
45   class Assignment;
46   namespace cache
47   {
48     struct RouterData;
49   }
50 } // namespace detail
51 
52 /// Default port used by the protocol.
53 static unsigned int const DEFAULT_PORT = 2048;
54 /// Number of buckets in WCCP hash allocation.
55 static unsigned int const N_BUCKETS = 256;
56 /// Unassigned bucket value (defined by protocol).
57 static uint8_t const UNASSIGNED_BUCKET = 0xFF;
58 /// Size of group password in octets.
59 static unsigned int const GROUP_PASSWORD_SIZE = 8;
60 /// Maximum # of caches
61 static uint32_t const MAX_CACHES = 32;
62 /// Maximum # of routers
63 static uint32_t const MAX_ROUTERS = 32;
64 
65 /// Our version of the protocol.
66 static unsigned int const VERSION = 0x200;
67 
68 /// @name Parse results.
69 /// @note Internal values are positive. System errors are reported as
70 /// the negative of errno.
71 //@{
72 /// Successful parse (message is well formatted)
73 static int const PARSE_SUCCESS = 0;
74 /// Component is the wrong type but looks like a valid type.
75 static int const PARSE_COMP_OTHER_TYPE = 1;
76 /// Component has a bogus type (cannot be valid).
77 static int const PARSE_COMP_TYPE_INVALID = 2;
78 /// Length in message is larger than actual message data.
79 static int const PARSE_MSG_TOO_BIG = 3;
80 /// Message header has invalid data.
81 static int const PARSE_MSG_INVALID = 5;
82 /// Component is malformed.
83 static int const PARSE_COMP_INVALID = 4;
84 /// Message is not the expected type.
85 static int const PARSE_MSG_WRONG_TYPE = 6;
86 /// Variable data for component can't fit in remaining data.
87 static int const PARSE_COMP_TOO_BIG = 7;
88 /// Fixed data for component can't fit in remaining data.
89 static int const PARSE_BUFFER_TOO_SMALL = 8;
90 /// Stored component size doesn't agree with locally computed size.
91 static int const PARSE_COMP_WRONG_SIZE = 9;
92 /// More data in message than can be accounted for.
93 static int const PARSE_DATA_OVERRUN = 10;
94 //@}
95 
96 /** Buffer for serialized data.
97     Takes the basic ATS buffer and adds a count field to track
98     the amount of buffer in use.
99 */
100 class MsgBuffer : protected ts::Buffer
101 {
102 public:
103   typedef MsgBuffer self;   ///< Self reference type.
104   typedef ts::Buffer super; ///< Parent type.
105 
106   MsgBuffer(); ///< Default construct empty buffer.
107   /// Construct from ATS buffer.
108   MsgBuffer(super const &that ///< Instance to copy.
109   );
110   /// Construct from pointer and size.
111   MsgBuffer(void *ptr, ///< Pointer to buffer.
112             size_t n   ///< Size of buffer.
113   );
114   /// Assign a buffer.
115   MsgBuffer &set(void *ptr, ///< Pointer to buffer.
116                  size_t n   ///< Size of buffer.
117   );
118 
119   /// Get the buffer size.
120   size_t getSize() const;
121   /// Get the content size (use count).
122   size_t getCount() const;
123   /// Get address of first unused byte.
124   char *getTail();
125   /// Get address of first byte.
126   char *getBase();
127   /// Get address of first byte.
128   const char *getBase() const;
129   /// Get the remaining space in the buffer.
130   size_t getSpace() const;
131   /// Mark additional space in use.
132   self &use(size_t n ///< Additional space to mark in use.
133   );
134   /// Mark all space as unused.
135   self &reset();
136 
137   /// Reset and zero the buffer.
138   self &zero();
139 
140   size_t _count; ///< Number of bytes in use.
141 };
142 
143 /// Sect 4.4: Cache assignment method.
144 enum CacheAssignmentType {
145   ASSIGNMENT_BY_HASH = 0,
146   ASSIGNMENT_BY_MASK = 1,
147 };
148 
149 /// Top level message types.
150 enum message_type_t {
151   INVALID_MSG_TYPE = 0,
152   HERE_I_AM        = 10,
153   I_SEE_YOU        = 11,
154   REDIRECT_ASSIGN  = 12,
155   REMOVAL_QUERY    = 13,
156 };
157 
158 /// Message component type.
159 /// See Sect 5.1 - 5.4
160 enum CompType {
161   SECURITY_INFO       = 0,
162   SERVICE_INFO        = 1,
163   ROUTER_ID_INFO      = 2,
164   CACHE_ID_INFO       = 3,
165   RTR_VIEW_INFO       = 4,
166   CACHE_VIEW_INFO     = 5,
167   REDIRECT_ASSIGNMENT = 6,
168   QUERY_INFO          = 7,
169   CAPABILITY_INFO     = 8,
170   ALT_ASSIGNMENT      = 13,
171   ASSIGN_MAP          = 14,
172   COMMAND_EXTENSION   = 15,
173   COMP_TYPE_MIN       = SECURITY_INFO,
174   COMP_TYPE_MAX       = COMMAND_EXTENSION
175 };
176 
177 /// Router Identity.
178 /// Data is stored in host order. This structure is not used publicly.
179 struct RouterId {
180   typedef RouterId self; ///< Self reference type.
181 
182   RouterId(); ///< Default constructor.
183   /// Construct from address and sequence number.
184   RouterId(uint32_t addr,   ///< Router address.
185            uint32_t recv_id ///< Receive ID (sequence number).
186   );
187 
188   uint32_t m_addr;    ///< Identifying router IP address.
189   uint32_t m_recv_id; ///< Receive ID (sequence #).
190 };
191 
192 /** Sect 5.7.1: Router Identity Element.
193 
194     This maps directly on to message content.
195 
196     @internal A @c RouterId with accessors to guarantee correct memory
197     layout.
198 */
199 class RouterIdElt : protected RouterId
200 {
201 protected:
202   typedef RouterId super; ///< Parent type.
203 public:
204   typedef RouterIdElt self; ///< Self reference type.
205 
206   /// Default constructor, members zero initialized.
207   RouterIdElt();
208   /// Construct from address and sequence number.
209   RouterIdElt(uint32_t addr,   ///< Router address.
210               uint32_t recv_id ///< Receive ID (sequence number).
211   );
212 
213   /// @name Accessors
214   //@{
215   uint32_t getAddr() const;     ///< Get the address field.
216   self &setAddr(uint32_t addr); ///< Set the address field to @a addr.
217   uint32_t getRecvId() const;   ///< Get the receive ID field.
218   self &setRecvId(uint32_t id); ///< Set the receive ID field to @a id.
219   //@}
220 
221   /// Assign from non-serialized variant.
222   self &operator=(super const &that);
223 };
224 
225 /// Sect 5.7.3: Assignment Key Element
226 /// @note This maps directly on to message content.
227 /// @internal: At top level because it is used in more than one component.
228 class AssignmentKeyElt
229 {
230 public:
231   typedef AssignmentKeyElt self; ///< Self reference type.
232 
233   AssignmentKeyElt(); ///< Default constructor. No member initialization.
234   /// Construct from address and sequence number.
235   AssignmentKeyElt(uint32_t addr,      ///< Key address.
236                    uint32_t generation ///< Change number.
237   );
238 
239   /// @name Accessors
240   //@{
241   uint32_t getAddr() const;          ///< Get the address field.
242   self &setAddr(uint32_t addr);      ///< Set the address field to @a addr.
243   uint32_t getChangeNumber() const;  ///< Get change number field.
244   self &setChangeNumber(uint32_t n); ///< Set change number field to @a n.
245   //@}
246 protected:
247   uint32_t m_addr;          ///< Identifying router IP address.
248   uint32_t m_change_number; ///< Change number (sequence #).
249 };
250 
251 /// Sect 5.7.4: Router Assignment Element
252 /// @note This maps directly on to message content.
253 /// @internal: At top level because it is used in more than one component.
254 class RouterAssignElt : public RouterIdElt
255 {
256 public:
257   typedef RouterAssignElt self; ///< Self reference type.
258   typedef RouterIdElt super;    ///< Parent type.
259 
260   /// Default constructor, members zero initialized.
261   RouterAssignElt();
262   /// Construct from address and sequence number.
263   RouterAssignElt(uint32_t addr,         ///< Router address.
264                   uint32_t recv_id,      ///< Receive ID (sequence number).
265                   uint32_t change_number ///< Change number (sequence number).
266   );
267 
268   /// @name Accessors
269   //@{
270   uint32_t getChangeNumber() const;  ///< Get change number field.
271   self &setChangeNumber(uint32_t n); ///< Set change number field to @a n.
272   //@}
273 protected:
274   uint32_t m_change_number; ///< Change number (sequence #).
275 };
276 
277 /** List of @c RouterAssignElt
278     @note Not explicitly part of the spec, but it shows up in multiple
279     places.
280  */
281 class RouterAssignListElt
282 {
283 public:
284   typedef RouterAssignListElt self; ///< Self reference type.
285 
286   /// Default constructor - @b no initialization.
287   RouterAssignListElt();
288   /// Construct with @n elements.
289   RouterAssignListElt(int n ///< Number of elements.
290   );
291 
292   /// @name Accessors
293   //@{
294   /// Access element.
295   RouterAssignElt &elt(int idx ///< Index of target element.
296   );
297   /// Access const element.
298   RouterAssignElt const &elt(int idx ///< Index of target element.
299   ) const;
300   /// Get the number of elements.
301   uint32_t getCount() const;
302   //@}
303 
304   /// Update ID for a router.
305   self &updateRouterId(uint32_t addr,  ///< Identifying IP address of router.
306                        uint32_t rcvid, ///< New receive ID value.
307                        uint32_t cno    ///< New change number.
308   );
309 
310   /// Get size in bytes of this structure.
311   size_t getSize() const;
312   /// Get the size of the variable part only.
313   /// This is useful for classes that put this element in their
314   /// stub structure.
315   size_t getVarSize() const;
316   /// Calculate size in bytes for @a n elements.
317   static size_t calcSize(int n ///< Number of elements.
318   );
319   /// Calculate size of variable data in bytes for @a n elements.
320   static size_t calcVarSize(int n ///< Number of elements.
321   );
322 
323 protected:
324   uint32_t m_count; ///< # of elements (network order).
325 };
326 
327 /// Sect 5.7.5: Capability Element
328 /// @note This maps directly on to message content.
329 class CapabilityElt
330 {
331 public:
332   typedef CapabilityElt self; ///< Self reference type.
333 
334   /// Capability types.
335   enum Type : uint16_t {
336     NO_METHOD               = 0, ///< Method not set.
337     PACKET_FORWARD_METHOD   = 1, ///< Packet forwarding methods.
338     CACHE_ASSIGNMENT_METHOD = 2, ///< Cache assignment methods.
339     PACKET_RETURN_METHOD    = 3  ///< Packet return methods.
340   };
341 
342   CapabilityElt(); ///< Default constructor.
343   /// Construct from address and sequence number.
344   CapabilityElt(Type type,    ///< Capability type.
345                 uint32_t data ///< Capability data.
346   );
347 
348   /// @name Accessors
349   //@{
350   Type getCapType() const; ///< Get the capability type.
351   /// Set capability type.
352   self &setCapType(Type cap ///< Capability type.
353   );
354   uint32_t getCapData() const; ///< Get capability data.
355   /// Set capability data.
356   self &setCapData(uint32_t data ///< Data value.
357   );
358   //@}
359 protected:
360   enum Type m_cap_type  = NO_METHOD; ///< Capability type.
361   uint16_t m_cap_length = 0;         ///< Length of capability data.
362   uint32_t m_cap_data   = 0;         ///< Capability data.
363 };
364 
365 /// Sect 5.7.7: Mask element
366 class MaskElt
367 {
368 public:
369   typedef MaskElt self; ///< Self reference type.
370 
371   /// Default constructor - @b no initialization.
372   MaskElt();
373   /// Construct with specific values.
374   MaskElt(uint32_t srcAddr, ///< Mask for source address.
375           uint32_t dstAddr, ///< Mask for destination address.
376           uint16_t srcPort, ///< Mask for source port.
377           uint16_t dstPort  ///< Mask for destination port.
378   );
379 
380   /// @name Accessors
381   //@{
382   /// Get source address mask field.
383   uint32_t getSrcAddr() const;
384   /// Set source address mask field to @a mask.
385   self &setSrcAddr(uint32_t mask);
386   /// Get destination address field.
387   uint32_t getDstAddr() const;
388   /// Set destination address field to @a mask.
389   self &setDstAddr(uint32_t mask);
390   /// Get source port mask field.
391   uint16_t getSrcPort() const;
392   /// Set source port mask field to @a mask.
393   self &setSrcPort(uint16_t mask);
394   /// Get destination port mask field.
395   uint16_t getDstPort() const;
396   /// Set destination port mask field to @a mask.
397   self &setDstPort(uint16_t mask);
398   //@}
399 
400 protected:
401   uint32_t m_src_addr = INADDR_ANY; ///< Source address mask.
402   uint32_t m_dst_addr = INADDR_ANY; ///< Destination address mask.
403   uint16_t m_src_port = 0;          ///< Source port mask.
404   uint16_t m_dst_port = 0;          ///< Destination port mask.
405 };
406 
407 /// Sect 5.7.8: Value element.
408 class ValueElt
409 {
410 public:
411   typedef ValueElt self; ///< Self reference type.
412 
413   /// Default constructor - @b no initialization.
414   ValueElt();
415   /// Construct a specific value.
416   ValueElt(uint32_t cacheAddr, ///< Address of cache for this value.
417            uint32_t srcAddr,   ///< Value for source address.
418            uint32_t dstAddr,   ///< Value for destination address.
419            uint16_t srcPort,   ///< Value for source port.
420            uint16_t dstPort    ///< Value for destination port.
421   );
422 
423   /// @name Accessors
424   //@{
425   uint32_t getf_src_addr() const;     ///< Get source address field.
426   self &setf_src_addr(uint32_t addr); ///< Set source address field to @a addr.
427   uint32_t getDstAddr() const;        ///< Get destination address field.
428   self &setf_dst_addr(uint32_t addr); ///< Set destination address field to @a addr.
429   uint16_t getf_src_port() const;     ///< Get source port field.
430   self &setf_src_port(uint16_t port); ///< Set source port field to @a port.
431   uint16_t getDstPort() const;        ///< Get destination port field.
432   self &setf_dst_port(uint16_t port); ///< Set destination port field to @a port.
433   uint32_t getCacheAddr() const;      ///< Get cache address field.
434   self &setCacheAddr(uint32_t addr);  ///< Set cache address field to @a addr
435   //@}
436 
437 protected:
438   uint32_t m_src_addr;   ///< Source address.
439   uint32_t m_dst_addr;   ///< Destination address.
440   uint16_t m_src_port;   ///< Source port.
441   uint16_t m_dst_port;   ///< Destination port.
442   uint32_t m_cache_addr; ///< Cache address.
443 };
444 
445 /** Sect 5.7.6: Mask/Value Set Element
446     This is a variable sized element.
447  */
448 class MaskValueSetElt
449 {
450 public:
451   typedef MaskValueSetElt self; ///< Self reference type.
452 
453   MaskValueSetElt(); ///< Default constructor.
454   /// Construct from address and sequence number.
455   MaskValueSetElt(uint32_t n ///< Value count.
456   );
457 
458   /// @name Accessors
459   //@{
460   /// Directly access contained mask element.
461   MaskElt &maskElt();
462 
463   /// Get source address mask field.
464   uint32_t getSrcAddrMask() const;
465   /// Set source address mask field to @a mask.
466   self &setSrcAddrMask(uint32_t mask);
467   /// Get destination address field.
468   uint32_t getDstAddrMask() const;
469   /// Set destination address field to @a mask.
470   self &setDstAddrMask(uint32_t mask);
471   /// Get source port mask field.
472   uint16_t getSrcPortMask() const;
473   /// Set source port mask field to @a mask.
474   self &setSrcPortMask(uint16_t mask);
475   /// Get destination port mask field.
476   uint16_t getDstPortMask() const;
477   /// Set destination port mask field to @a mask.
478   self &setDstPortMask(uint16_t mask);
479 
480   /// Append a value to this set.
481   self &addValue(uint32_t cacheAddr, ///< Address of cache for this value.
482                  uint32_t srcAddr,   ///< Value for source address.
483                  uint32_t dstAddr,   ///< Value for destination address.
484                  uint16_t srcPort,   ///< Value for source port.
485                  uint16_t dstPort    ///< Value for destination port.
486   );
487 
488   /// Get the value count.
489   /// @note No corresponding @c set because this cannot be directly changed.
490   uint32_t getCount() const;
491   /// Access value element.
492   ValueElt &operator[](int idx ///< Index of target element.
493   );
494   //@}
495   /// Calculate the size of an element with @a n values.
496   static size_t calcSize(uint32_t n ///< Number of values.
497   );
498   /// Get the size (length) of this element.
499   size_t getSize() const;
500 
501 protected:
502   // All members are kept in network order.
503   MaskElt m_mask;   ///< Base mask element.
504   uint32_t m_count; ///< Number of value elements.
505 
506   /// Get base address of Value elements.
507   ValueElt *values();
508   /// Get base address of Value elements.
509   ValueElt const *values() const;
510 };
511 
512 /// Assignment of caches by hash.
513 /// Not in specification.
514 class HashAssignElt
515 {
516 public:
517   typedef HashAssignElt self; ///< Self reference type.
518 
519   /// Hash assignment bucket.
520   struct Bucket {
521     unsigned int m_idx : 7; ///< Cache index.
522     unsigned int m_alt : 1; ///<  Alternate hash flag.
523 
524     /// Test for unassigned value in bucket.
525     bool is_unassigned() const;
526   } __attribute__((aligned(1), packed));
527 
528   /// Default constructor - @b no initialization.
529   HashAssignElt();
530   /// Construct with @n elements.
531   HashAssignElt(int n ///< Number of elements.
532   );
533 
534   /// @name Accessors
535   //@{
536   /// Get the number of caches.
537   uint32_t getCount() const;
538   /// Get a cache address.
539   uint32_t getAddr(int idx ///< Index of target address.
540   ) const;
541   /// Set a cache address.
542   self &setAddr(int idx,      ///< Index of target address.
543                 uint32_t addr ///< Address value to set.
544   );
545   /// Access a bucket.
546   Bucket &operator[](size_t idx ///< Bucket index (0..N_BUCKETS-1)
547   );
548   /// Access a const bucket.
549   Bucket const &operator[](size_t idx ///< Bucket index (0..N_BUCKETS-1)
550   ) const;
551   //@}
552 
553   /** Do a round robin assignment.
554       The buckets are assigned round robin, starting with 0, up to the
555       index of the last cache.
556       @return @c this.
557   */
558   self &round_robin_assign();
559 
560   /// Get size in bytes of this structure.
561   size_t getSize() const;
562   /// Calculate size in bytes for @a n caches.
563   static size_t calcSize(int n ///< Number of caches.
564   );
565 
566 protected:
567   uint32_t m_count; ///< # of caches (network order).
568 
569   Bucket *getBucketBase();
570 };
571 
572 /** Assignment of caches by mask.
573     @note Not in specification.
574 
575     @internal Because this is an element, it must correspond exactly
576     to the serialized layout. Therefore we can't keep extra accounting
577     data around to make manipulation easier. We need a helper class
578     for that, which functions in a manner similar to an iterator.
579  */
580 
581 class MaskAssignElt
582 {
583 public:
584   typedef MaskAssignElt self; ///< Self reference type.
585 
586   /** A minimalist insert iterator.
587    */
588   struct appender {
589     typedef appender self; ///< Self reference type.
590     /// Get pointer to current set.
591     MaskValueSetElt *operator->();
592     /// Append a new mask/value set.
593     /// @return A pointer to the new set.
594     MaskValueSetElt *mask(uint32_t srcAddr, ///< Mask for source address.
595                           uint32_t dstAddr, ///< Mask for destination address.
596                           uint16_t srcPort, ///< Mask for source port.
597                           uint16_t dstPort  ///< Mask for destination port.
598     );
599     /// Initialize the current set to empty with specific mask values.
600     /// @return A pointer to the new set.
601     MaskValueSetElt *initSet(uint32_t srcAddr, ///< Mask for source address.
602                              uint32_t dstAddr, ///< Mask for destination address.
603                              uint16_t srcPort, ///< Mask for source port.
604                              uint16_t dstPort  ///< Mask for destination port.
605     );
606     MaskValueSetElt *m_set; ///< Current set.
607     MaskAssignElt *m_elt;   ///< Parent element.
608   };
609 
610   /// @name Accessors
611   //@{
612   /// Get the number of mask/value sets.
613   uint32_t getCount() const;
614   //@}
615 
616   appender init(uint32_t srcAddr, ///< Mask for source address.
617                 uint32_t dstAddr, ///< Mask for destination address.
618                 uint16_t srcPort, ///< Mask for source port.
619                 uint16_t dstPort  ///< Mask for destination port.
620   );
621 
622   /// Get size in bytes of this structure.
623   /// @note This is not constant time. The mask/value sets must be traversed
624   /// to get the total size.
625   size_t getSize() const;
626   /// Get the size in bytes of the variable part of this structure.
627   /// @note This is not constant time. The mask/value sets must be traversed
628   /// to get the total size.
629   size_t getVarSize() const;
630 
631 protected:
632   uint32_t m_count = 0; ///< # of sets (network order).
633 
634   friend struct appender;
635 };
636 
637 class CacheIdBox;
638 
639 /** Sect 5.7.2: Web-Cache Identity Element
640     According to the specification, this is a fixed structure with
641     hash data. However, in practice there is an undocumented variant for
642     mask assignment where it contains mask data instead of hash data.
643 
644     This class provides basic control. Two subclasses specialize for the
645     two variants. Use @c isMask to detect which variant is present.
646 
647     @note Do not add virtual methods, as reasonable as that seems because
648     this is a serialized object and the memory layout correspond to the
649     protocol definition.
650 
651     @see CacheHashIdElt
652     @see CacheMaskIdElt
653 */
654 class CacheIdElt
655 {
656   friend class CacheIdBox;
657 
658 public:
659   typedef CacheIdElt self; ///< Self reference type.
660 
661   /// Hash revision (protocol required).
662   static uint16_t const HASH_REVISION = 0;
663 
664   /// @name Accessors
665   //@{
666   uint32_t getAddr() const;        ///< Get address field.
667   self &setAddr(uint32_t addr);    ///< Set address field to @a addr.
668   uint16_t getHashRev() const;     ///< Get hash revision field.
669   self &setHashRev(uint16_t rev);  ///< Set hash revision field to @a rev.
670   self &initHashRev();             ///< Set hash revision to default value.
671   bool getUnassigned() const;      ///< Get unassigned field.
672   self &setUnassigned(bool state); ///< Set unassigned field to @a state.
673   bool isMask() const;             ///< @return @c true if this is a mask assignment.
674                                    /** Set the maskiness of this structure.
675                                        Be very careful with this, as different values change the
676                                        memory layout of the object.
677                                    */
678   self &setMask(bool state         ///< @c true to be mask, @c false to be hash.
679   );
680 
681   self &clearReserved(); ///< Set reserved bits to zero.
682   //@}
683 
684 protected:
685   uint32_t m_addr;               ///< Identifying cache IP address.
686   uint16_t m_hash_rev;           ///< Hash revision.
687   unsigned int m_reserved_0 : 7; ///< Reserved bits.
688                                  /** Cache not assigned.
689                                      If set the cache does not have an assignment in the redirection
690                                      hash table and the data in @a m_buckets is historical. This allows
691                                      a cache that was removed to be added back in the same buckets.
692                                  */
693   unsigned int m_unassigned : 1;
694   unsigned int m_reserved_1 : 1; ///< Reserved (unused).
695   unsigned int m_is_mask : 1;    ///< Set -> mask, Clear -> hash.
696   unsigned int m_reserved_2 : 6; ///< Reserved (unused).
697                                  /** Trailing elements common to all cache ID variants.
698                                      Unfortunately, although @c weight and @c status are common, they are
699                                      after the variable data and so can't be put in the base class.
700                                      Best we can do is declare a struct for them for later convenience.
701                                  */
702   struct Tail {
703     uint16_t m_weight; ///< Weight of assignment.
704     uint16_t m_status; ///< Cache status.
705   };
706 };
707 
708 /** Cache ID for Hash assignment.
709  */
710 class CacheHashIdElt : public CacheIdElt
711 {
712   friend class CacheIdBox;
713 
714 public:
715   typedef CacheHashIdElt self; ///< Self reference type.
716   typedef CacheIdElt super;    ///< Parent type.
717   /// Container for hash assignment.
718   typedef uint8_t HashBuckets[N_BUCKETS >> 3];
719   /// @name Accessors
720   //@{
721   bool getBucket(int idx) const; ///< Get bucket state at index @a idx.
722   /// Set bucket at index @a idx to @a state.
723   self &setBucket(int idx, bool state);
724   self &setBuckets(bool state); ///< Set all buckets to @a state.
725   uint16_t getWeight() const;   ///< Get weight field.
726   self &setWeight(uint16_t w);  ///< Set weight field to @a w.
727   uint16_t getStatus() const;   ///< Get status field.
728   self &setStatus(uint16_t s);  ///< Set status field to @a s.
729   //@}
730   /// Get object size in bytes.
731   size_t getSize() const;
732 
733 protected:
734   /// Bit vector of buckets assigned to this cache.
735   HashBuckets m_buckets;
736   Tail m_tail; /// Trailing values in element.
737 
738   /// Get the address of the tail elements.
739   Tail *getTailPtr();
740 };
741 
742 /** Cache ID for Mask assignment.
743     Be a little careful with this object. Because it's an element and
744     must copy the serialized data layout, almost all of the methods are
745     not constant time but require walking internal data structures.
746 
747     @internal Experimentally,
748     - A mask assign element count of zero does not work. It fails
749     with the wrongly descriptive message "incompatible assignment data".
750     - A single mask assign element with a mask set with one value seems to
751     work.
752  */
753 class CacheMaskIdElt : public CacheIdElt
754 {
755   friend class CacheIdBox;
756 
757 public:
758   typedef CacheMaskIdElt self; ///< Self reference type.
759   typedef CacheIdElt super;    ///< Parent type.
760   /// @name Accessors
761   //@{
762   uint16_t getWeight() const;  ///< Get weight field.
763   self &setWeight(uint16_t w); ///< Set weight field to @a w.
764   uint16_t getStatus() const;  ///< Get status field.
765   self &setStatus(uint16_t s); ///< Set status field to @a s.
766   /// Get the number of mask/value sets.
767   uint32_t getCount() const;
768   //@}
769   /// Get object size in bytes.
770   size_t getSize() const;
771 
772 protected:
773   /// Mask assignment data.
774   MaskAssignElt m_assign;
775   /// Get a pointer to where the tail data is.
776   /// Presumes the assignment is filled out.
777   Tail *getTailPtr();
778 };
779 
780 /** Holder for a @c CacheIdElt.
781     This class is needed because of the restrictions on element classes and
782     because a @c CacheIdElt is a variable sized element yet we need to store
783     instances of it in other classes. This box both holds an instance and
784     handles some of the memory allocation issues involved.
785  */
786 class CacheIdBox
787 {
788 public:
789   typedef CacheIdBox self; ///< Self reference type.
790 
791   /// Default constructor.
792   CacheIdBox() = default;
793 
794   /// @name Accessors
795   //@{
796   /// Get the identifying cache address.
797   uint32_t getAddr() const;
798   /// Set the identifying cache address.
799   self &setAddr(uint32_t ///< Identifying IP address.
800   );
801   uint16_t getHashRev() const;     ///< Get hash revision field.
802   self &setHashRev(uint16_t rev);  ///< Set hash revision field to @a rev.
803   self &initHashRev();             ///< Set hash revision to default value.
804   bool getUnassigned() const;      ///< Get unassigned field.
805   self &setUnassigned(bool state); ///< Set unassigned field to @a state.
806   bool isMask() const;             ///< @return @c true if this is a mask assignment.
807                                    /** Set the maskiness of this structure.
808                                        Be very careful with this, as different values change the
809                                        memory layout of the object.
810                                    */
811   self &setMask(bool state         ///< @c true to be mask, @c false to be hash.
812   );
813 
814   self &clearReserved(); ///< Set reserved bits to zero.
815   //@}
816   /// Initialize to unassigned hash.
817   /// The cache address is set to @a addr.
818   self &initDefaultHash(uint32_t addr ///< Identifying cache address.
819   );
820   /// Initialize to unassigned mask
821   /// The cache address is set to @a addr.
822   self &initDefaultMask(uint32_t addr ///< Identifying cache address.
823   );
824   /** Fill in element from source copy.
825       Internal memory is allocated and the @a src copied.
826    */
827   self &fill(self const &src ///< Original source element
828   );
829   /** Fill in element from source copy.
830       This is used to write the element to memory that is allocated
831       independently of the box.
832       @note Caller is expected to have verified sufficient buffer space.
833    */
834   self &fill(void *base,     ///< Target buffer.
835              self const &src ///< Original source element
836   );
837   /// Initialize box from an existing element in memory.
838   int parse(MsgBuffer base ///< Source memory.
839   );
840 
841   /// Get the size in bytes of the contained element.
842   size_t getSize() const;
843 
844 protected:
845   /// Force buffer to be at least @a n bytes
846   self &require(size_t n ///< Minimum buffer size required.
847   );
848 
849   CacheIdElt *m_base       = nullptr; ///< Base address of memory for element.
850   CacheIdElt::Tail *m_tail = nullptr; ///< Base address of trailing data elements.
851   size_t m_size            = 0;       ///< Size of element (valid data in buffer);
852   size_t m_cap             = 0;       ///< Size of allocated memory. Zero if external memory.
853 };
854 
855 /** Base class for all components.
856 
857     Each component is a fixed sized object that represents a
858     component in the WCCP message. The component instance points at
859     its corresponding data in the message. Values in the message are
860     accessed through accessor methods which have the form @c
861     getNAME and @c setNAME for "get field" and "set field". The
862     @c set methods return a reference to the component so that
863     they can be chained.
864 
865     Most components will have an internal typedef @c raw_t which is a
866     structure with the exact memory layout of the
867     component. Components without this typedef cannot be directed
868     represented by a C++ structure (which is why we need this
869     indirection in the first place).
870 */
871 class ComponentBase
872 {
873 public:
874   typedef ComponentBase self; ///< Self reference type.
875   /// Default constructor.
876   ComponentBase() = default;
877   /// Check for not present.
878   bool isEmpty() const;
879 
880 protected:
881   /// Base of component in message data.
882   /// If this is @c NULL then the component is not in the message.
883   char *m_base = nullptr;
884 };
885 
886 /// Synthetic component to represent the overall message header.
887 class MsgHeaderComp : public ComponentBase
888 {
889 public:
890   typedef MsgHeaderComp self;  ///< Self reference type.
891   typedef ComponentBase super; ///< Parent type.
892 
893   /// Sect 5.5:  Message Header
894   /// Serialized layout of message header.
895   struct raw_t {
896     uint32_t m_type;    ///< @c message_type_t
897     uint16_t m_version; ///< Implementation version of sender
898     uint16_t m_length;  ///< Message body length (excluding header)
899   };
900 
901   /// Default constructor.
MsgHeaderComp()902   MsgHeaderComp() {}
903   /// @name Accessors
904   //@{
905   message_type_t getType();           ///< Get message type field.
906   uint16_t getVersion();              ///< Get message version field.
907   uint16_t getLength();               ///< Get message length field.
908   self &setType(message_type_t type); ///< Set message type field to @a type.
909   self &setVersion(uint16_t version); ///< Set version field to @a version.
910   self &setLength(uint16_t length);   ///< Set length field to @a length.
911   //@}
912 
913   /// Write initial values to message data.
914   /// @a base is updated to account for this component.
915   self &fill(MsgBuffer &base, ///< [in,out] Buffer for component storage.
916              message_type_t t ///< Message type.
917   );
918 
919   /// Validate component for existing data.
920   /// @a base is updated to account for this component.
921   int parse(MsgBuffer &base ///< [in,out] Base address for component data.
922   );
923 
924   /// Compute size of a component of this type.
925   static size_t calcSize();
926 
927   /// Convert to a top level message type.
928   /// @return The converted type if valid, @c INVALID_MSG_TYPE if not.
929   static message_type_t toMsgType(int t);
930 };
931 
932 /** Intermediate base class for components with the standard component header.
933 
934     @note That's all of them except the message header itself.
935 
936     @internal This saves some work getting around C++ co-variance issues
937     with return values.
938 */
939 template <typename T ///< Child class (CRT pattern)
940           >
941 struct CompWithHeader : public ComponentBase {
942   /** Serialized layout of per component header.
943       All components except the message header start with this structure.
944       Provided for ease of use by child classes, which should
945       subclass this for their own @c raw_t.
946   */
947   struct raw_t {
948     uint16_t m_type;   ///< Serialized @ref CompType.
949     uint16_t m_length; ///< length of rest of component (not including header).
950   };
951   /** Size of header.
952       This is needed by all subclasses because the value in the length field
953       excludes this structure.
954   */
955   static size_t const HEADER_SIZE = sizeof(raw_t);
956 
957   /// @name Accessors
958   //@{
959   CompType getType() const;      ///< Get component type field.
960   uint16_t getLength() const;    ///< Get component length field.
961   T &setType(CompType type);     ///< Set component type field to @a type.
962   T &setLength(uint16_t length); ///< Set length field to @a length.
963                                  //@}
964 
965   /** Check the component header for type and length sanity.
966       This requires the (subclass) client to
967       - Do a size check to verify enough space for the component header.
968       - Set @a m_base
969 
970       This method
971       - Checks the component type against the expected type (@a ect)
972       - Checks stored component length against the buffer size.
973 
974       @return A parse result.
975   */
976   int checkHeader(MsgBuffer const &buffer, ///< Message buffer.
977                   CompType t               ///< Expected component type.
978   );
979 };
980 
981 /** Sect 5.6.1: Security Info Component
982     This is used for both security options. Clients should check
983     the @c m_option to see if the @a m_impl member is valid.
984 */
985 class SecurityComp : public CompWithHeader<SecurityComp>
986 {
987 public:
988   typedef SecurityComp self;          ///< Self reference type.
989   typedef CompWithHeader<self> super; ///< Parent type.
990   /// Specify the type for this component.
991   static CompType const COMP_TYPE = SECURITY_INFO;
992 
993   /// Import security option type.
994   typedef SecurityOption Option;
995 
996   static size_t const KEY_SIZE = 8;
997   typedef char Key[KEY_SIZE];
998 
999   /// Raw memory layout, no security.
1000   struct RawNone : public super::raw_t {
1001     uint32_t m_option; ///< @c Option
1002   };
1003 
1004   /// Raw memory layout, with MD5.
1005   struct RawMD5 : public RawNone {
1006     /// Size of MD5 hash (in bytes).
1007     static size_t const HASH_SIZE = 16;
1008     /// Storage for MD5 hash.
1009     typedef uint8_t HashData[HASH_SIZE];
1010     /// MD5 hash value.
1011     HashData m_data;
1012   };
1013 
1014   /// Default constructor.
1015   SecurityComp();
1016 
1017   /// @name Accessors
1018   //@{
1019   Option getOption() const;    ///< Get security option field.
1020   self &setOption(Option opt); ///< Set security option field to @a opt.
1021   //@}
1022 
1023   /// Write default values to the serialization buffer.
1024   self &fill(MsgBuffer &buffer, Option opt = m_default_opt);
1025   /// Validate an existing structure.
1026   int parse(MsgBuffer &buffer);
1027 
1028   /// Compute the memory size of the component.
1029   static size_t calcSize(Option opt);
1030 
1031   /// Set the global / default security key.
1032   /// This is used for the security hash unless the local key is set.
1033   /// @a key is copied to a global buffer and clipped to @c KEY_SIZE bytes.
1034   static void setDefaultKey(const char *key ///< Shared key.
1035   );
1036   static void setDefaultOption(Option opt ///< Type of security.
1037   );
1038 
1039   /// Set message local security key.
1040   self &setKey(const char *key ///< Shared key.
1041   );
1042 
1043   /// Compute and set the security data.
1044   /// @a msg must be a buffer that covers exactly the entire message.
1045   self &secure(MsgBuffer const &msg ///< Message data.
1046   );
1047 
1048   bool validate(MsgBuffer const &msg ///< Message data.
1049   ) const;
1050 
1051 protected:
1052   /// Local to this message shared key / password.
1053   Key m_key;
1054   /// Use local key.
1055   bool m_local_key;
1056   /// Global (static) shared key / password.
1057   static Key m_default_key;
1058   /// Default security option.
1059   static Option m_default_opt;
1060 };
1061 
1062 /// Sect 5.6.2: Service Info Component
1063 class ServiceComp : public CompWithHeader<ServiceComp>
1064 {
1065 public:
1066   typedef ServiceComp self;           ///< Self reference type.
1067   typedef CompWithHeader<self> super; ///< Parent type.
1068 
1069   /// Specify the type for this component.
1070   static CompType const COMP_TYPE = SERVICE_INFO;
1071 
1072   /// Serialized format for component.
1073   struct raw_t : public super::raw_t, public ServiceGroup {
1074   };
1075 
1076   ServiceComp(); ///< Default constructor, no member initialization.
1077 
1078   /// @name Accessors
1079   //@{
1080   ServiceGroup::Type getSvcType() const; ///< Get service type field.
1081                                          /** Set the service type.
1082                                              If @a svc is @c SERVICE_STANDARD then all fields except the
1083                                              component header and service id are set to zero as required
1084                                              by the protocol.
1085                                          */
1086   self &setSvcType(ServiceGroup::Type svc);
1087 
1088   uint8_t getSvcId() const;   ///< Get service ID field.
1089   self &setSvcId(uint8_t id); ///< Set service ID field to @a id.
1090 
1091   uint8_t getPriority() const;    ///< Get priority field.
1092   self &setPriority(uint8_t pri); ///< Set priority field to @a p.
1093 
1094   uint8_t getProtocol() const;  ///< Get protocol field.
1095   self &setProtocol(uint8_t p); ///< Set protocol field to @a p.
1096 
1097   uint32_t getFlags() const;  ///< Get flags field.
1098   self &setFlags(uint32_t f); ///< Set the flags flags in field to @a f.
1099   /// Set the flags in the flag field that are set in @a f.
1100   /// Other flags are unchanged.
1101   self &enableFlags(uint32_t f);
1102   /// Clear the flags in the flag field that are set in @a f.
1103   /// Other flags are unchanged.
1104   self &disableFlags(uint32_t f);
1105 
1106   /// Get a port value.
1107   uint16_t getPort(int idx ///< Index of target port.
1108   ) const;
1109   /// Set a port value.
1110   self &setPort(int idx,      ///< Index of port.
1111                 uint16_t port ///< Value for port.
1112   );
1113   /// Zero (clear) all ports.
1114   self &clearPorts();
1115   /** Add a port to the service.
1116       The first port which has not been set is set to @a port. It is an error
1117       to add more than @c N_PORTS ports.
1118    */
1119   self &addPort(uint16_t port ///< Port value.
1120   );
1121   //@}
1122 
1123   /// Raw access to ServiceGroup.
1124   operator ServiceGroup const &() const;
1125 
1126   /** Fill from a service group definition.
1127    */
1128   self &fill(MsgBuffer &base,        ///< Target storage.
1129              ServiceGroup const &svc ///< Service group definition.
1130   );
1131 
1132   /// Validate an existing structure.
1133   /// @return Parse result.
1134   int parse(MsgBuffer &buffer);
1135 
1136   /// Compute the memory size of the component.
1137   static size_t calcSize();
1138 
1139 protected:
1140   int m_port_count; ///< Number of ports in use.
1141 
1142   /// Cast raw internal pointer to data type.
1143   raw_t *access();
1144   /// Cast raw internal pointer to data type.
1145   raw_t const *access() const;
1146 };
1147 
1148 /// Sect 5.6.3: RouterIdentity Info Component
1149 /// @note An instance of this struct is followed by @a m_count
1150 /// IP addresses.
1151 class RouterIdComp : public CompWithHeader<RouterIdComp>
1152 {
1153 public:
1154   typedef RouterIdComp self;          ///< Self reference type.
1155   typedef CompWithHeader<self> super; ///< Parent type.
1156 
1157   /// Specify the type for this component.
1158   static CompType const COMP_TYPE = ROUTER_ID_INFO;
1159 
1160   /// Stub of serialized layout.
1161   struct raw_t : public super::raw_t {
1162     RouterIdElt m_id; ///< Router ID element.
1163     /// Source address.
1164     /// For response messages, this is the address to which the
1165     /// original message was sent.
1166     uint32_t m_to_addr;
1167     /// # of target cache addresses.
1168     uint32_t m_from_count;
1169     // Addresses follow here.
1170   };
1171 
1172   /// @name Accessors
1173   //@{
1174   /// Directly access router ID element.
1175   RouterIdElt &idElt();
1176   /// Directly access router ID element.
1177   RouterIdElt const &idElt() const;
1178   /// Set the fields in the router ID element.
1179   self &setIdElt(uint32_t addr,   ///< Identifying IP address for router.
1180                  uint32_t recv_id ///< Receive count for router to target cache.
1181   );
1182   uint32_t getAddr() const;     ///< Get the address field in the ID element.
1183   self &setAddr(uint32_t addr); ///< Set the address field in the ID element.
1184   uint32_t getRecvId() const;   ///< Get the receive ID field in the ID element.
1185   self &setRecvId(uint32_t id); ///< Set the receive ID field in the ID element.
1186 
1187   /// Get the sent to address.
1188   uint32_t getToAddr() const;
1189   /// Set the sent to address.
1190   self &setToAddr(uint32_t addr ///< Address value.
1191   );
1192   /// Get router count field.
1193   /// @note No @c setf method because this cannot be changed independently.
1194   /// @see fill
1195   uint32_t getFromCount() const;
1196   /// Get received from address.
1197   uint32_t getFromAddr(int idx ///< Index of address.
1198   ) const;
1199   /// Set received from address.
1200   self &setFromAddr(int idx,      ///< Index of address.
1201                     uint32_t addr ///< Address value.
1202   );
1203   //@}
1204   /// Find an address in the from list.
1205   /// @return The index of the address, or -1 if not found.
1206   int findFromAddr(uint32_t addr ///< Search value.
1207   );
1208 
1209   /** Write serialization data for single cache target.
1210       This completely fills the component.
1211   */
1212   self &fillSingleton(MsgBuffer &base,     ///< Target storage.
1213                       uint32_t addr,       ///< Identifying IP address.
1214                       uint32_t recv_count, ///< Receive count for target cache.
1215                       uint32_t to_addr,    ///< Destination address in initial packet.
1216                       uint32_t from_addr   ///< Identifying IP address of target cache.
1217   );
1218 
1219   /** Write basic message structure.
1220       The router and cache data must be filled in separately.
1221   */
1222   self &fill(MsgBuffer &base, ///< Target storage.
1223              size_t n_caches  ///< Number of caches (fromAddr).
1224   );
1225 
1226   /// Validate an existing structure.
1227   /// @return Parse result.
1228   int parse(MsgBuffer &buffer);
1229 
1230   /// Compute the memory size of the component.
1231   static size_t calcSize(int n ///< Receive address count
1232   );
1233 };
1234 
1235 /** Sect 5.6.4: Web-Cache Identity Info Component
1236  */
1237 class CacheIdComp : public CompWithHeader<CacheIdComp>
1238 {
1239 public:
1240   typedef CacheIdComp self;           ///< Self reference type.
1241   typedef CompWithHeader<self> super; ///< Parent type.
1242 
1243   /// Component type ID for this component.
1244   static CompType const COMP_TYPE = CACHE_ID_INFO;
1245 
1246   /// Serialized format.
1247   struct raw_t : public super::raw_t {
1248     CacheIdElt m_id; ///< Identity element stub.
1249   };
1250 
1251   /// @name Accessors
1252   //@{
1253   /// Direct access to the cache ID element.
1254   CacheIdBox &cacheId();
1255   CacheIdBox const &cacheId() const;
1256 
1257   // Only forward the common ones.
1258   uint32_t getAddr() const;        ///< Get address field.
1259   self &setAddr(uint32_t addr);    ///< Set address field to @a addr.
1260   uint16_t getHashRev() const;     ///< Get hash revision field.
1261   self &setHashRev(uint16_t rev);  ///< Set hash revision field to @a rev.
1262   bool getUnassigned() const;      ///< Get unassigned field.
1263   self &setUnassigned(bool state); ///< Set unassigned field to @a state.
1264   uint16_t getWeight() const;      ///< Get weight field.
1265   self &setWeight(uint16_t w);     ///< Set weight field to @a w.
1266   uint16_t getStatus() const;      ///< Get status field.
1267   self &setStatus(uint16_t s);     ///< Set status field to @a s.
1268                                    //@}
1269 
1270   /** Write serialization data.
1271       - Sets required header fields for the component.
1272       - Copies the data from @a src.
1273   */
1274   self &fill(MsgBuffer &base,      ///< Target storage.
1275              CacheIdBox const &src ///< Cache descriptor
1276   );
1277 
1278   /// Validate an existing structure.
1279   /// @return Parse result.
1280   int parse(MsgBuffer &buffer);
1281 
1282   /// Compute the memory size of the component.
1283   /// Cannot be reliably computed statically.
1284   size_t getSize();
1285 
1286 protected:
1287   CacheIdBox m_box; ///< Wrapper for cache id element.
1288 };
1289 
1290 /** Sect 5.6.5: Router View Info Component
1291  */
1292 class RouterViewComp : public CompWithHeader<RouterViewComp>
1293 {
1294 public:
1295   typedef RouterViewComp self;        ///< Self reference type.
1296   typedef CompWithHeader<self> super; ///< Parent type.
1297 
1298   /// Component type ID for this component.
1299   static CompType const COMP_TYPE = RTR_VIEW_INFO;
1300 
1301   /// Stub of the serialized data.
1302   /// There is more variable sized data that must be handled specially.
1303   struct raw_t : public super::raw_t {
1304     uint32_t m_change_number; ///< Sequence number.
1305     AssignmentKeyElt m_key;   ///< Assignment data.
1306     uint32_t m_router_count;  ///< # of router elements.
1307   };
1308 
1309   RouterViewComp();
1310 
1311   /// @name Accessors
1312   //@{
1313   /// Directly access assignment key.
1314   AssignmentKeyElt &keyElt();
1315   /// Directly access assignment key.
1316   AssignmentKeyElt const &keyElt() const;
1317   /// Get address in assignment key.
1318   uint32_t getKeyAddr() const;
1319   /// Set address in assignment key.
1320   self &setKeyAddr(uint32_t addr);
1321   /// Get change number in assignment key.
1322   uint32_t getKeyChangeNumber() const;
1323   /// Set change number in assignment key.
1324   self &setKeyChangeNumber(uint32_t n);
1325 
1326   uint32_t getChangeNumber() const;  ///< Get change number field.
1327   self &setChangeNumber(uint32_t n); ///< Set change number field to @a n
1328 
1329   /// Get cache count field.
1330   /// @note No @c setf method because this cannot be changed independently.
1331   /// @see fill
1332   uint32_t getCacheCount() const;
1333   /// Access cache element.
1334   CacheIdBox &cacheId(int idx ///< Index of target element.
1335   );
1336   /// Access cache element.
1337   CacheIdBox const &cacheId(int idx ///< Index of target element.
1338   ) const;
1339   /// Get router count field.
1340   /// @note No @c setf method because this cannot be changed independently.
1341   /// @see fill
1342   uint32_t getRouterCount() const;
1343   /// Get router address.
1344   uint32_t getRouterAddr(int idx ///< Index of router.
1345   ) const;
1346   /// Set router address.
1347   self &setRouterAddr(int idx,      ///< Index of router.
1348                       uint32_t addr ///< Address value.
1349   );
1350   //@}
1351 
1352   /** Write serialization data.
1353 
1354       A client @b must call this method before writing any fields directly.
1355       After invocation the client must fill in the router and cache elements.
1356   */
1357   self &fill(MsgBuffer &base, ///< Target storage.
1358              int n_routers,   ///< Number of routers in view.
1359              int n_caches     ///< Number of caches in view.
1360   );
1361 
1362   /// Validate an existing structure.
1363   /// @return Parse result.
1364   int parse(MsgBuffer &buffer);
1365 
1366 protected:
1367   /// Serialized count of cache addresses.
1368   /// The actual addresses start immediate after this.
1369   uint32_t *m_cache_count;
1370   /// Wrappers for cache identity elements.
1371   /// These are variably sized in the general case.
1372   CacheIdBox m_cache_ids[MAX_CACHES];
1373 
1374   /// Compute the address of the cache count field.
1375   /// Assumes the router count field is set.
1376   uint32_t *calc_cache_count_ptr();
1377 };
1378 
1379 /** Sect 5.6.6: Web-Cache View Info Component
1380  */
1381 class CacheViewComp : public CompWithHeader<CacheViewComp>
1382 {
1383 public:
1384   typedef CacheViewComp self;         ///< Self reference type.
1385   typedef CompWithHeader<self> super; ///< Parent type.
1386 
1387   /// Component type ID for this component.
1388   static CompType const COMP_TYPE = CACHE_VIEW_INFO;
1389 
1390   /// Stub of the serialized data.
1391   /// There is more variable sized data that must be handled specially.
1392   struct raw_t : public super::raw_t {
1393     uint32_t m_change_number; ///< Sequence number.
1394     uint32_t m_router_count;  ///< # of router ID elements.
1395   };
1396 
1397   /// @name Accessors
1398   //@{
1399   uint32_t getChangeNumber() const;  ///< Get change number field.
1400   self &setChangeNumber(uint32_t n); ///< Set change number field to @a n
1401 
1402   /// Get router count field.
1403   /// @note No @c setf method because this cannot be changed independently.
1404   /// @see fill
1405   uint32_t getRouterCount() const;
1406   /// Access a router ID element.
1407   RouterIdElt &routerElt(int idx ///< Index of target element.
1408   );
1409   /** Find a router element by router IP address.
1410       @return A pointer to the router element or @c NULL
1411       if no router is identified by @a addr.
1412   */
1413   RouterIdElt *findf_router_elt(uint32_t addr ///< Router IP address.
1414   );
1415   /// Get cache count field.
1416   /// @note No @c setf method because this cannot be changed independently.
1417   /// @see fill
1418   uint32_t getCacheCount() const;
1419   /// Get a cache address.
1420   uint32_t getCacheAddr(int idx ///< Index of target address.
1421   ) const;
1422   /// Set a cache address.
1423   self &setCacheAddr(int idx,      ///< Index of target address.
1424                      uint32_t addr ///< Address value to set.
1425   );
1426   //@}
1427 
1428   /** Write serialization data.
1429 
1430       A client @b must call this method before writing any fields directly.
1431       After invocation the client must fill in the router and cache elements.
1432   */
1433   self &fill(MsgBuffer &buffer,                    ///< Target storage.
1434              detail::cache::GroupData const &group ///< Service group information.
1435   );
1436 
1437   /// Validate an existing structure.
1438   /// @return Parse result.
1439   int parse(MsgBuffer &buffer);
1440 
1441   /// Compute the total size of the component.
1442   static size_t calcSize(int n_routers, ///< Number of routers in view.
1443                          int n_caches   ///< Number of caches in view.
1444   );
1445 
1446 protected:
1447   /// Get router element array.
1448   /// @return A pointer to the first router element.
1449   RouterIdElt *atf_router_array();
1450   /// Serialized count of cache addresses.
1451   /// The actual addresses start immediate after this.
1452   uint32_t *m_cache_count;
1453 };
1454 
1455 /** Sect 5.6.7: Assignment Info Component
1456  */
1457 class AssignInfoComp : public CompWithHeader<AssignInfoComp>
1458 {
1459 public:
1460   typedef AssignInfoComp self;        ///< Self reference type.
1461   typedef CompWithHeader<self> super; ///< Parent type.
1462 
1463   /// Component type ID for this component.
1464   static CompType const COMP_TYPE = REDIRECT_ASSIGNMENT;
1465 
1466   /// Stub of the serialized data.
1467   /// There is more variable sized data that must be handled specially.
1468   struct raw_t : public super::raw_t {
1469     AssignmentKeyElt m_key;        ///< Assignment key data.
1470     RouterAssignListElt m_routers; ///< Routers.
1471   };
1472   typedef HashAssignElt::Bucket Bucket; ///< Import type.
1473 
1474   /// @name Accessors
1475   //@{
1476   /// Directly access assignment key.
1477   AssignmentKeyElt &keyElt();
1478   /// Directly access assignment key.
1479   AssignmentKeyElt const &keyElt() const;
1480   /// Get address in assignment key.
1481   uint32_t getKeyAddr() const;
1482   /// Set address in assignment key.
1483   self &setKeyAddr(uint32_t addr);
1484   /// Get change number in assignment key.
1485   uint32_t getKeyChangeNumber() const;
1486   /// Set change number in assignment key.
1487   self &setKeyChangeNumber(uint32_t n);
1488 
1489   /// Get router count field.
1490   /// @note No @c setf method because this cannot be changed independently.
1491   /// @see fill
1492   uint32_t getRouterCount() const;
1493   /// Access a router assignment element.
1494   RouterAssignElt &routerElt(int idx ///< Index of target element.
1495   );
1496   /// Get cache count field.
1497   /// @note No @c setf method because this cannot be changed independently.
1498   /// @see fill
1499   uint32_t getCacheCount() const;
1500   /// Get a cache address.
1501   uint32_t getCacheAddr(int idx ///< Index of target address.
1502   ) const;
1503   /// Set a cache address.
1504   self &setCacheAddr(int idx,      ///< Index of target address.
1505                      uint32_t addr ///< Address value to set.
1506   );
1507   /// Access a bucket.
1508   Bucket &bucket(int idx ///< Index of target bucket.
1509   );
1510   /// Access a bucket.
1511   Bucket const &bucket(int idx ///< Index of target bucket.
1512   ) const;
1513   //@}
1514 
1515   /// Fill out the component from an @c Assignment.
1516   self &fill(MsgBuffer &buffer,               ///< Target storage.
1517              detail::Assignment const &assign ///< Assignment data.
1518   );
1519 
1520   /// Validate an existing structure.
1521   /// @return Parse result.
1522   int parse(MsgBuffer &buffer);
1523 
1524   /// Compute the total size of the component.
1525   static size_t calcSize(int n_routers, ///< Number of routers in view.
1526                          int n_caches   ///< Number of caches in view.
1527   );
1528 
1529 protected:
1530   /// Serialized count of cache addresses.
1531   /// The actual addresses start immediate after this.
1532   uint32_t *m_cache_count;
1533   /// Serialized bucket data.
1534   Bucket *m_buckets;
1535   /// Calculate the address of the cache count.
1536   uint32_t *calcCacheCountPtr();
1537   /// Calculate the address of the bucket array.
1538   Bucket *calcBucketPtr();
1539 };
1540 
1541 /** Sect 5.6.9: Capabilities Info Component
1542  */
1543 class CapComp : public CompWithHeader<CapComp>
1544 {
1545 public:
1546   typedef CapComp self;               ///< Self reference type.
1547   typedef CompWithHeader<self> super; ///< Parent type.
1548 
1549   /// Component type ID for this component.
1550   static CompType const COMP_TYPE = CAPABILITY_INFO;
1551 
1552   // Not even a stub for this component, just an array of elements.
1553 
1554   /// Default constructor.
1555   CapComp();
1556 
1557   /// @name Accessors.
1558   //@{
1559   /// Directly access mask value element.
1560   CapabilityElt &elt(int idx ///< Index of target element.
1561   );
1562   CapabilityElt const &elt(int idx ///< Index of target element.
1563   ) const;
1564   /// Get the element count.
1565   /// @note No corresponding @c setf_ because that cannot be changed once set.
1566   /// @see fill
1567   uint32_t getEltCount() const;
1568   //@}
1569 
1570   /** Write serialization data.
1571 
1572       The capability elements must be filled @b after invoking this method.
1573       And, of course, do not fill more than @a n of them.
1574   */
1575   self &fill(MsgBuffer &buffer, ///< Target storage.
1576              int n              ///< Number of capabilities.
1577   );
1578 
1579   /// Validate an existing structure.
1580   /// @return Parse result.
1581   int parse(MsgBuffer &buffer);
1582 
1583   /// Compute the total size of the component.
1584   static size_t calcSize(int n ///< Number of capabilities.
1585   );
1586 
1587   /// Find value for Cache Assignment.
1588   ServiceGroup::CacheAssignmentStyle getCacheAssignmentStyle() const;
1589   /// Find value for packet forwarding.
1590   ServiceGroup::PacketStyle getPacketForwardStyle() const;
1591   /// Find value for packet return.
1592   ServiceGroup::PacketStyle getPacketReturnStyle() const;
1593   /// Invalidate cached values.
1594   /// Needed after modifying elements via the @c elt method.
1595   self &invalidate();
1596 
1597 protected:
1598   /// Fill the cached values.
1599   void cache() const;
1600 
1601   int m_count = 0; ///< # of elements.
1602                    /** Whether the style values are valid.
1603                        We load all the values on the first request because we have to walk
1604                        all the capabilities anyway, and cache them.
1605                    */
1606   mutable bool m_cached = false;
1607   /// Style used to forward packets to cache.
1608   mutable ServiceGroup::PacketStyle m_packet_forward = ServiceGroup::PacketStyle::NO_PACKET_STYLE;
1609   /// Style used to return packets to the router.
1610   mutable ServiceGroup::PacketStyle m_packet_return = ServiceGroup::PacketStyle::NO_PACKET_STYLE;
1611   /// Style used to make cache assignments.
1612   mutable ServiceGroup::CacheAssignmentStyle m_cache_assign = ServiceGroup::CacheAssignmentStyle::NO_CACHE_ASSIGN_STYLE;
1613 };
1614 
1615 /** Sect 5.6.10: Alternate Assignment Component
1616     This is an abstract base class. It is specialized for each alternate.
1617  */
1618 class AltAssignComp : public CompWithHeader<AltAssignComp>
1619 {
1620 public:
1621   typedef AltAssignComp self;         ///< Self reference type.
1622   typedef CompWithHeader<self> super; ///< Parent type.
1623 
1624   /// Component type ID for this component.
1625   static CompType const COMP_TYPE = ALT_ASSIGNMENT;
1626   /// Alternate is hash.
1627   static uint16_t const ALT_HASH_ASSIGNMENT = 0;
1628   /// Alternate is mask.
1629   static uint16_t const ALT_MASK_ASSIGNMENT = 1;
1630 
1631   /// Component secondary header.
1632   /// @internal Split out because we need to compute its size.
1633   struct local_header_t {
1634     uint16_t m_assign_type;   ///< Assignment body type.
1635     uint16_t m_assign_length; ///< Assignment body length.
1636   };
1637   /// Stub of the serialized data.
1638   /// There is more variable sized data that must be handled specially.
1639   struct raw_t : public super::raw_t, public local_header_t {
1640     // These are the same in all current subclasses.
1641     AssignmentKeyElt m_key;        ///< Assignment key data.
1642     RouterAssignListElt m_routers; ///< Routers.
1643   };
1644 
1645   /// Force virtual destructor.
~AltAssignComp()1646   virtual ~AltAssignComp() {}
1647   /// @name Accessors
1648   //@{
1649   /// Get the assignment type.
1650   uint16_t getAssignType() const;
1651   /// Set the assignment type.
1652   self &setAssignType(uint16_t t ///< Assignment type.
1653   );
1654   /// Get the assignment length.
1655   uint16_t getAssignLength() const;
1656   /// Set the assignment length.
1657   self &setAssignLength(uint16_t length ///< Length in bytes.
1658   );
1659   /// Get router count field.
1660   /// @note No @c setf method because this cannot be changed independently.
1661   /// @see fill
1662   uint32_t getRouterCount() const;
1663   /// Directly access assignment key.
1664   AssignmentKeyElt &keyElt();
1665   /// Directly access assignment key.
1666   AssignmentKeyElt const &keyElt() const;
1667   //@}
1668 
1669   /// Fill out the component from an @c Assignment.
1670   virtual self &fill(MsgBuffer &buffer,               ///< Target storage.
1671                      detail::Assignment const &assign ///< Assignment data.
1672                      ) = 0;
1673 
1674   /// Validate an existing structure.
1675   /// @return Parse result.
1676   virtual int parse(MsgBuffer &buffer) = 0;
1677 
1678 protected:
1679   /// Calculate the first byte past the end of the variable data.
1680   void *calcVarPtr();
1681 };
1682 
1683 /** Sect 5.6.10: Alternate Assignment Component
1684     This is the hash based version.
1685  */
1686 class AltHashAssignComp : public AltAssignComp
1687 {
1688 public:
1689   typedef AltHashAssignComp self; ///< Self reference type.
1690   typedef AltAssignComp super;    ///< Parent type.
1691 
1692   /// @name Accessors
1693   //@{
1694   /// Get cache count field.
1695   /// @note No @c setf method because this cannot be changed independently.
1696   /// @see fill
1697   uint32_t getCacheCount() const;
1698   //@}
1699 
1700   /// Force virtual destructor.
~AltHashAssignComp()1701   virtual ~AltHashAssignComp() {}
1702   /// Fill out the component from an @c Assignment.
1703   virtual self &fill(MsgBuffer &buffer,               ///< Target storage.
1704                      detail::Assignment const &assign ///< Assignment data.
1705   );
1706 
1707   /// Validate an existing structure.
1708   /// @return Parse result.
1709   virtual int parse(MsgBuffer &buffer);
1710 
1711   /// Compute the total size of the component.
1712   static size_t calcSize(int n_routers, ///< Number of routers in view.
1713                          int n_caches   ///< Number of caches in view.
1714   );
1715 
1716 protected:
1717   /// Serialized count of cache addresses.
1718   /// The actual addresses start immediate after this.
1719   uint32_t *m_cache_count;
1720   /// Calculate the address of the cache count.
1721   uint32_t *calcCacheCountPtr();
1722 };
1723 
1724 /** Sect 5.6.10: Alternate Assignment Component
1725     This is the mask based version.
1726  */
1727 class AltMaskAssignComp : public AltAssignComp
1728 {
1729 public:
1730   typedef AltMaskAssignComp self; ///< Self reference type.
1731   typedef AltAssignComp super;    ///< Parent type.
1732 
1733   /// Force virtual destructor.
~AltMaskAssignComp()1734   virtual ~AltMaskAssignComp() {}
1735   /// Fill out the component from an @c Assignment.
1736   virtual self &fill(MsgBuffer &buffer,               ///< Target storage.
1737                      detail::Assignment const &assign ///< Assignment data.
1738   );
1739 
1740   /// Validate an existing structure.
1741   /// @return Parse result.
1742   virtual int parse(MsgBuffer &buffer);
1743 
1744 protected:
1745   MaskAssignElt *m_mask_elt; ///< Address of the mask assign element.
1746 };
1747 
1748 /** Sect 5.6.12: Command Info Component
1749  */
1750 class CmdComp : public CompWithHeader<CmdComp>
1751 {
1752 public:
1753   typedef CmdComp self;               ///< Self reference type.
1754   typedef CompWithHeader<self> super; ///< Parent type.
1755 
1756   /// Component type ID for this component.
1757   static CompType const COMP_TYPE = COMMAND_EXTENSION;
1758 
1759   /// Command types.
1760   enum cmd_t {
1761     SHUTDOWN          = 1, ///< Cache is shutting down.
1762     SHUTDOWN_RESPONSE = 2  ///< SHUTDOWN ack.
1763   };
1764 
1765   /// Serialized data layout.
1766   /// @internal Technically the command data is variable, but all currently
1767   /// defined commands have the same 32 bit data element.
1768   struct raw_t : public super::raw_t {
1769     uint16_t m_cmd;        ///< Command type / code.
1770     uint16_t m_cmd_length; ///< Length of command data.
1771     uint32_t m_cmd_data;   ///< Command data.
1772   };
1773 
1774   /// @name Accessors.
1775   //@{
1776   /// Directly access mask value element.
1777   cmd_t getCmd() const;            ///< Get command type.
1778   self &setCmd(cmd_t cmd);         ///< Set command type.
1779   uint32_t getCmdData() const;     ///< Get command data.
1780   self &setCmdData(uint32_t data); ///< Set command @a data.
1781   //@}
1782 
1783   /// Write basic serialization data.
1784   /// Elements must be filled in separately and after invoking this method.
1785   self &fill(MsgBuffer &buffer, ///< Component storage.
1786              cmd_t cmd,         ///< Command type.
1787              uint32_t data      ///< Command data.
1788   );
1789 
1790   /// Validate an existing structure.
1791   /// @return Parse result.
1792   int parse(MsgBuffer &buffer);
1793 
1794   /// Compute the total size of the component.
1795   static size_t calcSize();
1796 };
1797 
1798 /// Sect 5.6.11: Assignment Map Component
1799 class AssignMapComp : public CompWithHeader<AssignMapComp>
1800 {
1801 public:
1802   typedef AssignMapComp self;         ///< Self reference type.
1803   typedef CompWithHeader<self> super; ///< Parent type.
1804 
1805   /// Component type ID for this component.
1806   static CompType const COMP_TYPE = ASSIGN_MAP;
1807 
1808   /// Serialized layout structure.
1809   /// Not complete, only a stub.
1810   struct raw_t : public super::raw_t {
1811     MaskAssignElt m_assign;
1812   };
1813 
1814   /// Default constructor.
1815   AssignMapComp();
1816 
1817   /// @name Accessors.
1818   //@{
1819   /// Get the element count.
1820   uint32_t getCount() const;
1821   //@}
1822 
1823   /// Fill from assignment data.
1824   self &fill(MsgBuffer &buffer,               ///< Component storage.
1825              detail::Assignment const &assign ///< Assignment data.
1826   );
1827 
1828   /// Validate an existing structure.
1829   /// @return Parse result.
1830   int parse(MsgBuffer &buffer);
1831 };
1832 
1833 /// Sect 5.6.8: Router Query Info Component.
1834 class QueryComp : public CompWithHeader<QueryComp>
1835 {
1836 public:
1837   typedef QueryComp self;             ///< Self reference type.
1838   typedef CompWithHeader<self> super; ///< Parent type.
1839 
1840   /// Component type ID for this component.
1841   static CompType const COMP_TYPE = QUERY_INFO;
1842 
1843   /// Internal layout.
1844   struct raw_t : public super::raw_t {
1845     uint32_t m_router_addr; ///< Identifying router address.
1846     uint32_t m_recv_id;     ///< Receive ID router expects in reply.
1847     uint32_t m_to_addr;     ///< Destination address of query.
1848     uint32_t m_cache_addr;  ///< Identifying address of cache.
1849   };
1850 
1851   /// @name Accessors.
1852   //@{
1853   /// Directly access mask value element.
1854   uint32_t getRouterAddr() const;     ///< Get identifying router address.
1855   self &setRouterAddr(uint32_t addr); ///< Set identifying router address.
1856   uint32_t getToAddr() const;         ///< Get target address.
1857   self &setToAddr(uint32_t addr);     ///< Set target address.
1858   uint32_t getCacheAddr() const;      ///< Get identifying cache address.
1859   self &setCacheAddr(uint32_t addr);  ///< Set identifying cache address.
1860   uint32_t getRecvId() const;         ///< Get receive ID.
1861   self &setRecvId(uint32_t data);     ///< Set receive ID.
1862   //@}
1863 
1864   /// Write serialization data.
1865   /// This fills in all fields.
1866   self &fill(MsgBuffer &buffer,   ///< Component storage.
1867              uint32_t routerAddr, ///< Router identifying address.
1868              uint32_t toAddr,     ///< Destination address.
1869              uint32_t cacheAddr,  ///< Cache identifying address.
1870              uint32_t recvId      ///< Receive ID.
1871   );
1872 
1873   /// Validate an existing structure.
1874   /// @return Parse result.
1875   int parse(MsgBuffer &buffer);
1876 
1877   /// Compute the total size of the component.
1878   static size_t calcSize();
1879 };
1880 
1881 /// Cache assignment hash function.
1882 inline uint8_t
assignment_hash(uint32_t key)1883 assignment_hash(uint32_t key ///< Key to hash.
1884 )
1885 {
1886   key ^= key >> 16;
1887   key ^= key >> 8;
1888   return key & 0xFF;
1889 }
1890 
1891 /// IP header information for a receive message.
1892 struct IpHeader {
1893   uint32_t m_src; ///< Source address.
1894   uint32_t m_dst; ///< Destination address.
1895 };
1896 
1897 // Various static values.
1898 const char *const BUFFER_TOO_SMALL_FOR_COMP_TEXT = "Unable to write component -- buffer too small";
1899 
1900 // ------------------------------------------------------
1901 namespace detail
1902 {
1903   /** Local storage for cache assignment data.
1904       The maintenance of this data is sufficiently complex that it is better
1905       to have a standard class to hold it, rather than updating a serialized
1906       form.
1907   */
1908   class Assignment
1909   {
1910   public:
1911     typedef Assignment self;      ///< Self reference type.
1912     typedef AssignmentKeyElt Key; ///< Import assignment key type.
1913     /// Import assignment bucket definition.
1914     /// @internal Just one byte, no serialization issues.
1915     typedef AssignInfoComp::Bucket Bucket;
1916 
1917     /// Default constructor. Initialization to empty state.
1918     Assignment();
1919 
1920     /** Check for active assignment.
1921 
1922         An assignment is active if it is is current. This means either it
1923         was successfully generated on the cache side, or a valid assignment
1924         was received on the router side and has not expired.
1925 
1926         @return The current active state.
1927     */
1928     bool isActive() const;
1929     /// Control active flag.
1930     self &setActive(bool state ///< New active state.
1931     );
1932 
1933     /** Fill the assignment from cache service group data.
1934         Caches that are obsolete are purged from the data.
1935         @return @c true if a valid assignment was generated,
1936         @c false otherwise.
1937     */
1938     bool fill(cache::GroupData &group, ///< Service group data.
1939               uint32_t addr            ///< Identifying IP address of designated cache.
1940     );
1941     /// Update the receive ID for a router.
1942     self &updateRouterId(uint32_t addr,  ///< Identifying IP address of router.
1943                          uint32_t rcvid, ///< New receive ID.
1944                          uint32_t cno    ///< New change number.
1945     );
1946 
1947     /// Get the assignment key.
1948     AssignmentKeyElt const &getKey() const;
1949     /// Get the router assignment list.
1950     RouterAssignListElt const &getRouterList() const;
1951     /// Get the hash assignment.
1952     HashAssignElt const &getHash() const;
1953     /// Get the mask assignment.
1954     MaskAssignElt const &getMask() const;
1955 
1956   protected:
1957     Key m_key;     ///< Assignment key.
1958     bool m_active; ///< Active state.
1959 
1960     // These store the serialized assignment chunks which are assembled
1961     // in to the components as needed. Each points in to the serialization
1962     // buffer, or is @c NULL if that assignment data isn't valid.
1963     /// Router assignments.
1964     RouterAssignListElt *m_router_list;
1965     /// Hash assignment.
1966     HashAssignElt *m_hash_assign;
1967     /// Mask assignment.
1968     MaskAssignElt *m_mask_assign;
1969 
1970     /// Buffer for serialization.
1971     MsgBuffer m_buffer;
1972   };
1973 
1974   namespace endpoint
1975   {
1976     /// Common service group data.
1977     struct GroupData {
1978       typedef GroupData self; ///< Self reference type.
1979 
1980       ServiceGroup m_svc;           ///< The service definition.
1981       uint32_t m_generation    = 0; ///< Generation value (change number).
1982       time_t m_generation_time = 0; ///< Time of last view change.
1983 
1984       bool m_use_security_opt             = false;         ///< Use group local security.
1985       SecurityComp::Option m_security_opt = SECURITY_NONE; ///< Type of security.
1986       bool m_use_security_key             = false;         ///< Use group local key.
1987       SecurityComp::Key m_security_key;                    ///< MD5 key.
1988 
1989       /** Group assignment data.
1990           This is used as a place to generate an assignment or
1991           store one received from an extern source.
1992       */
1993       detail::Assignment m_assign_info;
1994 
1995       /// Default constructor.
1996       GroupData() = default;
1997       /// Use @a key instead of global default.
1998       self &setKey(const char *key ///< Shared key.
1999       );
2000       /// Use security @a style instead of global default.
2001       self &setSecurity(SecurityOption style ///< Security style to use.
2002       );
2003     };
2004   } // namespace endpoint
2005 } // namespace detail
2006 // ------------------------------------------------------
2007 /** Base class for all messages.
2008  */
2009 class BaseMsg
2010 {
2011 public:
2012   /// Default constructor.
2013   BaseMsg();
2014   /// Destructor.
~BaseMsg()2015   virtual ~BaseMsg() {}
2016   /// Set the message @a buffer.
2017   void setBuffer(MsgBuffer const &buffer ///< Storage for message.
2018   );
2019   /// Get the current buffer.
2020   MsgBuffer const &buffer() const;
2021   /// Invoke once all components have been filled.
2022   /// Sets the length and updates security data if needed.
2023   virtual void finalize();
2024   /// Get available buffer space.
2025   size_t getSpace() const;
2026   /// Get the message size.
2027   size_t getCount() const;
2028 
2029   /// Validate security option.
2030   /// @note This presumes a subclass has already successfully parsed.
2031   bool validateSecurity() const;
2032 
2033   // Common starting components for all messages.
2034   MsgHeaderComp m_header;  ///< Message header.
2035   SecurityComp m_security; ///< Security component.
2036   ServiceComp m_service;   ///< Service provided.
2037 
2038 protected:
2039   MsgBuffer m_buffer; ///< Raw storage for message data.
2040 };
2041 
2042 /// Sect 5.1: Layout and control for @c WCCP2_HERE_I_AM
2043 class HereIAmMsg : public BaseMsg
2044 {
2045 public:
2046   typedef HereIAmMsg self; ///< Self reference type.
2047 
2048   /** Fill in the basic message structure.
2049       This expects @c setBuffer to have already been called
2050       with an appropriate buffer.
2051       The actual router and cache data must be filled in
2052       after this call, which will allocate the appropriate spaces
2053       in the message layou.
2054   */
2055   void fill(detail::cache::GroupData const &group, ///< Service group for message.
2056             CacheIdBox const &cache_id,            ///< ID to use for this cache.
2057             SecurityOption sec_opt                 ///< Security option to use.
2058   );
2059   /** Fill in optional capabilities.
2060       The capabilities component is added only if the @a router
2061       is set to send them.
2062   */
2063   void fill_caps(detail::cache::RouterData const &router ///< Target router.
2064   );
2065   /// Parse message data, presumed to be of this type.
2066   int parse(ts::Buffer const &buffer ///< Raw message data.
2067   );
2068 
2069   CacheIdComp m_cache_id;     ///< Web cache identity info.
2070   CacheViewComp m_cache_view; ///< Web cache view.
2071   CapComp m_capabilities;     ///< Capabilities data.
2072   CmdComp m_command;          ///< Command extension.
2073 };
2074 
2075 /// Sect 5.2: 'I See You' Message
2076 class ISeeYouMsg : public BaseMsg
2077 {
2078 public:
2079   typedef ISeeYouMsg self; ///< Self reference type.
2080 
2081   /// Fill out message structure.
2082   /// Router ID and view data must be filled in separately.
2083   void fill(detail::router::GroupData const &group, ///< Service groupc context.
2084             SecurityOption sec_opt,                 ///< Security option.
2085             detail::Assignment &assign,             ///< Cache assignment data.
2086             size_t to_caches,                       ///< # of target caches for message.
2087             size_t n_routers,                       ///< Routers in view.
2088             size_t n_caches,                        ///< Caches in view.
2089             bool send_capabilities = false          ///< Send capabilities.
2090   );
2091 
2092   /// Parse message data, presumed to be of this type.
2093   int parse(ts::Buffer const &buffer ///< Raw message data.
2094   );
2095 
2096   RouterIdComp m_router_id;     ///< Router ID.
2097   RouterViewComp m_router_view; ///< Router view data.
2098   // The rest of these are optional. The spec says we should get
2099   // an assignment or map, but in practice that doesn't happen with
2100   // actual Cisco routers in the hash case. Perhaps it happens with
2101   // a map.
2102   AssignInfoComp m_assignment; ///< Assignment data.
2103   AssignMapComp m_map;         ///< Assignment map.
2104   CapComp m_capabilities;      ///< Capabilities data.
2105   CmdComp m_command;           ///< Command extension.
2106 };
2107 
2108 /// Sect 5.1: Layout and control for @c WCCP2_REDIRECT_ASSIGN
2109 class RedirectAssignMsg : public BaseMsg
2110 {
2111 public:
2112   typedef RedirectAssignMsg self; ///< Self reference type.
2113 
2114   /** Fill in the basic message structure.
2115       This expects @c setBuffer to have already been called
2116       with an appropriate buffer.
2117       The actual router and cache data must be filled in
2118       after this call, which will allocate the appropriate spaces
2119       in the message layou.
2120   */
2121   void fill(detail::cache::GroupData const &group, ///< Service group for message.
2122             SecurityOption sec_opt                 ///< Security option to use.
2123   );
2124 
2125   /// Parse message data, presumed to be of this type.
2126   int parse(ts::Buffer const &buffer ///< Raw message data.
2127   );
2128 
2129   // Only one of these should be present in an instance.
2130   AssignInfoComp m_hash_assign;        ///< Primary (hash) assignment.
2131   AltHashAssignComp m_alt_hash_assign; ///< Alternate (hash) assignment.
2132   AltMaskAssignComp m_alt_mask_assign; ///< Alternate (mask) assignment.
2133 };
2134 
2135 /// Sect 5.4: @c WCCP_REMOVAL_QUERY
2136 class RemovalQueryMsg : public BaseMsg
2137 {
2138 public:
2139   typedef RemovalQueryMsg self; ///< Self reference type.
2140 
2141   /** Fill in the basic message structure.
2142       This expects @c setBuffer to have already been called
2143       with an appropriate buffer.
2144       The actual router and cache data must be filled in
2145       after this call, which will allocate the appropriate spaces
2146       in the message layou.
2147   */
2148   void fill(detail::cache::GroupData const &group, ///< Service group for message.
2149             SecurityOption sec_opt,                ///< Security option to use.
2150             AssignmentKeyElt const &key,           ///< Assignment key.
2151             int n_routers,                         ///< Number of routers expected.
2152             int n_caches                           ///< Number of caches expected.
2153   );
2154 
2155   /// Parse message data, presumed to be of this type.
2156   int parse(ts::Buffer const &buffer ///< Raw message data.
2157   );
2158 
2159   QueryComp m_query; ///< Router Removal Query component.
2160 };
2161 
2162 // ------------------------------------------------------
2163 /// Last packet information.
2164 struct PacketStamp {
2165   typedef PacketStamp self; ///< Self reference type.
2166 
2167   PacketStamp(); ///< Default constructor (zero elements).
2168   /// Set the @a time and @a generation.
2169   self &set(time_t time, uint32_t generation);
2170 
2171   time_t m_time; ///< Time when packet was sent/received.
2172   uint32_t m_sn; ///< Sequence # of packet.
2173 };
2174 
2175 /** Implementation class for EndPoint.
2176     All of the WCCP structures are defined in this class.
2177 
2178     A note on the component classes - these are designed to reside in
2179     a side buffer which then points in to the actual message
2180     buffer. This is done because the WCCP designers were not too
2181     bright. Rather than packing the fixed sized elements in front and
2182     using offsets to point at variables sized data, it's intermixed,
2183     so it's not possible to declare C++ structures that map on to the
2184     actual message data in all cases. And because mixed styles are
2185     worse than a consistent mediocre style, we go with the latter and
2186     put all the message structures on the side. This also means having
2187     to use accessor methods.
2188  */
2189 class Impl : public ts::IntrusivePtrCounter
2190 {
2191   friend class EndPoint;
2192 
2193 public:
2194   typedef Impl self; ///< Self reference type.
2195 
2196   /// Import detail struct.
2197   typedef detail::endpoint::GroupData GroupData;
2198 
2199   /// Default constructor.
2200   Impl() = default;
2201   /** Set the local address used for this endpoint.
2202       If not set, an arbitrary local address will be
2203       @note This can only be called once, and must be called before
2204       @c open.
2205   */
2206   /// Force virtual destructor.
2207   virtual ~Impl();
2208 
2209   /// Open a socket for communications.
2210   /// @return 0 on success, -ERRNO on failure.
2211   virtual int open(uint32_t addr ///< Local IP address.
2212   );
2213 
2214   /// Use MD5 security.
2215   void useMD5Security(std::string_view const key ///< Shared key.
2216   );
2217 
2218   /// Perform all scheduled housekeeping functions.
2219   /// @return 0 for success, -errno on error.
2220   virtual int housekeeping() = 0;
2221 
2222   /// Receive and process a message.
2223   /// @return 0 for success, -ERRNO on system error.
2224   virtual ts::Rv<int> handleMessage();
2225 
2226   /// Check if endpoint is configured.
2227   /// @return @c true if ready to operate, @c false otherwise.
2228   virtual bool isConfigured() const = 0;
2229 
2230   /* These handlers simply generate an error message and return.  The
2231      base @c handleMessage will read the data from the socket and
2232      validate the message header. It then calls the appropriate one of
2233      these specialized message handlers.  Subclasses should override
2234      to process relevant messages.
2235   */
2236   /// Process HERE_I_AM message.
2237   virtual ts::Errata handleHereIAm(IpHeader const &header, ///< IP packet data.
2238                                    ts::Buffer const &data  ///< Buffer with message data.
2239   );
2240   /// Process I_SEE_YOU message.
2241   virtual ts::Errata handleISeeYou(IpHeader const &header, ///< IP packet data.
2242                                    ts::Buffer const &data  ///< Buffer with message data.
2243   );
2244   /// Process REDIRECT_ASSIGN message.
2245   virtual ts::Errata handleRedirectAssign(IpHeader const &header, ///< IP packet data.
2246                                           ts::Buffer const &data  ///< Buffer with message data.
2247   );
2248   /// Process REMOVAL_QUERY message.
2249   virtual ts::Errata handleRemovalQuery(IpHeader const &header, ///< IP packet data.
2250                                         ts::Buffer const &data  ///< Buffer with message data.
2251   );
2252 
2253 protected:
2254   /** Local address for this end point.
2255       This is set only when the socket is open.
2256    */
2257   uint32_t m_addr = INADDR_ANY;
2258   int m_fd        = ts::NO_FD; ///< Our socket.
2259 
2260   bool m_use_security_opt             = false;         ///< Use group local security.
2261   SecurityComp::Option m_security_opt = SECURITY_NONE; ///< Type of security.
2262   bool m_use_security_key             = false;         ///< Use group local key.
2263   SecurityComp::Key m_security_key;                    ///< MD5 key.
2264 
2265   /// Close the socket.
2266   void close();
2267   /// Set security options in a message.
2268   /// @return Security option to use during message fill.
2269   SecurityOption setSecurity(BaseMsg &msg,          ///< Message.
2270                              GroupData const &group ///< Group data used to control fill.
2271   ) const;
2272   /// Validate a security component.
2273   bool validateSecurity(BaseMsg &msg,          ///< Message data (including security component).
2274                         GroupData const &group ///< Group data for message.
2275   );
2276 };
2277 // ------------------------------------------------------
2278 namespace detail
2279 {
2280   namespace cache
2281   {
2282     /// Caches's view of caches.
2283     struct CacheData {
2284       /// Get the identifying IP address for this cache.
2285       uint32_t idAddr() const;
2286       /// Cache identity data.
2287       CacheIdBox m_id;
2288       /// Last time this cache was mentioned by the routers.
2289       /// Indexed in parallel to the routers.
2290       std::vector<PacketStamp> m_src;
2291     };
2292 
2293     /// Cache's view of routers.
2294     struct RouterData {
2295       /// Default constructor, no member initialization.
2296       RouterData();
2297       /// Construct with address.
2298       RouterData(uint32_t addr ///< Router identifying address.
2299       );
2300 
2301       /// Time until next packet.
2302       /// @return Seconds until a packet should be sent.
2303       time_t waitTime(time_t now ///< Current time.
2304       ) const;
2305       /// Time till next ping.
2306       /// @return Seconds until a HERE_I_AM should be sent.
2307       time_t pingTime(time_t now ///< Current time.
2308       ) const;
2309 
2310       uint32_t m_addr;       ///< Router identifying IP address.
2311       uint32_t m_generation; ///< Router's view change number.
2312                              /** Most recent packet received from router.
2313                               *  The sequence number @a m_sn is the receive ID of the router.
2314                               */
2315       PacketStamp m_recv;
2316       /** Most recent packet sent to router.
2317        *  The sequence number @a m_sn is the view generation of this cache.
2318        */
2319       PacketStamp m_xmit;
2320       /// Cache ID of this cache as reflected by this router.
2321       CacheIdBox m_local_cache_id;
2322       int m_rapid;      ///< Rapid replies to send.
2323       bool m_assign;    ///< Send a REDIRECT_ASSIGN.
2324       bool m_send_caps; ///< Send capabilities.
2325       /// Packet forwarding method selected.
2326       ServiceGroup::PacketStyle m_packet_forward = ServiceConstants::NO_PACKET_STYLE;
2327       /// Packet return method selected.
2328       ServiceGroup::PacketStyle m_packet_return = ServiceConstants::NO_PACKET_STYLE;
2329       /// Cache assignment method selected.
2330       ServiceGroup::CacheAssignmentStyle m_cache_assign = ServiceConstants::NO_CACHE_ASSIGN_STYLE;
2331     };
2332 
2333     /// Data for a seeded router.
2334     struct SeedRouter {
2335       SeedRouter(); ///< Default constructor, no member initialization.
2336       /// Construct with address @a addr.
2337       /// Other members are zero initialized.
2338       SeedRouter(uint32_t addr);
2339       uint32_t m_addr;  ///< Address of router.
2340       uint32_t m_count; ///< # of packets sent w/o response.
2341       time_t m_xmit;    ///< Time of last packet sent.
2342     };
2343 
2344     /// Storage type for known caches.
2345     typedef std::vector<CacheData> CacheBag;
2346     /// Storage type for known routers.
2347     typedef std::vector<RouterData> RouterBag;
2348 
2349     /** Cache's view of a service group.
2350         This stores the internal accounting information, it is not the
2351         serialized form.
2352     */
2353     struct GroupData : public endpoint::GroupData {
2354       typedef GroupData self;            ///< Self reference type.
2355       typedef endpoint::GroupData super; ///< Parent type.
2356 
2357       /// Cache identity of this cache.
2358       CacheIdBox m_id;
2359 
2360       /// Packet forwarding methods supported.
2361       ServiceGroup::PacketStyle m_packet_forward = ServiceConstants::NO_PACKET_STYLE;
2362       /// Packet return methods supported.
2363       ServiceGroup::PacketStyle m_packet_return = ServiceConstants::NO_PACKET_STYLE;
2364       /// Cache assignment methods supported.
2365       ServiceGroup::CacheAssignmentStyle m_cache_assign = ServiceConstants::NO_CACHE_ASSIGN_STYLE;
2366 
2367       /// Known caches.
2368       CacheBag m_caches;
2369       /// Known routers.
2370       RouterBag m_routers;
2371       char *m_proc_name;
2372 
2373       /// Set if there an assignment should be computed and sent.
2374       /// This is before checking for being a designated cache
2375       /// (that check is part of the assignment generation).
2376       bool m_assignment_pending;
2377 
2378       /// Seed routers.
2379       std::vector<SeedRouter> m_seed_routers;
2380 
2381       GroupData(); ///< Default constructor.
2382 
2383       void setProcName(const std::string_view name);
2384       const char *getProcName();
2385 
2386       /// Find a router by IP @a addr.
2387       /// @return A pointer to the router, or @c NULL if not found.
2388       RouterBag::iterator findRouter(uint32_t addr ///< IP address of cache.
2389       );
2390 
2391       /// Set an initial router for a service group.
2392       self &seedRouter(uint32_t addr ///< IP address for router.
2393       );
2394       /// Remove a seed router.
2395       /// @return The last time a packet was sent to the router.
2396       time_t removeSeedRouter(uint32_t addr ///< Identifying router address.
2397       );
2398 
2399       /// Find a cache by IP @a addr.
2400       /// @return An iterator to the cache, or @c NULL if not found.
2401       CacheBag::iterator findCache(uint32_t addr ///< IP address of cache.
2402       );
2403       /// Adjust packet stamp vectors to track routers.
2404       void resizeCacheSources();
2405 
2406       /// Time until next event.
2407       /// @return The number of seconds until the next event of interest.
2408       time_t waitTime(time_t now ///< Current time.
2409       ) const;
2410 
2411       /** Cull routers.
2412           Routers that have not replied recently are moved from the
2413           active router list to the seed router list.
2414 
2415           @return @c true if any routers were culled, @c false otherwise.
2416       */
2417       bool cullRouters(time_t now ///< Current time.
2418       );
2419 
2420       /** Check to see if the process associated with service is up
2421        */
2422       bool processUp();
2423 
2424       /// Update state to reflect a view change.
2425       self &viewChanged(time_t now);
2426 
2427       /// Use @a key instead of global default.
2428       self &setKey(const char *key ///< Shared key.
2429       );
2430       /// Use security @a style instead of global default.
2431       self &setSecurity(SecurityOption style ///< Security style to use.
2432       );
2433     };
2434     inline const char *
getProcName()2435     GroupData::getProcName()
2436     {
2437       return m_proc_name;
2438     }
2439     inline void
setProcName(const std::string_view name)2440     GroupData::setProcName(const std::string_view name)
2441     {
2442       m_proc_name = ats_strndup(name.data(), name.size());
2443     }
2444   } // namespace cache
2445 } // namespace detail
2446 
2447 /** Implementation class for Cache Endpoint.
2448  */
2449 class CacheImpl : public Impl
2450 {
2451 public:
2452   typedef CacheImpl self; ///< Self reference type.
2453   typedef Impl super;     ///< Parent type.
2454 
2455   // Import details
2456   typedef detail::cache::SeedRouter SeedRouter;
2457   typedef detail::cache::CacheData CacheData;
2458   typedef detail::cache::RouterData RouterData;
2459   typedef detail::cache::GroupData GroupData;
2460   typedef detail::cache::CacheBag CacheBag;
2461   typedef detail::cache::RouterBag RouterBag;
2462 
2463   /** Define a service group.
2464       If no service is defined for the ID in @a svc, it is created.
2465       If @a result is not @c NULL then it is set to
2466       - @c ServiceGroup::DEFINED if the service was created.
2467       - @c ServiceGroup::EXISTS if the service matches the existing service.
2468       - @c ServiceGroup::CONFLICT if the service doesn't match the existing service.
2469 
2470       @return The data for the service group.
2471   */
2472   virtual GroupData &defineServiceGroup(ServiceGroup const &svc,         ///< [in] Service to define.
2473                                         ServiceGroup::Result *result = 0 ///< [out] Result for service creation.
2474   );
2475 
2476   /** Set an initial router for a service group.
2477       This is needed to bootstrap the protocol.
2478       If the router is already seeded, this call is silently ignored.
2479   */
2480   self &seedRouter(uint8_t id,   ///< Service group ID.
2481                    uint32_t addr ///< IP address for router.
2482   );
2483 
2484   /// Define services from a configuration file.
2485   ts::Errata loadServicesFromFile(const char *path ///< Path to file.
2486   );
2487 
2488   /// Override.
2489   int open(uint32_t addr);
2490 
2491   /// Time until next scheduled event.
2492   time_t waitTime() const;
2493 
2494   /// Check for configuration.
2495   bool isConfigured() const;
2496 
2497   /// Perform all scheduled housekeeping functions.
2498   /// @return 0 for success, -errno on error.
2499   virtual int housekeeping();
2500 
2501   /** Check cache assignment reported by a router against internal assign.
2502       @return @c true if they are the same, @c false otherwise.
2503   */
2504   virtual ts::Errata checkRouterAssignment(GroupData const &group,    ///< Group with assignment.
2505                                            RouterViewComp const &comp ///< Assignment reported by router.
2506   ) const;
2507 
2508 protected:
2509   /// Generate contents in HERE_I_AM @a msg for seed router.
2510   void generateHereIAm(HereIAmMsg &msg, ///< Message with allocated buffer.
2511                        GroupData &group ///< Group with data for message.
2512   );
2513   /// Generate contents in HERE_I_AM @a msg for active @a router.
2514   void generateHereIAm(HereIAmMsg &msg,   ///< Message with allocated buffer.
2515                        GroupData &group,  ///< Group with data for message.
2516                        RouterData &router ///< Target router.
2517   );
2518   /// Generate contents in REDIRECT_ASSIGN @a msg for a service @a group.
2519   void generateRedirectAssign(RedirectAssignMsg &msg, ///< Message with allocated buffer.
2520                               GroupData &group        ///< Group with data for message.
2521   );
2522   /// Process HERE_I_AM message.
2523   virtual ts::Errata handleISeeYou(IpHeader const &header, ///< IP packet data.
2524                                    ts::Buffer const &data  ///< Buffer with message data.
2525   );
2526   /// Process REMOVAL_QUERY message.
2527   virtual ts::Errata handleRemovalQuery(IpHeader const &header, ///< IP packet data.
2528                                         ts::Buffer const &data  ///< Message data.
2529   );
2530 
2531   /// Map Service Group ID to Service Group Data.
2532   typedef std::map<uint8_t, GroupData> GroupMap;
2533   /// Active service groups.
2534   GroupMap m_groups;
2535 
2536 private:
2537   ts::Errata loader(const YAML::Node &node);
2538 };
2539 
2540 // ------------------------------------------------------
2541 namespace detail
2542 {
2543   namespace router
2544   {
2545     /** Router's view of a cache.
2546         @a m_count tracks the number of packets received from this particular
2547         cache. The RFC is unclear but it looks like this should be tracked
2548         independently for each target address (which can be different than
2549         caches if multicasting). A response is pending if @a m_count is
2550         different than @ m_xmit.m_gen which is the received count last time
2551         this router sent this cache a response.
2552     */
2553     struct CacheData {
2554       /// Get the identifying IP address for this cache.
2555       uint32_t idAddr() const;
2556 
2557       /// Received count for this cache.
2558       uint32_t m_recv_count;
2559       /// Change number of last received message.
2560       uint32_t m_generation;
2561       /// Need to send a response to this cache.
2562       bool m_pending;
2563       /// Address used by cache to send to this router.
2564       uint32_t m_to_addr;
2565       /// Stamp for last pack transmitted to this cache.
2566       PacketStamp m_xmit;
2567       //// Stamp for last packet received from this cache.
2568       PacketStamp m_recv;
2569 
2570       CacheIdBox m_id;        ///< Transmitted cache descriptor.
2571       uint32_t m_target_addr; ///< Target address of last packet.
2572     };
2573 
2574     /// Router's view of other routers.
2575     struct RouterData {
2576       typedef RouterData self; ///< Self reference type.
2577 
2578       /// Identifying IP address of router.
2579       uint32_t m_addr;
2580       /** Stamp for last mention of this router from a cache.
2581           Indexed in parallel with the Caches.
2582           The sequence number @a m_sn is the cache's change #.
2583       */
2584       std::vector<PacketStamp> m_src;
2585       /// Resize the packet stamp vector.
2586       self &resize(size_t);
2587     };
2588 
2589     /// Storage type for known caches.
2590     typedef std::vector<CacheData> CacheBag;
2591     /// Storage type for known routers.
2592     typedef std::vector<RouterData> RouterBag;
2593 
2594     /** A router's view of a service group.
2595 
2596         This stores the internal accounting information, it is not the
2597         serialized form.
2598     */
2599     struct GroupData : public detail::endpoint::GroupData {
2600       typedef GroupData self;                    ///< Self reference type.
2601       typedef detail::endpoint::GroupData super; ///< Parent type.
2602 
2603       GroupData(); ///< Default constructor.
2604 
2605       /// Known caches.
2606       CacheBag m_caches;
2607       /// Known (other) routers.
2608       RouterBag m_routers;
2609 
2610       /// Find a cache by IP @a addr.
2611       /// @return An iterator to the cache, or @c NULL if not found.
2612       CacheBag::iterator findCache(uint32_t addr ///< IP address of cache.
2613       );
2614       /// Adjust packet stamp vectors to track caches.
2615       void resizeRouterSources();
2616     };
2617   } // namespace router
2618 } // namespace detail
2619 
2620 /** Implementation class for Router Endpoint.
2621  */
2622 class RouterImpl : public Impl
2623 {
2624 public:
2625   typedef RouterImpl self; ///< Self reference type.
2626   typedef Impl super;      ///< Parent type.
2627   // Import details
2628   typedef detail::router::CacheData CacheData;
2629   typedef detail::router::RouterData RouterData;
2630   typedef detail::router::GroupData GroupData;
2631   typedef detail::router::CacheBag CacheBag;
2632   typedef detail::router::RouterBag RouterBag;
2633 
2634   /// Process HERE_I_AM message.
2635   virtual ts::Errata handleHereIAm(IpHeader const &header, ///< IP packet data.
2636                                    ts::Buffer const &data  ///< Buffer with message data.
2637   );
2638   /// Perform all scheduled housekeeping functions.
2639   int housekeeping();
2640   /// Send pending I_SEE_YOU messages.
2641   int xmitISeeYou();
2642   /// Check for configuration.
2643   bool isConfigured() const;
2644 
2645 protected:
2646   /** Find or create a service group record.
2647       If no service is defined for the ID, it is created.
2648       If @a result is not @c NULL then it is set to
2649       - @c ServiceGroup::DEFINED if the service was created.
2650       - @c ServiceGroup::EXISTS if the service matches the existing service.
2651       - @c ServiceGroup::CONFLICT if the service doesn't match the existing service.
2652 
2653       @return The data for the service group.
2654   */
2655   GroupData &defineServiceGroup(ServiceGroup const &svc, ServiceGroup::Result *result);
2656   /// Fill out message data.
2657   void generateISeeYou(ISeeYouMsg &msg,  ///< Message structure to fill.
2658                        GroupData &group, ///< Group data for message.
2659                        CacheData &cache  ///< Target cache.
2660   );
2661 
2662   /// Map Service Group ID to Service Group Data.
2663   typedef std::map<uint8_t, GroupData> GroupMap;
2664   /// Active service groups.
2665   GroupMap m_groups;
2666 };
2667 // ------------------------------------------------------
RouterId()2668 inline RouterId::RouterId() : m_addr(0), m_recv_id(0) {}
RouterId(uint32_t addr,uint32_t recv_id)2669 inline RouterId::RouterId(uint32_t addr, uint32_t recv_id) : m_addr(addr), m_recv_id(recv_id) {}
2670 
RouterIdElt(uint32_t addr,uint32_t recv_id)2671 inline RouterIdElt::RouterIdElt(uint32_t addr, uint32_t recv_id) : super(addr, htonl(recv_id)) {}
2672 inline uint32_t
getAddr()2673 RouterIdElt::getAddr() const
2674 {
2675   return m_addr;
2676 }
2677 inline RouterIdElt &
setAddr(uint32_t addr)2678 RouterIdElt::setAddr(uint32_t addr)
2679 {
2680   m_addr = addr;
2681   return *this;
2682 }
2683 inline uint32_t
getRecvId()2684 RouterIdElt::getRecvId() const
2685 {
2686   return ntohl(m_recv_id);
2687 }
2688 inline RouterIdElt &
setRecvId(uint32_t recv_id)2689 RouterIdElt::setRecvId(uint32_t recv_id)
2690 {
2691   m_recv_id = htonl(recv_id);
2692   return *this;
2693 }
2694 inline RouterIdElt &
2695 RouterIdElt::operator=(super const &that)
2696 {
2697   return this->setAddr(that.m_addr).setRecvId(that.m_recv_id);
2698 }
2699 
MaskElt()2700 inline MaskElt::MaskElt() {}
2701 
MaskElt(uint32_t srcAddr,uint32_t dstAddr,uint16_t srcPort,uint16_t dstPort)2702 inline MaskElt::MaskElt(uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
2703   : m_src_addr(srcAddr), m_dst_addr(dstAddr), m_src_port(srcPort), m_dst_port(dstPort)
2704 {
2705 }
2706 
2707 inline uint32_t
getSrcAddr()2708 MaskElt::getSrcAddr() const
2709 {
2710   return ntohl(m_src_addr);
2711 }
2712 inline MaskElt &
setSrcAddr(uint32_t mask)2713 MaskElt::setSrcAddr(uint32_t mask)
2714 {
2715   m_src_addr = htonl(mask);
2716   return *this;
2717 }
2718 inline uint32_t
getDstAddr()2719 MaskElt::getDstAddr() const
2720 {
2721   return ntohl(m_dst_addr);
2722 }
2723 inline MaskElt &
setDstAddr(uint32_t mask)2724 MaskElt::setDstAddr(uint32_t mask)
2725 {
2726   m_dst_addr = htonl(mask);
2727   return *this;
2728 }
2729 inline uint16_t
getSrcPort()2730 MaskElt::getSrcPort() const
2731 {
2732   return ntohs(m_src_port);
2733 }
2734 inline MaskElt &
setSrcPort(uint16_t mask)2735 MaskElt::setSrcPort(uint16_t mask)
2736 {
2737   m_src_port = htons(mask);
2738   return *this;
2739 }
2740 inline uint16_t
getDstPort()2741 MaskElt::getDstPort() const
2742 {
2743   return ntohs(m_dst_port);
2744 }
2745 inline MaskElt &
setDstPort(uint16_t mask)2746 MaskElt::setDstPort(uint16_t mask)
2747 {
2748   m_dst_port = htons(mask);
2749   return *this;
2750 }
2751 
ValueElt()2752 inline ValueElt::ValueElt() {}
2753 
ValueElt(uint32_t cacheAddr,uint32_t srcAddr,uint32_t dstAddr,uint16_t srcPort,uint16_t dstPort)2754 inline ValueElt::ValueElt(uint32_t cacheAddr, uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
2755   : m_src_addr(srcAddr), m_dst_addr(dstAddr), m_src_port(srcPort), m_dst_port(dstPort), m_cache_addr(cacheAddr)
2756 {
2757 }
2758 
MaskValueSetElt()2759 inline MaskValueSetElt::MaskValueSetElt() {}
MaskValueSetElt(uint32_t count)2760 inline MaskValueSetElt::MaskValueSetElt(uint32_t count) : m_count(count) {}
2761 inline MaskElt &
maskElt()2762 MaskValueSetElt::maskElt()
2763 {
2764   return m_mask;
2765 }
2766 inline uint32_t
getCount()2767 MaskValueSetElt::getCount() const
2768 {
2769   return ntohl(m_count);
2770 }
2771 
2772 inline uint32_t
getSrcAddrMask()2773 MaskValueSetElt::getSrcAddrMask() const
2774 {
2775   return m_mask.getSrcAddr();
2776 }
2777 inline MaskValueSetElt &
setSrcAddrMask(uint32_t mask)2778 MaskValueSetElt::setSrcAddrMask(uint32_t mask)
2779 {
2780   m_mask.setSrcAddr(mask);
2781   return *this;
2782 }
2783 inline uint32_t
getDstAddrMask()2784 MaskValueSetElt::getDstAddrMask() const
2785 {
2786   return m_mask.getDstAddr();
2787 }
2788 inline MaskValueSetElt &
setDstAddrMask(uint32_t mask)2789 MaskValueSetElt::setDstAddrMask(uint32_t mask)
2790 {
2791   m_mask.setDstAddr(mask);
2792   return *this;
2793 }
2794 inline uint16_t
getSrcPortMask()2795 MaskValueSetElt::getSrcPortMask() const
2796 {
2797   return m_mask.getSrcPort();
2798 }
2799 inline MaskValueSetElt &
setSrcPortMask(uint16_t mask)2800 MaskValueSetElt::setSrcPortMask(uint16_t mask)
2801 {
2802   m_mask.setSrcPort(mask);
2803   return *this;
2804 }
2805 inline uint16_t
getDstPortMask()2806 MaskValueSetElt::getDstPortMask() const
2807 {
2808   return m_mask.getDstPort();
2809 }
2810 inline MaskValueSetElt &
setDstPortMask(uint16_t mask)2811 MaskValueSetElt::setDstPortMask(uint16_t mask)
2812 {
2813   m_mask.setDstPort(mask);
2814   return *this;
2815 }
2816 inline ValueElt *
values()2817 MaskValueSetElt::values()
2818 {
2819   return reinterpret_cast<ValueElt *>(this + 1);
2820 }
2821 inline ValueElt const *
values()2822 MaskValueSetElt::values() const
2823 {
2824   return const_cast<self *>(this)->values();
2825 }
2826 inline size_t
calcSize(uint32_t n)2827 MaskValueSetElt::calcSize(uint32_t n)
2828 {
2829   return sizeof(self) + n * sizeof(ValueElt);
2830 }
2831 inline size_t
getSize()2832 MaskValueSetElt::getSize() const
2833 {
2834   return self::calcSize(ntohl(m_count));
2835 }
2836 
2837 inline size_t
getSize()2838 MaskAssignElt::getSize() const
2839 {
2840   return sizeof(self) + this->getVarSize();
2841 }
2842 
2843 inline uint32_t
getAddr()2844 CacheIdElt::getAddr() const
2845 {
2846   return m_addr;
2847 }
2848 inline CacheIdElt &
setAddr(uint32_t addr)2849 CacheIdElt::setAddr(uint32_t addr)
2850 {
2851   m_addr = addr;
2852   return *this;
2853 }
2854 inline uint16_t
getHashRev()2855 CacheIdElt::getHashRev() const
2856 {
2857   return ntohs(m_hash_rev);
2858 }
2859 inline CacheIdElt &
setHashRev(uint16_t addr)2860 CacheIdElt::setHashRev(uint16_t addr)
2861 {
2862   m_hash_rev = htons(addr);
2863   return *this;
2864 }
2865 inline CacheIdElt &
initHashRev()2866 CacheIdElt::initHashRev()
2867 {
2868   this->setHashRev(HASH_REVISION);
2869   return *this;
2870 }
2871 inline bool
getUnassigned()2872 CacheIdElt::getUnassigned() const
2873 {
2874   return 1 == m_unassigned;
2875 }
2876 inline CacheIdElt &
setUnassigned(bool state)2877 CacheIdElt::setUnassigned(bool state)
2878 {
2879   m_unassigned = state ? 1 : 0;
2880   return *this;
2881 }
2882 inline CacheIdElt &
clearReserved()2883 CacheIdElt::clearReserved()
2884 {
2885   m_reserved_0 = 0;
2886   m_reserved_1 = 0;
2887   m_reserved_2 = 0;
2888   return *this;
2889 }
2890 inline bool
isMask()2891 CacheIdElt::isMask() const
2892 {
2893   return 1 == m_is_mask;
2894 }
2895 inline CacheIdElt &
setMask(bool state)2896 CacheIdElt::setMask(bool state)
2897 {
2898   m_is_mask = state ? 1 : 0;
2899   return *this;
2900 }
2901 
2902 inline CacheIdElt::Tail *
getTailPtr()2903 CacheHashIdElt::getTailPtr()
2904 {
2905   return &m_tail;
2906 }
2907 
2908 inline uint32_t
getCount()2909 CacheMaskIdElt::getCount() const
2910 {
2911   return m_assign.getCount();
2912 }
2913 
2914 inline size_t
getSize()2915 CacheMaskIdElt::getSize() const
2916 {
2917   return sizeof(self) + sizeof(Tail) + m_assign.getVarSize();
2918 }
2919 
2920 inline CacheIdElt::Tail *
getTailPtr()2921 CacheMaskIdElt::getTailPtr()
2922 {
2923   return reinterpret_cast<Tail *>(reinterpret_cast<char *>(this) + sizeof(self) + m_assign.getVarSize());
2924 }
2925 
2926 inline uint32_t
getAddr()2927 CacheIdBox::getAddr() const
2928 {
2929   return m_base->getAddr();
2930 }
2931 
2932 inline CacheIdBox &
setAddr(uint32_t addr)2933 CacheIdBox::setAddr(uint32_t addr)
2934 {
2935   m_base->setAddr(addr);
2936   return *this;
2937 }
2938 
2939 inline CacheIdBox &
setUnassigned(bool state)2940 CacheIdBox::setUnassigned(bool state)
2941 {
2942   m_base->setUnassigned(state);
2943   return *this;
2944 }
2945 
AssignmentKeyElt(uint32_t addr,uint32_t n)2946 inline AssignmentKeyElt::AssignmentKeyElt(uint32_t addr, uint32_t n) : m_addr(addr), m_change_number(htonl(n)) {}
2947 inline uint32_t
getAddr()2948 AssignmentKeyElt::getAddr() const
2949 {
2950   return m_addr;
2951 }
2952 inline AssignmentKeyElt &
setAddr(uint32_t addr)2953 AssignmentKeyElt::setAddr(uint32_t addr)
2954 {
2955   m_addr = addr;
2956   return *this;
2957 }
2958 inline uint32_t
getChangeNumber()2959 AssignmentKeyElt::getChangeNumber() const
2960 {
2961   return ntohl(m_change_number);
2962 }
2963 inline AssignmentKeyElt &
setChangeNumber(uint32_t n)2964 AssignmentKeyElt::setChangeNumber(uint32_t n)
2965 {
2966   m_change_number = htonl(n);
2967   return *this;
2968 }
2969 
RouterAssignElt(uint32_t addr,uint32_t recv_id,uint32_t change_number)2970 inline RouterAssignElt::RouterAssignElt(uint32_t addr, uint32_t recv_id, uint32_t change_number)
2971   : super(addr, recv_id), m_change_number(htonl(change_number))
2972 {
2973 }
2974 inline uint32_t
getChangeNumber()2975 RouterAssignElt::getChangeNumber() const
2976 {
2977   return ntohl(m_change_number);
2978 }
2979 inline RouterAssignElt &
setChangeNumber(uint32_t n)2980 RouterAssignElt::setChangeNumber(uint32_t n)
2981 {
2982   m_change_number = htonl(n);
2983   return *this;
2984 }
2985 
SecurityComp()2986 inline SecurityComp::SecurityComp() : m_local_key(false) {}
2987 inline void
setDefaultOption(Option opt)2988 SecurityComp::setDefaultOption(Option opt)
2989 {
2990   m_default_opt = opt;
2991 }
2992 inline size_t
calcSize(Option opt)2993 SecurityComp::calcSize(Option opt)
2994 {
2995   return SECURITY_NONE == opt ? sizeof(RawNone) : sizeof(RawMD5);
2996 }
2997 
ServiceComp()2998 inline ServiceComp::ServiceComp() : m_port_count(0) {}
2999 inline ServiceComp::raw_t *
access()3000 ServiceComp::access()
3001 {
3002   return reinterpret_cast<raw_t *>(m_base);
3003 }
3004 inline ServiceComp::raw_t const *
access()3005 ServiceComp::access() const
3006 {
3007   return reinterpret_cast<raw_t const *>(m_base);
3008 }
3009 inline ServiceGroup::Type
getSvcType()3010 ServiceComp::getSvcType() const
3011 {
3012   return this->access()->getSvcType();
3013 }
3014 inline ServiceComp &
setSvcType(ServiceGroup::Type t)3015 ServiceComp::setSvcType(ServiceGroup::Type t)
3016 {
3017   this->access()->setSvcType(t);
3018   return *this;
3019 }
3020 inline uint8_t
getSvcId()3021 ServiceComp::getSvcId() const
3022 {
3023   return this->access()->getSvcId();
3024 }
3025 inline ServiceComp &
setSvcId(uint8_t id)3026 ServiceComp::setSvcId(uint8_t id)
3027 {
3028   this->access()->setSvcId(id);
3029   return *this;
3030 }
3031 inline uint8_t
getPriority()3032 ServiceComp::getPriority() const
3033 {
3034   return this->access()->getPriority();
3035 }
3036 inline ServiceComp &
setPriority(uint8_t pri)3037 ServiceComp::setPriority(uint8_t pri)
3038 {
3039   this->access()->setPriority(pri);
3040   return *this;
3041 }
3042 inline uint8_t
getProtocol()3043 ServiceComp::getProtocol() const
3044 {
3045   return this->access()->getProtocol();
3046 }
3047 inline ServiceComp &
setProtocol(uint8_t proto)3048 ServiceComp::setProtocol(uint8_t proto)
3049 {
3050   this->access()->setProtocol(proto);
3051   return *this;
3052 }
3053 inline uint32_t
getFlags()3054 ServiceComp::getFlags() const
3055 {
3056   return this->access()->getFlags();
3057 }
3058 inline ServiceComp &
setFlags(uint32_t flags)3059 ServiceComp::setFlags(uint32_t flags)
3060 {
3061   this->access()->setFlags(flags);
3062   return *this;
3063 }
3064 inline ServiceComp &
enableFlags(uint32_t flags)3065 ServiceComp::enableFlags(uint32_t flags)
3066 {
3067   this->access()->enableFlags(flags);
3068   return *this;
3069 }
3070 inline ServiceComp &
disableFlags(uint32_t flags)3071 ServiceComp::disableFlags(uint32_t flags)
3072 {
3073   this->access()->disableFlags(flags);
3074   return *this;
3075 }
3076 inline uint16_t
getPort(int idx)3077 ServiceComp::getPort(int idx) const
3078 {
3079   return this->access()->getPort(idx);
3080 }
3081 inline size_t
calcSize()3082 ServiceComp::calcSize()
3083 {
3084   return sizeof(raw_t);
3085 }
3086 inline ServiceComp::operator ServiceGroup const &() const
3087 {
3088   return *static_cast<ServiceGroup const *>(this->access());
3089 }
3090 
3091 inline size_t
calcSize(int n)3092 RouterIdComp::calcSize(int n)
3093 {
3094   return sizeof(raw_t) + n * sizeof(uint32_t);
3095 }
3096 
3097 inline uint32_t
getKeyAddr()3098 RouterViewComp::getKeyAddr() const
3099 {
3100   return this->keyElt().getAddr();
3101 }
3102 inline RouterViewComp &
setKeyAddr(uint32_t addr)3103 RouterViewComp::setKeyAddr(uint32_t addr)
3104 {
3105   this->keyElt().setAddr(addr);
3106   return *this;
3107 }
3108 inline uint32_t
getKeyChangeNumber()3109 RouterViewComp::getKeyChangeNumber() const
3110 {
3111   return this->keyElt().getChangeNumber();
3112 }
3113 inline RouterViewComp &
setKeyChangeNumber(uint32_t change_number)3114 RouterViewComp::setKeyChangeNumber(uint32_t change_number)
3115 {
3116   this->keyElt().setChangeNumber(change_number);
3117   return *this;
3118 }
3119 inline CacheIdBox const &
cacheId(int idx)3120 RouterViewComp::cacheId(int idx) const
3121 {
3122   return const_cast<self *>(this)->cacheId(idx);
3123 }
3124 
3125 inline CacheIdBox &
cacheId()3126 CacheIdComp::cacheId()
3127 {
3128   return m_box;
3129 }
3130 inline CacheIdBox const &
cacheId()3131 CacheIdComp::cacheId() const
3132 {
3133   return m_box;
3134 }
3135 inline uint32_t
getAddr()3136 CacheIdComp::getAddr() const
3137 {
3138   return this->cacheId().getAddr();
3139 }
3140 inline CacheIdComp &
setAddr(uint32_t addr)3141 CacheIdComp::setAddr(uint32_t addr)
3142 {
3143   this->cacheId().setAddr(addr);
3144   return *this;
3145 }
3146 inline uint16_t
getHashRev()3147 CacheIdComp::getHashRev() const
3148 {
3149   return this->cacheId().getHashRev();
3150 }
3151 inline CacheIdComp &
setHashRev(uint16_t rev)3152 CacheIdComp::setHashRev(uint16_t rev)
3153 {
3154   this->cacheId().setHashRev(rev);
3155   return *this;
3156 }
3157 inline bool
getUnassigned()3158 CacheIdComp::getUnassigned() const
3159 {
3160   return this->cacheId().getUnassigned();
3161 }
3162 inline CacheIdComp &
setUnassigned(bool state)3163 CacheIdComp::setUnassigned(bool state)
3164 {
3165   this->cacheId().setUnassigned(state);
3166   return *this;
3167 }
3168 
3169 inline bool
isActive()3170 detail::Assignment::isActive() const
3171 {
3172   return m_active;
3173 }
3174 inline detail::Assignment &
setActive(bool state)3175 detail::Assignment::setActive(bool state)
3176 {
3177   m_active = state;
3178   return *this;
3179 }
3180 inline detail::Assignment &
updateRouterId(uint32_t addr,uint32_t rcvid,uint32_t cno)3181 detail::Assignment::updateRouterId(uint32_t addr, uint32_t rcvid, uint32_t cno)
3182 {
3183   if (m_router_list)
3184     m_router_list->updateRouterId(addr, rcvid, cno);
3185   return *this;
3186 }
AssignmentKeyElt()3187 inline AssignmentKeyElt::AssignmentKeyElt() {}
3188 inline AssignmentKeyElt const &
getKey()3189 detail::Assignment::getKey() const
3190 {
3191   return m_key;
3192 }
3193 inline RouterAssignListElt const &
getRouterList()3194 detail::Assignment::getRouterList() const
3195 {
3196   assert(m_router_list);
3197   return *m_router_list;
3198 }
3199 inline HashAssignElt const &
getHash()3200 detail::Assignment::getHash() const
3201 {
3202   assert(m_hash_assign);
3203   return *m_hash_assign;
3204 }
3205 inline MaskAssignElt const &
getMask()3206 detail::Assignment::getMask() const
3207 {
3208   assert(m_mask_assign);
3209   return *m_mask_assign;
3210 }
3211 
MsgBuffer()3212 inline MsgBuffer::MsgBuffer() : super(), _count(0) {}
MsgBuffer(super const & that)3213 inline MsgBuffer::MsgBuffer(super const &that) : super(that), _count(0) {}
MsgBuffer(void * p,size_t n)3214 inline MsgBuffer::MsgBuffer(void *p, size_t n) : super(static_cast<char *>(p), n), _count(0) {}
3215 
3216 inline size_t
getSize()3217 MsgBuffer::getSize() const
3218 {
3219   return _size;
3220 }
3221 inline size_t
getCount()3222 MsgBuffer::getCount() const
3223 {
3224   return _count;
3225 }
3226 inline char *
getBase()3227 MsgBuffer::getBase()
3228 {
3229   return _ptr;
3230 }
3231 inline const char *
getBase()3232 MsgBuffer::getBase() const
3233 {
3234   return _ptr;
3235 }
3236 inline char *
getTail()3237 MsgBuffer::getTail()
3238 {
3239   return _ptr + _count;
3240 }
3241 inline size_t
getSpace()3242 MsgBuffer::getSpace() const
3243 {
3244   return _size - _count;
3245 }
3246 inline MsgBuffer &
reset()3247 MsgBuffer::reset()
3248 {
3249   _count = 0;
3250   return *this;
3251 }
3252 
3253 inline MsgBuffer &
set(void * ptr,size_t n)3254 MsgBuffer::set(void *ptr, size_t n)
3255 {
3256   _ptr   = static_cast<char *>(ptr);
3257   _size  = n;
3258   _count = 0;
3259   return *this;
3260 }
3261 
3262 inline MsgBuffer &
use(size_t n)3263 MsgBuffer::use(size_t n)
3264 {
3265   _count += std::min(n, this->getSpace());
3266   return *this;
3267 }
3268 
3269 inline MsgBuffer &
zero()3270 MsgBuffer::zero()
3271 {
3272   memset(_ptr, 0, _size);
3273   _count = 0;
3274   return *this;
3275 }
3276 
PacketStamp()3277 inline PacketStamp::PacketStamp() : m_time(0), m_sn(0) {}
3278 
3279 inline PacketStamp &
set(time_t time,uint32_t sn)3280 PacketStamp::set(time_t time, uint32_t sn)
3281 {
3282   m_time = time;
3283   m_sn   = sn;
3284   return *this;
3285 }
3286 
ServiceGroup()3287 inline ServiceGroup::ServiceGroup() : m_svc_type(STANDARD), m_svc_id(0), m_priority(0), m_protocol(0), m_flags(0) {}
3288 
RouterIdElt()3289 inline RouterIdElt::RouterIdElt() {}
RouterAssignElt()3290 inline RouterAssignElt::RouterAssignElt() : m_change_number(0) {}
3291 
RouterAssignListElt()3292 inline RouterAssignListElt::RouterAssignListElt() {}
RouterAssignListElt(int n)3293 inline RouterAssignListElt::RouterAssignListElt(int n) : m_count(htonl(n)) {}
3294 inline RouterAssignElt &
elt(int n)3295 RouterAssignListElt::elt(int n)
3296 {
3297   return access_array<RouterAssignElt>(this + 1)[n];
3298 }
3299 inline RouterAssignElt const &
elt(int n)3300 RouterAssignListElt::elt(int n) const
3301 {
3302   return const_cast<self *>(this)->elt(n);
3303 }
3304 inline size_t
calcVarSize(int n)3305 RouterAssignListElt::calcVarSize(int n)
3306 {
3307   return n * sizeof(RouterAssignElt);
3308 }
3309 inline size_t
calcSize(int n)3310 RouterAssignListElt::calcSize(int n)
3311 {
3312   return sizeof(self) + self::calcVarSize(n);
3313 }
3314 inline size_t
getSize()3315 RouterAssignListElt::getSize() const
3316 {
3317   return this->calcSize(this->getCount());
3318 }
3319 inline size_t
getVarSize()3320 RouterAssignListElt::getVarSize() const
3321 {
3322   return this->getSize() - sizeof(self);
3323 }
3324 // This is untainted because an overall size check is done when the packet is read. If any of the
3325 // counts are bogus, that size check will fail.
3326 // coverity[ -tainted_data_return]
3327 inline uint32_t
getCount()3328 RouterAssignListElt::getCount() const
3329 {
3330   return ntohl(m_count);
3331 }
3332 
HashAssignElt()3333 inline HashAssignElt::HashAssignElt() {}
HashAssignElt(int n)3334 inline HashAssignElt::HashAssignElt(int n) : m_count(htonl(n)) {}
3335 // This is untainted because an overall size check is done when the packet is read. If any of the
3336 // counts are bogus, that size check will fail.
3337 // coverity[ -tainted_data_return]
3338 inline uint32_t
getCount()3339 HashAssignElt::getCount() const
3340 {
3341   return ntohl(m_count);
3342 }
3343 inline size_t
calcSize(int n)3344 HashAssignElt::calcSize(int n)
3345 {
3346   return sizeof(self) + n * sizeof(uint32_t) + sizeof(Bucket) * N_BUCKETS;
3347 }
3348 inline size_t
getSize()3349 HashAssignElt::getSize() const
3350 {
3351   return self::calcSize(this->getCount());
3352 }
3353 inline uint32_t
getAddr(int idx)3354 HashAssignElt::getAddr(int idx) const
3355 {
3356   // coverity[ptr_arith]
3357   return (&m_count)[idx + 1];
3358 }
3359 inline HashAssignElt &
setAddr(int idx,uint32_t addr)3360 HashAssignElt::setAddr(int idx, uint32_t addr)
3361 {
3362   // coverity[ptr_arith]
3363   (&m_count)[idx + 1] = addr;
3364   return *this;
3365 }
3366 inline HashAssignElt::Bucket *
getBucketBase()3367 HashAssignElt::getBucketBase()
3368 {
3369   // coverity[ptr_arith]
3370   return reinterpret_cast<Bucket *>((&m_count + 1 + this->getCount()));
3371 }
3372 inline HashAssignElt::Bucket &
3373 HashAssignElt::operator[](size_t idx)
3374 {
3375   return this->getBucketBase()[idx];
3376 }
3377 inline HashAssignElt::Bucket const &
3378 HashAssignElt::operator[](size_t idx) const
3379 {
3380   return (*(const_cast<self *>(this)))[idx];
3381 }
3382 
3383 // This is untainted because an overall size check is done when the packet is read. If any of the
3384 // counts are bogus, that size check will fail.
3385 // coverity[ -tainted_data_return]
3386 inline uint32_t
getCount()3387 MaskAssignElt::getCount() const
3388 {
3389   return ntohl(m_count);
3390 }
3391 inline MaskValueSetElt *
3392 MaskAssignElt::appender::operator->()
3393 {
3394   return m_set;
3395 }
3396 inline MaskValueSetElt *
initSet(uint32_t srcAddr,uint32_t dstAddr,uint16_t srcPort,uint16_t dstPort)3397 MaskAssignElt::appender::initSet(uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
3398 {
3399   (*(new (m_set) MaskValueSetElt(0)))
3400     .setSrcAddrMask(srcAddr)
3401     .setDstAddrMask(dstAddr)
3402     .setSrcPortMask(srcPort)
3403     .setDstPortMask(dstPort);
3404   return m_set;
3405 }
3406 inline MaskValueSetElt *
mask(uint32_t srcAddr,uint32_t dstAddr,uint16_t srcPort,uint16_t dstPort)3407 MaskAssignElt::appender::mask(uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
3408 {
3409   m_set          = reinterpret_cast<MaskValueSetElt *>(reinterpret_cast<char *>(m_set) + m_set->getSize());
3410   m_elt->m_count = htonl(1 + m_elt->getCount()); // bump set count.
3411   this->initSet(srcAddr, dstAddr, srcPort, dstPort);
3412   return m_set;
3413 }
3414 inline MaskAssignElt::appender
init(uint32_t srcAddr,uint32_t dstAddr,uint16_t srcPort,uint16_t dstPort)3415 MaskAssignElt::init(uint32_t srcAddr, uint32_t dstAddr, uint16_t srcPort, uint16_t dstPort)
3416 {
3417   appender zret;
3418   m_count    = htonl(1);
3419   zret.m_set = reinterpret_cast<MaskValueSetElt *>(this + 1);
3420   zret.m_elt = this;
3421   zret.initSet(srcAddr, dstAddr, srcPort, dstPort);
3422   return zret;
3423 }
3424 
3425 inline bool
isEmpty()3426 ComponentBase::isEmpty() const
3427 {
3428   return 0 == m_base;
3429 }
3430 
3431 inline message_type_t
toMsgType(int t)3432 MsgHeaderComp::toMsgType(int t)
3433 {
3434   return HERE_I_AM != t && I_SEE_YOU != t && REDIRECT_ASSIGN != t && REMOVAL_QUERY != t ? INVALID_MSG_TYPE :
3435                                                                                           static_cast<message_type_t>(t);
3436 }
3437 
3438 template <typename T>
3439 CompType
getType()3440 CompWithHeader<T>::getType() const
3441 {
3442   return static_cast<CompType>(ntohs(reinterpret_cast<raw_t const *>(m_base)->m_type));
3443 }
3444 
3445 template <typename T>
3446 T &
setType(CompType t)3447 CompWithHeader<T>::setType(CompType t)
3448 {
3449   reinterpret_cast<raw_t *>(m_base)->m_type = htons(t);
3450   return static_cast<T &>(*this);
3451 }
3452 
3453 template <typename T>
3454 uint16_t
getLength()3455 CompWithHeader<T>::getLength() const
3456 {
3457   return ntohs(reinterpret_cast<raw_t const *>(m_base)->m_length);
3458 }
3459 
3460 template <typename T>
3461 T &
setLength(uint16_t length)3462 CompWithHeader<T>::setLength(uint16_t length)
3463 {
3464   reinterpret_cast<raw_t *>(m_base)->m_length = htons(length);
3465   return static_cast<T &>(*this);
3466 }
3467 
3468 template <typename T>
3469 int
checkHeader(MsgBuffer const & buffer,CompType ect)3470 CompWithHeader<T>::checkHeader(MsgBuffer const &buffer, CompType ect)
3471 {
3472   CompType act = this->getType();
3473   if (act != ect)
3474     return (act < COMP_TYPE_MIN || COMP_TYPE_MAX < act) ? PARSE_COMP_TYPE_INVALID : PARSE_COMP_OTHER_TYPE;
3475   if (this->getLength() + sizeof(raw_t) > buffer.getSpace())
3476     return PARSE_COMP_TOO_BIG;
3477   return PARSE_SUCCESS;
3478 }
3479 
3480 inline AssignInfoComp::Bucket &
bucket(int idx)3481 AssignInfoComp::bucket(int idx)
3482 {
3483   return m_buckets[idx];
3484 }
3485 inline AssignInfoComp::Bucket const &
bucket(int idx)3486 AssignInfoComp::bucket(int idx) const
3487 {
3488   return m_buckets[idx];
3489 }
RouterViewComp()3490 inline RouterViewComp::RouterViewComp() : m_cache_count(0)
3491 {
3492   ink_zero(m_cache_ids);
3493 }
3494 
CapComp()3495 inline CapComp::CapComp() {}
3496 inline CapComp &
invalidate()3497 CapComp::invalidate()
3498 {
3499   m_cached = false;
3500   return *this;
3501 }
3502 inline uint32_t
getEltCount()3503 CapComp::getEltCount() const
3504 {
3505   return this->m_count;
3506 }
3507 inline size_t
calcSize(int n)3508 CapComp::calcSize(int n)
3509 {
3510   return sizeof(super::raw_t) + n * sizeof(CapabilityElt);
3511 }
3512 inline ServiceGroup::PacketStyle
getPacketForwardStyle()3513 CapComp::getPacketForwardStyle() const
3514 {
3515   if (!m_cached)
3516     this->cache();
3517   return m_packet_forward;
3518 }
3519 inline ServiceGroup::PacketStyle
getPacketReturnStyle()3520 CapComp::getPacketReturnStyle() const
3521 {
3522   if (!m_cached)
3523     this->cache();
3524   return m_packet_return;
3525 }
3526 inline ServiceGroup::CacheAssignmentStyle
getCacheAssignmentStyle()3527 CapComp::getCacheAssignmentStyle() const
3528 {
3529   if (!m_cached)
3530     this->cache();
3531   return m_cache_assign;
3532 }
3533 
AssignMapComp()3534 inline AssignMapComp::AssignMapComp() {}
3535 
3536 /*  Implementation note: Due to a bug in gcc, we have to be
3537     careful with these fields. If we use the field access templates
3538     directly, we get bad results because the pointer to member matching
3539     is done incorrectly (it uses a super type, not @c raw_t). We work
3540     around this by putting the pointer to member in a static variable.
3541 */
3542 inline uint16_t
getAssignType()3543 AltAssignComp::getAssignType() const
3544 {
3545   static uint16_t raw_t::*mptr = &raw_t::m_assign_type;
3546   return get_field(mptr, m_base);
3547 }
3548 inline AltAssignComp &
setAssignType(uint16_t t)3549 AltAssignComp::setAssignType(uint16_t t)
3550 {
3551   static uint16_t raw_t::*mptr = &raw_t::m_assign_type;
3552   set_field(mptr, m_base, t);
3553   return *this;
3554 }
3555 inline uint16_t
getAssignLength()3556 AltAssignComp::getAssignLength() const
3557 {
3558   static uint16_t raw_t::*mptr = &raw_t::m_assign_length;
3559   return get_field(mptr, m_base);
3560 }
3561 inline AltAssignComp &
setAssignLength(uint16_t length)3562 AltAssignComp::setAssignLength(uint16_t length)
3563 {
3564   static uint16_t raw_t::*mptr = &raw_t::m_assign_length;
3565   set_field(mptr, m_base, length);
3566   return *this;
3567 }
3568 
3569 inline uint32_t
getRouterAddr()3570 QueryComp::getRouterAddr() const
3571 {
3572   return access_field(&raw_t::m_router_addr, m_base);
3573 }
3574 inline QueryComp &
setRouterAddr(uint32_t addr)3575 QueryComp::setRouterAddr(uint32_t addr)
3576 {
3577   access_field(&raw_t::m_router_addr, m_base) = addr;
3578   return *this;
3579 }
3580 inline uint32_t
getToAddr()3581 QueryComp::getToAddr() const
3582 {
3583   return access_field(&raw_t::m_to_addr, m_base);
3584 }
3585 inline QueryComp &
setToAddr(uint32_t addr)3586 QueryComp::setToAddr(uint32_t addr)
3587 {
3588   access_field(&raw_t::m_to_addr, m_base) = addr;
3589   return *this;
3590 }
3591 inline uint32_t
getCacheAddr()3592 QueryComp::getCacheAddr() const
3593 {
3594   return access_field(&raw_t::m_cache_addr, m_base);
3595 }
3596 inline QueryComp &
setCacheAddr(uint32_t addr)3597 QueryComp::setCacheAddr(uint32_t addr)
3598 {
3599   access_field(&raw_t::m_cache_addr, m_base) = addr;
3600   return *this;
3601 }
3602 inline uint32_t
getRecvId()3603 QueryComp::getRecvId() const
3604 {
3605   return get_field(&raw_t::m_recv_id, m_base);
3606 }
3607 inline QueryComp &
setRecvId(uint32_t data)3608 QueryComp::setRecvId(uint32_t data)
3609 {
3610   set_field(&raw_t::m_recv_id, m_base, data);
3611   return *this;
3612 }
3613 inline size_t
calcSize()3614 QueryComp::calcSize()
3615 {
3616   return sizeof(raw_t);
3617 }
3618 
SeedRouter()3619 inline detail::cache::SeedRouter::SeedRouter() {}
3620 
SeedRouter(uint32_t addr)3621 inline detail::cache::SeedRouter::SeedRouter(uint32_t addr) : m_addr(addr), m_count(0), m_xmit(0) {}
3622 
BaseMsg()3623 inline BaseMsg::BaseMsg() : m_buffer(0, 0) {}
3624 inline MsgBuffer const &
buffer()3625 BaseMsg::buffer() const
3626 {
3627   return m_buffer;
3628 }
3629 inline size_t
getSpace()3630 BaseMsg::getSpace() const
3631 {
3632   return m_buffer.getSpace();
3633 }
3634 inline size_t
getCount()3635 BaseMsg::getCount() const
3636 {
3637   return m_buffer.getCount();
3638 }
3639 
3640 inline RouterImpl::RouterData &
resize(size_t n)3641 RouterImpl::RouterData::resize(size_t n)
3642 {
3643   m_src.resize(n);
3644   return *this;
3645 }
3646 // ------------------------------------------------------
3647 
3648 } // namespace wccp
3649