Platinum UPnP SDK
PltUtilities.h
1 /*****************************************************************
2 |
3 | Platinum - Utilities
4 |
5 | Copyright (c) 2004-2010, Plutinosoft, LLC.
6 | All rights reserved.
7 | http://www.plutinosoft.com
8 |
9 | This program is free software; you can redistribute it and/or
10 | modify it under the terms of the GNU General Public License
11 | as published by the Free Software Foundation; either version 2
12 | of the License, or (at your option) any later version.
13 |
14 | OEMs, ISVs, VARs and other distributors that combine and
15 | distribute commercially licensed software with Platinum software
16 | and do not wish to distribute the source code for the commercially
17 | licensed software under version 2, or (at your option) any later
18 | version, of the GNU General Public License (the "GPL") must enter
19 | into a commercial license agreement with Plutinosoft, LLC.
20 | licensing@plutinosoft.com
21 |
22 | This program is distributed in the hope that it will be useful,
23 | but WITHOUT ANY WARRANTY; without even the implied warranty of
24 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 | GNU General Public License for more details.
26 |
27 | You should have received a copy of the GNU General Public License
28 | along with this program; see the file LICENSE.txt. If not, write to
29 | the Free Software Foundation, Inc.,
30 | 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
31 | http://www.gnu.org/licenses/gpl-2.0.html
32 |
33 ****************************************************************/
34 
35 #ifndef _PLT_UTILITIES_H_
36 #define _PLT_UTILITIES_H_
37 
38 /*----------------------------------------------------------------------
39 | includes
40 +---------------------------------------------------------------------*/
41 #include "Neptune.h"
42 
43 /*----------------------------------------------------------------------
44 | PLT_XmlAttributeFinder
45 +---------------------------------------------------------------------*/
51 {
52 public:
53  // if 'namespc' is NULL, we're looking for ANY namespace
54  // if 'namespc' is '\0', we're looking for NO namespace
55  // if 'namespc' is non-empty, look for that SPECIFIC namespace
56  PLT_XmlAttributeFinder(const NPT_XmlElementNode& element,
57  const char* name,
58  const char* namespc) :
59  m_Element(element), m_Name(name), m_Namespace(namespc) {}
60 
61  bool operator()(const NPT_XmlAttribute* const & attribute) const {
62  if (attribute->GetName() == m_Name) {
63  if (m_Namespace) {
64  const NPT_String& prefix = attribute->GetPrefix();
65  if (m_Namespace[0] == '\0') {
66  // match if the attribute has NO namespace
67  return prefix.IsEmpty();
68  } else {
69  // match if the attribute has the SPECIFIC namespace
70  // we're looking for
71  const NPT_String* namespc = m_Element.GetNamespaceUri(prefix);
72  return namespc && *namespc == m_Namespace;
73  }
74  } else {
75  // ANY namespace will match
76  return true;
77  }
78  } else {
79  return false;
80  }
81  }
82 
83 private:
84  const NPT_XmlElementNode& m_Element;
85  const char* m_Name;
86  const char* m_Namespace;
87 };
88 
89 /*----------------------------------------------------------------------
90 | PLT_XmlHelper
91 +---------------------------------------------------------------------*/
97 {
98 public:
99 
100  // static methods
101 
102  static NPT_Result Parse(const NPT_String& xml,
103  NPT_XmlElementNode*& tree) {
104  // reset tree
105  tree = NULL;
106 
107  // parse body
108  NPT_XmlParser parser;
109  NPT_XmlNode* node;
110  NPT_Result result = parser.Parse(xml, node);
111  if (NPT_FAILED(result)) {
112  //NPT_LOG_FINEST_1("Failed to parse %s", xml.IsEmpty()?"(empty string)":xml.GetChars());
113  NPT_CHECK(result);
114  }
115 
116  tree = node->AsElementNode();
117  if (!tree) {
118  delete node;
119  return NPT_FAILURE;
120  }
121 
122  return NPT_SUCCESS;
123  }
124 
125  static NPT_Result GetChildText(NPT_XmlElementNode* node,
126  const char* tag,
127  NPT_String& value,
128  const char* namespc = "",
129  NPT_Cardinal max_size = 1024) {
130  value = "";
131 
132  if (!node) return NPT_FAILURE;
133 
134  // special case "" means we look for the same namespace as the parent
135  if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
136 
137  NPT_XmlElementNode* child = node->GetChild(tag, namespc);
138  if (!child) return NPT_FAILURE;
139 
140  const NPT_String* text = child->GetText();
141  // DLNA 7.3.17
142  value = text?text->SubString(0, max_size):"";
143  return NPT_SUCCESS;
144  }
145 
146  static NPT_Result RemoveAttribute(NPT_XmlElementNode* node,
147  const char* name,
148  const char* namespc = "") {
149  if (!node) return NPT_FAILURE;
150 
151  // special case "" means we look for the same namespace as the parent
152  if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
153 
154  NPT_List<NPT_XmlAttribute*>::Iterator attribute;
155  attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
156  if (!attribute) return NPT_FAILURE;
157 
158  delete *attribute;
159  NPT_CHECK(node->GetAttributes().Erase(attribute));
160 
161  return NPT_SUCCESS;
162  }
163 
164  static NPT_Result GetAttribute(NPT_XmlElementNode* node,
165  const char* name,
166  NPT_XmlAttribute*& attr,
167  const char* namespc = "") {
168  attr = NULL;
169 
170  if (!node) return NPT_FAILURE;
171 
172  // special case "" means we look for the same namespace as the parent
173  if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
174 
175  NPT_List<NPT_XmlAttribute*>::Iterator attribute;
176  attribute = node->GetAttributes().Find(PLT_XmlAttributeFinder(*node, name, namespc));
177  if (!attribute) {
178  //NPT_Debug("Failed to find attribute [%s]:%s", namespc, name);
179  return NPT_FAILURE;
180  }
181 
182  attr = (*attribute);
183  return NPT_SUCCESS;
184  }
185 
186  static NPT_Result GetAttribute(NPT_XmlElementNode* node,
187  const char* name,
188  NPT_String& value,
189  const char* namespc = "",
190  NPT_Cardinal max_size = 1024) {
191  value = "";
192 
193  NPT_XmlAttribute* attribute = NULL;
194  NPT_Result result = GetAttribute(node, name, attribute, namespc);
195  if (NPT_FAILED(result)) return result;
196 
197  if (!attribute) return NPT_FAILURE;
198  // DLNA 7.3.17 truncate to 1024 bytes
199  value = attribute->GetValue().SubString(0, max_size);
200  return NPT_SUCCESS;
201  }
202 
203  static NPT_Result SetAttribute(NPT_XmlElementNode* node,
204  const char* name,
205  NPT_String& value,
206  const char* namespc = "") {
207  NPT_XmlAttribute* attribute = NULL;
208  NPT_CHECK(GetAttribute(node, name, attribute, namespc));
209  if (!attribute) return NPT_FAILURE;
210 
211  attribute->SetValue(value);
212  return NPT_SUCCESS;
213  }
214 
215  static NPT_Result AddChildText(NPT_XmlElementNode* node,
216  const char* tag,
217  const char* text,
218  const char* prefix = NULL) {
219  if (!node) return NPT_FAILURE;
220  NPT_XmlElementNode* child = new NPT_XmlElementNode(prefix, tag);
221  child->AddText(text);
222  return node->AddChild(child);
223  }
224 
225  static bool IsMatch(const NPT_XmlNode* const & node, const char* tag, const char* namespc_mapped) {
226  // if m_Namespace is NULL, we're looking for ANY namespace
227  // if m_Namespace is '\0', we're looking for NO namespace
228  // if m_Namespace is non-empty, look for that SPECIFIC namespace
229 
230  const NPT_XmlElementNode* element = node->AsElementNode();
231  // is tag the same (case sensitive)?
232  if (element && element->GetTag() == tag) {
233  if (namespc_mapped) {
234  // look for a SPECIFIC namespace or NO namespace
235  const NPT_String* namespc = element->GetNamespace();
236  if (namespc) {
237  // the element has a namespace, match if it is equal to
238  // what we're looking for
239  return *namespc == namespc_mapped;
240  } else {
241  // the element does not have a namespace, match if we're
242  // looking for NO namespace
243  return namespc_mapped[0] == '\0';
244  }
245  } else {
246  // ANY namespace will match
247  return true;
248  }
249  }
250  return false;
251  }
252 
253  static NPT_Result GetChildren(NPT_XmlElementNode* node,
254  NPT_Array<NPT_XmlElementNode*>& children,
255  const char* tag,
256  const char* namespc = "") {
257  if (!node) return NPT_FAILURE;
258 
259  // special case "" means we look for the same namespace as the parent
260  if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
261 
262  const char* namespc_mapped = (namespc==NULL)?"":(namespc[0]=='*' && namespc[1]=='\0')?NULL:namespc;
263 
264  // get all children first
265  NPT_List<NPT_XmlNode*>& allchildren = node->GetChildren();
266 
267  // iterate through children and add only elements with matching tag
268  NPT_List<NPT_XmlNode*>::Iterator child = allchildren.GetFirstItem();
269  while (child) {
270  if (IsMatch(*child, tag, namespc_mapped)) {
271  children.Add((*child)->AsElementNode());
272  }
273  ++child;
274  }
275  return NPT_SUCCESS;
276  }
277 
278  static NPT_XmlElementNode* GetChild(NPT_XmlElementNode* node,
279  const char* tag,
280  const char* namespc = "") {
281  if (!node) return NULL;
282 
283  // special case "" means we look for the same namespace as the parent
284  if (namespc && namespc[0] == '\0') namespc = node->GetNamespace()?node->GetNamespace()->GetChars():NPT_XML_NO_NAMESPACE;
285 
286  return node->GetChild(tag, namespc);
287  }
288 
289  static NPT_Result GetChild(NPT_XmlElementNode* parent,
290  NPT_XmlElementNode*& child,
291  NPT_Ordinal n = 0) {
292  if (!parent) return NPT_FAILURE;
293 
294  // reset child
295  child = NULL;
296 
297  // get all children first
298  NPT_List<NPT_XmlNode*>::Iterator children = parent->GetChildren().GetFirstItem();
299  while (children) {
300  if ((*children)->AsElementNode() && n-- == 0) {
301  child = (*children)->AsElementNode();
302  return NPT_SUCCESS;
303  }
304  children++;
305  }
306 
307  return NPT_FAILURE;
308  }
309 
310  static NPT_Result Serialize(NPT_XmlNode& node, NPT_String& xml, bool add_header = true, NPT_Int8 indentation = 0) {
311  NPT_XmlWriter writer(indentation);
312  NPT_StringOutputStreamReference stream(new NPT_StringOutputStream(&xml));
313  NPT_CHECK(writer.Serialize(node, *stream, add_header));
314  return NPT_SUCCESS;
315  }
316 
317  static NPT_String Serialize(NPT_XmlNode& node, bool add_header = true, NPT_Int8 indentation = 0) {
318  NPT_XmlWriter writer(indentation);
319  NPT_String xml;
320  NPT_StringOutputStreamReference stream(new NPT_StringOutputStream(&xml));
321  if (NPT_FAILED(writer.Serialize(node, *stream, add_header))) {
322  NPT_Debug("Failed to serialize xml node");
323  return "";
324  }
325 
326  return xml;
327  }
328 private:
329  // members
330 };
331 
332 /*----------------------------------------------------------------------
333 | NPT_StringFinder
334 +---------------------------------------------------------------------*/
340 {
341 public:
342  // methods
343  NPT_StringFinder(const char* value, bool ignore_case = false) :
344  m_Value(value), m_IgnoreCase(ignore_case) {}
345  virtual ~NPT_StringFinder() {}
346  bool operator()(const NPT_String* const & value) const {
347  return value->Compare(m_Value, m_IgnoreCase) ? false : true;
348  }
349  bool operator()(const NPT_String& value) const {
350  return value.Compare(m_Value, m_IgnoreCase) ? false : true;
351  }
352 
353 private:
354  // members
355  NPT_String m_Value;
356  bool m_IgnoreCase;
357 };
358 
359 /*----------------------------------------------------------------------
360 | NPT_IpAddressFinder
361 +---------------------------------------------------------------------*/
367 {
368 public:
369  // methods
370  NPT_IpAddressFinder(NPT_IpAddress ip) : m_Value(ip) {}
371  virtual ~NPT_IpAddressFinder() {}
372 
373  bool operator()(const NPT_IpAddress* const & value) const {
374  return *value == m_Value;
375  }
376  bool operator()(const NPT_IpAddress& value) const {
377  return value == m_Value;
378  }
379 
380 private:
381  // members
382  NPT_IpAddress m_Value;
383 };
384 
385 
386 /*----------------------------------------------------------------------
387 | PLT_UPnPMessageHelper class
388 +---------------------------------------------------------------------*/
394 {
395 public:
396  // methods
397  static const NPT_String* GetST(const NPT_HttpMessage& message) {
398  return message.GetHeaders().GetHeaderValue("ST");
399  }
400  static NPT_Result SetST(NPT_HttpMessage& message,
401  const char* st) {
402  return message.GetHeaders().SetHeader("ST", st);
403  }
404  static const NPT_String* GetNT(const NPT_HttpMessage& message) {
405  return message.GetHeaders().GetHeaderValue("NT");
406  }
407  static NPT_Result SetNT(NPT_HttpMessage& message,
408  const char* nt) {
409  return message.GetHeaders().SetHeader("NT", nt);
410  }
411  static const NPT_String* GetNTS(const NPT_HttpMessage& message) {
412  return message.GetHeaders().GetHeaderValue("NTS");
413  }
414  static NPT_Result SetNTS(NPT_HttpMessage& message,
415  const char* nts) {
416  return message.GetHeaders().SetHeader("NTS", nts);
417  }
418  static const NPT_String* GetMAN(const NPT_HttpMessage& message) {
419  return message.GetHeaders().GetHeaderValue("MAN");
420  }
421  static NPT_Result SetMAN(NPT_HttpMessage& message,
422  const char* man) {
423  return message.GetHeaders().SetHeader("MAN", man);
424  }
425  static const NPT_String* GetLocation(const NPT_HttpMessage& message) {
426  return message.GetHeaders().GetHeaderValue("Location");
427  }
428  static NPT_Result SetLocation(NPT_HttpMessage& message,
429  const char* location) {
430  return message.GetHeaders().SetHeader("Location", location);
431  }
432  static const NPT_String* GetServer(const NPT_HttpMessage& message) {
433  return message.GetHeaders().GetHeaderValue(NPT_HTTP_HEADER_SERVER);
434  }
435  static NPT_Result SetServer(NPT_HttpMessage& message,
436  const char* server,
437  bool replace = true) {
438  return message.GetHeaders().SetHeader(
439  NPT_HTTP_HEADER_SERVER,
440  server,
441  replace);
442  }
443  static const NPT_String* GetUSN(const NPT_HttpMessage& message) {
444  return message.GetHeaders().GetHeaderValue("USN");
445  }
446  static NPT_Result SetUSN(NPT_HttpMessage& message,
447  const char* usn) {
448  return message.GetHeaders().SetHeader("USN", usn);
449  }
450  static const NPT_String* GetCallbacks(const NPT_HttpMessage& message) {
451  return message.GetHeaders().GetHeaderValue("CALLBACK");
452  }
453  static NPT_Result SetCallbacks(NPT_HttpMessage& message,
454  const char* callbacks) {
455  return message.GetHeaders().SetHeader("CALLBACK", callbacks);
456  }
457  static const NPT_String* GetSID(const NPT_HttpMessage& message) {
458  return message.GetHeaders().GetHeaderValue("SID");
459  }
460  static NPT_Result SetSID(NPT_HttpMessage& message,
461  const char* sid) {
462  return message.GetHeaders().SetHeader("SID", sid);
463  }
464  static NPT_Result GetLeaseTime(const NPT_HttpMessage& message,
465  NPT_TimeInterval& lease) {
466  const NPT_String* cc =
467  message.GetHeaders().GetHeaderValue("Cache-Control");
468  NPT_CHECK_POINTER(cc);
469  return ExtractLeaseTime(*cc, lease);
470  }
471  static NPT_Result SetLeaseTime(NPT_HttpMessage& message,
472  const NPT_TimeInterval& lease) {
473  return message.GetHeaders().SetHeader(
474  "Cache-Control",
475  "max-age="+NPT_String::FromInteger(lease.ToSeconds()));
476  }
477  static NPT_Result GetTimeOut(const NPT_HttpMessage& message,
478  NPT_Int32& seconds) {
479  seconds = 0;
480  const NPT_String* timeout =
481  message.GetHeaders().GetHeaderValue("TIMEOUT");
482  NPT_CHECK_POINTER(timeout);
483  return ExtractTimeOut(*timeout, seconds);
484  }
485  static NPT_Result SetTimeOut(NPT_HttpMessage& message,
486  const NPT_Int32 seconds) {
487  if (seconds >= 0) {
488  return message.GetHeaders().SetHeader(
489  "TIMEOUT",
490  "Second-"+NPT_String::FromInteger(seconds));
491  } else {
492  return message.GetHeaders().SetHeader(
493  "TIMEOUT",
494  "Second-infinite");
495  }
496  }
497  static NPT_Result SetDate(NPT_HttpMessage& message) {
498  NPT_TimeStamp now;
499  NPT_System::GetCurrentTimeStamp(now);
500  NPT_DateTime date(now);
501 
502  return message.GetHeaders().SetHeader("Date", date.ToString(NPT_DateTime::FORMAT_RFC_1123));
503  }
504  static NPT_Result GetIfModifiedSince(const NPT_HttpMessage& message,
505  NPT_DateTime& date) {
506 
507  const NPT_String* value =
508  message.GetHeaders().GetHeaderValue("If-Modified-Since");
509  if (!value) return NPT_FAILURE;
510 
511  // Try RFC 1123, RFC 1036, then ANSI
512  if (NPT_SUCCEEDED(date.FromString(*value, NPT_DateTime::FORMAT_RFC_1123)))
513  return NPT_SUCCESS;
514  if (NPT_SUCCEEDED(date.FromString(*value, NPT_DateTime::FORMAT_RFC_1036)))
515  return NPT_SUCCESS;
516  return date.FromString(*value, NPT_DateTime::FORMAT_ANSI);
517  }
518  static NPT_Result SetIfModifiedSince(NPT_HttpMessage& message,
519  const NPT_DateTime& date) {
520  return message.GetHeaders().SetHeader(
521  "If-Modified-Since",
522  date.ToString(NPT_DateTime::FORMAT_RFC_1123));
523  }
524  static NPT_Result GetMX(const NPT_HttpMessage& message,
525  NPT_UInt32& value) {
526  value = 0;
527  const NPT_String* mx =
528  message.GetHeaders().GetHeaderValue("MX");
529  NPT_CHECK_POINTER(mx);
530  return NPT_ParseInteger32(*mx, value, false); // no relax to be UPnP compliant
531  }
532  static NPT_Result SetMX(NPT_HttpMessage& message,
533  const NPT_UInt32 mx) {
534  return message.GetHeaders().SetHeader(
535  "MX",
536  NPT_String::FromInteger(mx));
537  }
538  static NPT_Result GetSeq(const NPT_HttpMessage& message,
539  NPT_UInt32& value) {
540  value = 0;
541  const NPT_String* seq =
542  message.GetHeaders().GetHeaderValue("SEQ");
543  NPT_CHECK_POINTER(seq);
544  return NPT_ParseInteger32(*seq, value);
545  }
546  static NPT_Result SetSeq(NPT_HttpMessage& message,
547  const NPT_UInt32 seq) {
548  return message.GetHeaders().SetHeader(
549  "SEQ",
550  NPT_String::FromInteger(seq));
551  }
552  static const char* GenerateUUID(int count,
553  NPT_String& uuid) {
554  uuid = "";
555  for (int i=0;i<(count<100?count:100);i++) {
556  int random = NPT_System::GetRandomInteger();
557  uuid += (char)((random % 25) + 66);
558  }
559  return uuid;
560  }
561 
562  static const char* GenerateSerialNumber(NPT_String& sn, int count = 40) {
563  sn = "{";
564  for (int i=0;i<count;i++) {
565  char nibble = (char)(NPT_System::GetRandomInteger() % 16);
566  sn += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
567  }
568  sn += "}";
569  return sn;
570  }
571  static const char* GenerateGUID(NPT_String& guid) {
572  guid = "";
573  for (int i=0;i<32;i++) {
574  char nibble = (char)(NPT_System::GetRandomInteger() % 16);
575  guid += (nibble < 10) ? ('0' + nibble) : ('a' + (nibble-10));
576  if (i == 7 || i == 11 || i == 15 || i == 19) {
577  guid += '-';
578  }
579  }
580  return guid;
581  }
582  static NPT_Result ExtractLeaseTime(const NPT_String& cache_control,
583  NPT_TimeInterval& lease) {
584  NPT_Int32 value;
585  if (cache_control.StartsWith("max-age=", true) &&
586  NPT_SUCCEEDED(NPT_ParseInteger32(cache_control.GetChars()+8,
587  value))) {
588  lease.SetSeconds(value);
589  return NPT_SUCCESS;
590  }
591  return NPT_FAILURE;
592  }
593  static NPT_Result ExtractTimeOut(const char* timeout,
594  NPT_Int32& len) {
595  NPT_String temp = timeout;
596  if (temp.CompareN("Second-", 7, true)) {
597  return NPT_ERROR_INVALID_FORMAT;
598  }
599 
600  if (temp.Compare("Second-infinite", true) == 0) {
601  len = NPT_TIMEOUT_INFINITE;
602  return NPT_SUCCESS;
603  }
604  return temp.SubString(7).ToInteger(len);
605  }
606  static NPT_Result GetIPAddresses(NPT_List<NPT_IpAddress>& ips,
607  bool with_localhost = false) {
608  NPT_List<NPT_NetworkInterface*> if_list;
609  NPT_CHECK(GetNetworkInterfaces(if_list, with_localhost));
610 
611  NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
612  while (iface) {
613  NPT_IpAddress ip = (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress();
614  if (ip.ToString().Compare("0.0.0.0") &&
615  (with_localhost || ip.ToString().Compare("127.0.0.1"))) {
616  ips.Add(ip);
617  }
618  ++iface;
619  }
620 
621  if (with_localhost && !ips.Find(NPT_IpAddressFinder(NPT_IpAddress(127, 0, 0, 1)))) {
622  NPT_IpAddress localhost;
623  localhost.Parse("127.0.0.1");
624  ips.Add(localhost);
625  }
626 
627  if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
628  return NPT_SUCCESS;
629  }
630 
631  static NPT_Result GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list,
632  bool with_localhost = false) {
633  NPT_CHECK(_GetNetworkInterfaces(if_list, with_localhost, false));
634 
635  // if no valid interfaces or if requested, add localhost interface
636  if (if_list.GetItemCount() == 0) {
637  NPT_CHECK(_GetNetworkInterfaces(if_list, true, true));
638  }
639  return NPT_SUCCESS;
640  }
641 
642  static NPT_Result GetMACAddresses(NPT_List<NPT_String>& addresses) {
643  NPT_List<NPT_NetworkInterface*> if_list;
644  NPT_CHECK(GetNetworkInterfaces(if_list));
645 
646  NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
647  while (iface) {
648  NPT_String ip = (*(*iface)->GetAddresses().GetFirstItem()).GetPrimaryAddress().ToString();
649  if (ip.Compare("0.0.0.0") && ip.Compare("127.0.0.1")) {
650  addresses.Add((*iface)->GetMacAddress().ToString());
651  }
652  ++iface;
653  }
654 
655  if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
656  return NPT_SUCCESS;
657  }
658 
659 
660  static bool IsLocalNetworkAddress(const NPT_IpAddress& address) {
661  if (address.ToString() == "127.0.0.1") return true;
662 
663  NPT_List<NPT_NetworkInterface*> if_list;
664  NPT_NetworkInterface::GetNetworkInterfaces(if_list);
665 
666  NPT_List<NPT_NetworkInterface*>::Iterator iface = if_list.GetFirstItem();
667  while (iface) {
668  if((*iface)->IsAddressInNetwork(address)) return true;
669  ++iface;
670  }
671 
672  if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
673  return false;
674  }
675 
676 private:
677 
678  static NPT_Result _GetNetworkInterfaces(NPT_List<NPT_NetworkInterface*>& if_list,
679  bool include_localhost = false,
680  bool only_localhost = false) {
681  NPT_List<NPT_NetworkInterface*> _if_list;
682  NPT_CHECK(NPT_NetworkInterface::GetNetworkInterfaces(_if_list));
683 
684  NPT_NetworkInterface* iface;
685  while (NPT_SUCCEEDED(_if_list.PopHead(iface))) {
686  // only interested in non PTP & multicast capable interfaces
687  if ((iface->GetAddresses().GetItemCount() == 0) ||
688  !(iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_MULTICAST) ||
689  (iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_POINT_TO_POINT)) {
690  delete iface;
691  continue;
692  }
693 
694  NPT_String ip = iface->GetAddresses().GetFirstItem()->GetPrimaryAddress().ToString();
695 
696  if (iface->GetFlags() & NPT_NETWORK_INTERFACE_FLAG_LOOPBACK) {
697  if (include_localhost || only_localhost) {
698  if_list.Add(iface);
699  continue;
700  }
701  } else if (ip.Compare("0.0.0.0") && !only_localhost) {
702  if_list.Add(iface);
703  continue;
704  }
705 
706  delete iface;
707  }
708 
709  // cleanup any remaining items in list if we breaked early
710  _if_list.Apply(NPT_ObjectDeleter<NPT_NetworkInterface>());
711  return NPT_SUCCESS;
712  }
713 };
714 
715 #endif // _PLT_UTILITIES_H_
716 
717 
718 
719 
720 
721 
722 
723 
724