libtins  4.0
pdu_allocator.h
1 /*
2  * Copyright (c) 2017, Matias Fontanini
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are
7  * met:
8  *
9  * * Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * * Redistributions in binary form must reproduce the above
12  * copyright notice, this list of conditions and the following disclaimer
13  * in the documentation and/or other materials provided with the
14  * distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
17  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
18  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
19  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
20  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  *
28  */
29 
30 #ifndef TINS_PDU_ALLOCATOR_H
31 #define TINS_PDU_ALLOCATOR_H
32 
33 #include <map>
34 #include <tins/pdu.h>
35 
36 namespace Tins {
40 class EthernetII;
41 class SNAP;
42 class Dot1Q;
43 class SLL;
44 class IP;
45 class IPv6;
46 
47 namespace Internals {
48 
49 template<typename PDUType>
50 PDU* default_allocator(const uint8_t* buffer, uint32_t size) {
51  return new PDUType(buffer, size);
52 }
53 
54 template<typename Tag>
55 class PDUAllocator {
56 public:
57  typedef typename Tag::identifier_type id_type;
58  typedef PDU *(*allocator_type)(const uint8_t *, uint32_t);
59 
60  template<typename PDUType>
61  static void register_allocator(id_type identifier) {
62  allocators[identifier] = &default_allocator<PDUType>;
63  pdu_types[PDUType::pdu_flag] = identifier;
64  }
65 
66  static PDU* allocate(id_type identifier, const uint8_t* buffer, uint32_t size) {
67  typename allocators_type::const_iterator it = allocators.find(identifier);
68  return (it == allocators.end()) ? 0 : (*it->second)(buffer, size);
69  }
70 
71  static bool pdu_type_registered(PDU::PDUType type) {
72  return pdu_types.count(type) != 0;
73  }
74 
75  static id_type pdu_type_to_id(PDU::PDUType type) {
76  typename pdu_map_types::const_iterator it = pdu_types.find(type);
77  return it->second;
78  }
79 private:
80  typedef std::map<id_type, allocator_type> allocators_type;
81  typedef std::map<PDU::PDUType, id_type> pdu_map_types;
82 
83  static allocators_type allocators;
84  static pdu_map_types pdu_types;
85 };
86 
87 template<typename Tag>
88 typename PDUAllocator<Tag>::allocators_type PDUAllocator<Tag>::allocators;
89 
90 template<typename Tag>
91 typename PDUAllocator<Tag>::pdu_map_types PDUAllocator<Tag>::pdu_types;
92 
93 template<typename IDType>
94 struct pdu_tag {
95  typedef IDType identifier_type;
96 };
97 
98 template<typename PDUType>
99 struct pdu_tag_mapper;
100 
101 #define TINS_GENERATE_TAG_MAPPER(pdu, id_type) \
102 template<> \
103 struct pdu_tag_mapper<pdu> { \
104  typedef pdu_tag<id_type> type; \
105 };
106 
107 TINS_GENERATE_TAG_MAPPER(EthernetII, uint16_t)
108 TINS_GENERATE_TAG_MAPPER(SNAP, uint16_t)
109 TINS_GENERATE_TAG_MAPPER(SLL, uint16_t)
110 TINS_GENERATE_TAG_MAPPER(Dot1Q, uint16_t)
111 TINS_GENERATE_TAG_MAPPER(IP, uint8_t)
112 TINS_GENERATE_TAG_MAPPER(IPv6, uint8_t)
113 
114 #undef TINS_GENERATE_TAG_MAPPER
115 
116 template<typename PDUType>
117 PDU* allocate(typename pdu_tag_mapper<PDUType>::type::identifier_type id,
118  const uint8_t* buffer,
119  uint32_t size) {
120  return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::allocate(id, buffer, size);
121 }
122 
123 template<typename PDUType>
124 bool pdu_type_registered(PDU::PDUType type) {
125  return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::pdu_type_registered(type);
126 }
127 
128 template<typename PDUType>
129 typename pdu_tag_mapper<PDUType>::type::identifier_type pdu_type_to_id(PDU::PDUType type) {
130  return PDUAllocator<typename pdu_tag_mapper<PDUType>::type>::pdu_type_to_id(type);
131 }
132 
133 } // Interals
141 namespace Allocators {
165 template<typename PDUType, typename AllocatedType>
166 void register_allocator(typename Internals::pdu_tag_mapper<PDUType>::type::identifier_type id) {
167  Internals::PDUAllocator<
168  typename Internals::pdu_tag_mapper<PDUType>::type
169  >::template register_allocator<AllocatedType>(id);
170 }
171 
172 } // Allocators
173 } // Tins
174 
175 #endif // TINS_PDU_ALLOCATOR_H
PDUType
Enum which identifies each type of PDU.
Definition: pdu.h:127
The Tins namespace.
Definition: address_range.h:38
void register_allocator(typename Internals::pdu_tag_mapper< PDUType >::type::identifier_type id)
Registers an allocator for the provided PDU type.
Definition: pdu_allocator.h:166