EMANE  1.2.1
filterreader.cc
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2013,2016 - Adjacent Link LLC, Bridgewater, New Jersey
3  * Copyright (c) 2009-2010 - DRS CenGen, LLC, Columbia, Maryland
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * * Redistributions of source code must retain the above copyright
11  * notice, this list of conditions and the following disclaimer.
12  * * Redistributions in binary form must reproduce the above copyright
13  * notice, this list of conditions and the following disclaimer in
14  * the documentation and/or other materials provided with the
15  * distribution.
16  * * Neither the name of DRS CenGen, LLC nor the names of its
17  * contributors may be used to endorse or promote products derived
18  * from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
23  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
24  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
25  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
26  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
27  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
30  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #include "filterreader.h"
35 #include "ipprotocoludprule.h"
36 #include "ipprotocolsimplerule.h"
38 
39 #include "emane/net.h"
41 
42 #include <arpa/inet.h>
43 
44 void
45 EMANE::Models::CommEffect::FilterReader::getFilters(xmlNode * cur, Filters & filters)
46 {
47  while(cur)
48  {
49  if((!xmlStrcmp(cur->name, XMLCHAR "filter")))
50  {
51  Target * pTarget = getTarget(cur->xmlChildrenNode);
52 
53  if(pTarget)
54  {
55  auto optionalEffect = getEffect(cur->xmlChildrenNode);
56 
57  if(optionalEffect.second)
58  {
59  filters.push_back({pTarget,optionalEffect.first});
60  }
61  else
62  {
63  delete pTarget;
64  }
65  }
66  }
67  cur = cur->next;
68  }
69 }
70 
71 
72 
74 EMANE::Models::CommEffect::FilterReader::getTarget(xmlNode * cur)
75 {
76  while(cur)
77  {
78  if((!xmlStrcmp(cur->name, XMLCHAR "target")))
79  {
80  EthernetProtocolRules rules =
81  getEthernetProtocolRules(cur->xmlChildrenNode);
82 
83  return new Target(rules);
84  }
85  cur = cur->next;
86  }
87 
88  return NULL;
89 }
90 
91 
92 
93 std::pair<EMANE::Events::CommEffect,bool>
94 EMANE::Models::CommEffect::FilterReader::getEffect(xmlNode * cur)
95 {
96  while(cur)
97  {
98  if((!xmlStrcmp(cur->name, XMLCHAR "effect")))
99  {
100  return std::make_pair(Events::CommEffect{0,
101  getDuration(cur->xmlChildrenNode, "latency"),
102  getDuration(cur->xmlChildrenNode, "jitter"),
103  getProbability(cur->xmlChildrenNode, "loss"),
104  getProbability(cur->xmlChildrenNode, "duplicate"),
105  getBitRate(cur->xmlChildrenNode, "unicastbitrate"),
106  getBitRate(cur->xmlChildrenNode, "broadcastbitrate")},true);
107  }
108  cur = cur->next;
109  }
110 
111  return std::make_pair(EMANE::Events::CommEffect{0,{},{},0,0,0,0},false);
112 }
113 
114 
115 
117 EMANE::Models::CommEffect::FilterReader::getEthernetProtocolRules(xmlNode * cur)
118 {
119  EthernetProtocolRules rules;
120 
121  while(cur)
122  {
123  if((!xmlStrcmp(cur->name, XMLCHAR "ipv4")))
124  {
125  std::string sSrc = getAttribute(cur, XMLCHAR "src");
126  std::string sDst = getAttribute(cur, XMLCHAR "dst");
127  std::string sLen = getAttribute(cur, XMLCHAR "len");
128  std::string sTTL = getAttribute(cur, XMLCHAR "ttl");
129  std::string sTOS = getAttribute(cur, XMLCHAR "tos");
130 
131  EthernetProtocolIPv4Rule * ethProto =
132  new EthernetProtocolIPv4Rule{static_cast<uint32_t>(inet_addr(sSrc.c_str())),
133  static_cast<uint32_t>(inet_addr(sDst.c_str())),
134  EMANE::HTONS(Utils::ParameterConvert(sLen).toUINT16()),
135  Utils::ParameterConvert(sTOS).toUINT8(),
136  Utils::ParameterConvert(sTTL).toUINT8(),
137  getIPProtocolRules(cur->xmlChildrenNode)};
138 
139  rules.push_back(ethProto);
140  }
141 
142  cur = cur->next;
143  }
144 
145  return rules;
146 }
147 
148 
149 
151 EMANE::Models::CommEffect::FilterReader::getIPProtocolRules(xmlNodePtr cur)
152 {
153  IPProtocolRules rules;
154 
155  while(cur)
156  {
157  if((!xmlStrcmp(cur->name, XMLCHAR "udp")))
158  {
159  std::string sSrc = getAttribute(cur, XMLCHAR "sport");
160  std::string sDst = getAttribute(cur, XMLCHAR "dport");
161 
162  rules.push_back(new IPProtocolUDPRule{EMANE::HTONS(Utils::ParameterConvert(sSrc).toUINT16()),
163  EMANE::HTONS(Utils::ParameterConvert(sDst).toUINT16())});
164  }
165  else if((!xmlStrcmp(cur->name, XMLCHAR "protocol")))
166  {
167  std::string type = getAttribute(cur, XMLCHAR "type");
168 
169  rules.push_back(new IPProtocolSimpleRule{Utils::ParameterConvert(type).toUINT8()});
170  }
171 
172  cur = cur->next;
173  }
174 
175  return rules;
176 }
177 
178 
179 
181 EMANE::Models::CommEffect::FilterReader::getDuration(xmlNode * cur, const char *id)
182 {
183  while(cur)
184  {
185  if((!xmlStrcmp(cur->name, XMLCHAR id)))
186  {
187  std::string sSec = getAttribute(cur, XMLCHAR "sec");
188  std::string sUSec = getAttribute(cur, XMLCHAR "usec");
189 
190  return Microseconds{std::chrono::duration_cast<Microseconds>(std::chrono::seconds{Utils::ParameterConvert(sSec).toUINT32()}) +
191  Microseconds{Utils::ParameterConvert(sUSec).toUINT32()}};
192  }
193  cur = cur->next;
194  }
195 
196  return EMANE::Microseconds::zero();
197 }
198 
199 
200 
201 float
202 EMANE::Models::CommEffect::FilterReader::getProbability(xmlNode * cur, const char * id)
203 {
204  while(cur)
205  {
206  if((!xmlStrcmp(cur->name, XMLCHAR id)))
207  {
208  std::string sValue = getContent(cur);
209 
210  return Utils::ParameterConvert(sValue).toFloat();
211  }
212  cur = cur->next;
213  }
214 
215  return 0;
216 }
217 
218 
219 std::uint64_t
220 EMANE::Models::CommEffect::FilterReader::getBitRate(xmlNode * cur, const char * id)
221 {
222  while(cur)
223  {
224  if((!xmlStrcmp(cur->name, XMLCHAR id)))
225  {
226  std::string sValue = getContent(cur);
227 
228  return Utils::ParameterConvert(sValue).toUINT64();
229  }
230  cur = cur->next;
231  }
232 
233  return 0;
234 }
235 
236 
237 
238 std::string
239 EMANE::Models::CommEffect::FilterReader::getAttribute(xmlNodePtr cur, const xmlChar * id)
240 {
241  // default. don't care
242  std::string str = "0";
243 
244  if(id)
245  {
246  xmlChar *attr = xmlGetProp(cur, id);
247 
248  if(attr)
249  {
250  str =(const char *) attr;
251  }
252  xmlFree(attr);
253  }
254 
255  return str;
256 }
257 
258 
259 std::string
260 EMANE::Models::CommEffect::FilterReader::getContent(xmlNodePtr cur)
261 {
262  // default. don't care
263  std::string str = "0";
264 
265  xmlChar *attr = xmlNodeGetContent(cur);
266 
267  if(attr)
268  {
269  str =(const char *) attr;
270  }
271  xmlFree(attr);
272 
273  return str;
274 }
275 
278 {
279  xmlDoc * pDoc{};
280  xmlNode * pRoot{};
281  xmlParserCtxtPtr pContext{};
282  Filters filters;
283 
284  if(pzFilename)
285  {
286  pContext = xmlNewParserCtxt();
287 
288  if(pContext)
289  {
290  // Allocate the document tree
291  if(!(pDoc = xmlCtxtReadFile(pContext,
292  pzFilename,
293  0,
294  XML_PARSE_DTDVALID)))
295  {
296  xmlFreeParserCtxt(pContext);
297 
298  throw FilterLoadFailure{};
299  }
300 
301  if((pContext)->valid)
302  {
303  if(!(pRoot = xmlDocGetRootElement(pDoc)))
304  {
305  xmlFreeParserCtxt(pContext);
306 
307  throw FilterLoadFailure{};
308  }
309  }
310  else
311  {
312  xmlFreeParserCtxt(pContext);
313 
314  xmlFreeDoc(pDoc);
315 
316  throw FilterLoadFailure{};
317  }
318  }
319  else
320  {
321  throw FilterLoadFailure{};
322  }
323  }
324  else
325  {
326  throw FilterLoadFailure{};;
327  }
328 
329  xmlNodePtr pCurrent = pRoot;
330 
331  while(pCurrent)
332  {
333  if((!xmlStrcmp(pCurrent->name, XMLCHAR "commeffect")))
334  {
335  getFilters(pCurrent->xmlChildrenNode, filters);
336  }
337 
338  pCurrent = pCurrent->next;
339  }
340 
341  xmlFreeParserCtxt(pContext);
342 
343  xmlFreeDoc(pDoc);
344 
345  return filters;
346 }
std::list< IPProtocolRule * > IPProtocolRules
std::list< Filter > Filters
Definition: filter.h:64
static Filters load(const char *pzFileName)
std::list< EthernetProtocolRule * > EthernetProtocolRules
std::chrono::microseconds Microseconds
Definition: types.h:45
A CommEffect entry holds the NEM Id of a transmitter and the link effects to apply to received transm...
Definition: commeffect.h:52
constexpr std::uint16_t HTONS(std::uint16_t x)
Definition: net.h:125
#define XMLCHAR
Definition: filterreader.h:47