model: Updated API for pluggable wire format

As of this commit, the selected (default) wire format is controlled via
global variable ndn::WireFormat:

    Config::SetGlobal ("ndn::WireFormat", IntegerValue (ndn::Wire::WIRE_FORMAT_CCNB));

or

    ./waf --run="... --ndn::WireFormat=1

Refs #1008 (http://redmine.named-data.net/issues/1008)
diff --git a/examples/ndn-simple-with-pcap.cc b/examples/ndn-simple-with-pcap.cc
index fb01947..6065624 100644
--- a/examples/ndn-simple-with-pcap.cc
+++ b/examples/ndn-simple-with-pcap.cc
@@ -56,7 +56,7 @@
   Config::SetDefault ("ns3::PointToPointChannel::Delay", StringValue ("10ms"));
   Config::SetDefault ("ns3::DropTailQueue::MaxPackets", StringValue ("20"));
 
-  Config::SetDefault ("ns3::ndn::Face::WireFormat", StringValue ("1"));
+  Config::SetGlobal ("ndn::WireFormat", StringValue ("1"));
 
   // Creating nodes
   NodeContainer nodes;
diff --git a/model/ndn-face.cc b/model/ndn-face.cc
index a408dc4..18231f5 100644
--- a/model/ndn-face.cc
+++ b/model/ndn-face.cc
@@ -34,10 +34,8 @@
 
 #include "ns3/ndn-header-helper.h"
 #include "ns3/ndnSIM/utils/ndn-fw-hop-count-tag.h"
-#include "ns3/ndnSIM/model/wire/ndnsim.h"
-#include "ns3/ndnSIM/model/wire/ndnsim/wire-ndnsim.h"
-#include "ns3/ndnSIM/model/wire/ccnb.h"
-#include "ns3/ndnSIM/model/wire/ccnb/wire-ccnb.h"
+
+#include "ns3/ndn-wire.h"
 
 #include <boost/ref.hpp>
 
@@ -59,14 +57,6 @@
                    UintegerValue (0),
                    MakeUintegerAccessor (&Face::m_id),
                    MakeUintegerChecker<uint32_t> ())
-
-    .AddAttribute ("WireFormat",
-                   "Default wire format for the face.  The face will be accepting packets "
-                   "in any supported packet formats, but if encoding requested, it will "
-                   "use default wire format to encode (0 for ndnSIM (default), 1 for CCNb)",
-                   UintegerValue (WIRE_FORMAT_NDNSIM),
-                   MakeUintegerAccessor (&Face::m_wireFormat),
-                   MakeUintegerChecker<uint32_t> ())
     ;
   return tid;
 }
@@ -139,16 +129,7 @@
       return false;
     }
 
-  Ptr<Packet> packet;
-  if (m_wireFormat == WIRE_FORMAT_NDNSIM)
-    packet = wire::ndnSIM::Interest::ToWire (interest);
-  else if (m_wireFormat == WIRE_FORMAT_CCNB)
-    packet = wire::ccnb::Interest::ToWire (interest);
-  else
-    {
-      NS_FATAL_ERROR ("Unsupported format requested");
-    }
-  return Send (packet);
+  return Send (Wire::FromInterest (interest));
 }
 
 bool
@@ -161,16 +142,7 @@
       return false;
     }
 
-  Ptr<Packet> packet;
-  if (m_wireFormat == WIRE_FORMAT_NDNSIM)
-    packet = wire::ndnSIM::Data::ToWire (data);
-  else if (m_wireFormat == WIRE_FORMAT_CCNB)
-    packet = wire::ccnb::Data::ToWire (data);
-  else
-    {
-      NS_FATAL_ERROR ("Unsupported format requested");
-    }
-  return Send (packet);
+  return Send (Wire::FromData (data));
 }
 
 bool
@@ -205,33 +177,20 @@
       switch (type)
         {
         case HeaderHelper::INTEREST_NDNSIM:
-          {
-            Ptr<Interest> interest = wire::ndnSIM::Interest::FromWire (packet);
-            return ReceiveInterest (interest);
-          }
-        case HeaderHelper::CONTENT_OBJECT_NDNSIM:
-          {
-            Ptr<ContentObject> data = wire::ndnSIM::Data::FromWire (packet);
-            return ReceiveData (data);
-          }
+          return ReceiveInterest (Wire::ToInterest (packet, Wire::WIRE_FORMAT_NDNSIM));
         case HeaderHelper::INTEREST_CCNB:
-          {
-            Ptr<Interest> interest = wire::ccnb::Interest::FromWire (packet);
-            return ReceiveInterest (interest);
-          }
+          return ReceiveInterest (Wire::ToInterest (packet, Wire::WIRE_FORMAT_CCNB));
+        case HeaderHelper::CONTENT_OBJECT_NDNSIM:
+          return ReceiveData (Wire::ToData (packet, Wire::WIRE_FORMAT_NDNSIM));
         case HeaderHelper::CONTENT_OBJECT_CCNB:
-          {
-            Ptr<ContentObject> data = wire::ccnb::Data::FromWire (packet);
-            return ReceiveData (data);
-          }
+          return ReceiveData (Wire::ToData (packet, Wire::WIRE_FORMAT_CCNB));
         }
 
       // exception will be thrown if packet is not recognized
     }
   catch (UnknownHeaderException)
     {
-      NS_ASSERT_MSG (false, "Unknown NDN header. Should not happen");
-      NS_LOG_ERROR ("Unknown NDN header. Should not happen");
+      NS_FATAL_ERROR ("Unknown NDN header. Should not happen");
       return false;
     }
 }
@@ -313,56 +272,6 @@
   return os;
 }
 
-uint32_t
-Face::NameToWireSize (Ptr<Name> name) const
-{
-  if (m_wireFormat == WIRE_FORMAT_NDNSIM)
-    return wire::NdnSim::SerializedSizeName (*name);
-  else if (m_wireFormat == WIRE_FORMAT_CCNB)
-    return wire::Ccnb::SerializedSizeName (*name);
-  else
-    {
-      NS_FATAL_ERROR ("Unsupported format requested");
-    }
-  return 0;
-}
-  
-/**
- * @brief Convert name to wire format
- */
-void
-Face::NameToWire (Buffer::Iterator start, Ptr<const Name> name) const
-{
-  if (m_wireFormat == WIRE_FORMAT_NDNSIM)
-    wire::NdnSim::SerializedSizeName (*name);
-  else if (m_wireFormat == WIRE_FORMAT_CCNB)
-    wire::Ccnb::SerializedSizeName (*name);
-  else
-    {
-      NS_FATAL_ERROR ("Unsupported format requested");
-    }
-}
-
-/**
- * @brief Convert name from wire format
- */
-Ptr<Name>
-Face::NameFromWire (Buffer::Iterator start) const
-{
-  if (m_wireFormat == WIRE_FORMAT_NDNSIM)
-    return wire::NdnSim::DeserializeName (start);
-  else if (m_wireFormat == WIRE_FORMAT_CCNB)
-    {
-      return wire::Ccnb::DeserializeName (start);
-    }
-  else
-    {
-      NS_FATAL_ERROR ("Unsupported format requested");
-    }
-  return 0;
-}
-
-
 } // namespace ndn
 } // namespace ns3
 
diff --git a/model/ndn-face.h b/model/ndn-face.h
index 86003ff..1fdc7f0 100644
--- a/model/ndn-face.h
+++ b/model/ndn-face.h
@@ -59,12 +59,6 @@
     public Object
 {
 public:
-  enum
-    {
-      WIRE_FORMAT_NDNSIM = 0,
-      WIRE_FORMAT_CCNB = 1
-    };
-
   static TypeId
   GetTypeId ();
 
@@ -248,27 +242,6 @@
   bool
   operator< (const Face &face) const;
 
-  ///////////////////////////////////////////////////////////////////////////////
-  // Helpers to create wire-formatted data in default wire format, since settings about
-  // the wire format belong to the face
-  /*
-   * @brief Get size of buffer to fit wire-formatted name object
-   */
-  uint32_t
-  NameToWireSize (Ptr<Name> name) const;
-  
-  /**
-   * @brief Convert name to wire format
-   */
-  void
-  NameToWire (Buffer::Iterator start, Ptr<const Name> name) const;
-
-  /**
-   * @brief Convert name from wire format
-   */
-  Ptr<Name>
-  NameFromWire (Buffer::Iterator start) const;
-  
 protected:
   /**
    * @brief Send packet down to the stack (towards app or network)
@@ -296,8 +269,6 @@
   Ptr<Node> m_node; ///< \brief Smart pointer to Node
 
 private:
-  uint32_t m_wireFormat;
-
   InterestHandler m_upstreamInterestHandler;
   DataHandler m_upstreamDataHandler;
   bool m_ifup;
diff --git a/model/ndn-interest.cc b/model/ndn-interest.cc
index 7364701..5d76362 100644
--- a/model/ndn-interest.cc
+++ b/model/ndn-interest.cc
@@ -53,17 +53,7 @@
   , m_payload          (interest.GetPayload ()->Copy ())
   , m_wire             (0)
 {
-}
-
-Interest::Interest (Ptr<const Interest> interest)
-  : m_name             (Create<Name> (interest->GetName ()))
-  , m_scope            (interest->m_scope)
-  , m_interestLifetime (interest->m_interestLifetime)
-  , m_nonce            (interest->m_nonce)
-  , m_nackType         (interest->m_nackType)
-  , m_payload          (interest->GetPayload ()->Copy ())
-  , m_wire             (0)
-{
+  NS_LOG_FUNCTION ("correct copy constructor");
 }
 
 void
diff --git a/model/ndn-interest.h b/model/ndn-interest.h
index 050cc9f..d0959a9 100644
--- a/model/ndn-interest.h
+++ b/model/ndn-interest.h
@@ -55,11 +55,6 @@
   Interest (const Interest &interest);
 
   /**
-   * @brief Another version of copy constructor
-   */
-  Interest (Ptr<const Interest> interest);  
-
-  /**
    * \brief Set interest name
    *
    * @param name smart pointer to Name
diff --git a/model/wire/ndn-wire.cc b/model/wire/ndn-wire.cc
new file mode 100644
index 0000000..6b50340
--- /dev/null
+++ b/model/wire/ndn-wire.cc
@@ -0,0 +1,228 @@
+/** -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/* 
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ * 
+ * GNU 3.0 license, See the LICENSE file for more information
+ * 
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#include "ndn-wire.h"
+
+#include "ns3/global-value.h"
+#include "ns3/integer.h"
+#include "ns3/ndn-common.h"
+#include "ns3/ndn-interest.h"
+#include "ns3/ndn-content-object.h"
+#include "ns3/ndn-header-helper.h"
+
+#include "ndnsim.h"
+#include "ndnsim/wire-ndnsim.h"
+#include "ccnb.h"
+#include "ccnb/wire-ccnb.h"
+
+NDN_NAMESPACE_BEGIN
+
+static
+GlobalValue g_wireFormat ("ndn::WireFormat", 
+                          "Default wire format for ndnSIM.  ndnSIM will be accepting packets "
+                          "in any supported packet formats, but if encoding requested, it will "
+                          "use default wire format to encode (0 for ndnSIM (default), 1 for CCNb)",
+                          IntegerValue (Wire::WIRE_FORMAT_NDNSIM),
+                          MakeIntegerChecker<int32_t> ());
+
+static inline uint32_t
+GetWireFormat ()
+{
+  static int32_t format = -1;
+  if (format >= 0)
+    return format;
+
+  IntegerValue value;
+  g_wireFormat.GetValue (value);
+  format = value.Get ();
+
+  return format;
+}
+
+Ptr<Packet>
+Wire::FromInterest (Ptr<const Interest> interest, int8_t wireFormat/* = WIRE_FORMAT_DEFAULT*/)
+{
+  if (wireFormat == WIRE_FORMAT_DEFAULT)
+    wireFormat = GetWireFormat ();
+    
+  if (wireFormat == WIRE_FORMAT_NDNSIM)
+    return wire::ndnSIM::Interest::ToWire (interest);
+  else if (wireFormat == WIRE_FORMAT_CCNB)
+    return wire::ccnb::Interest::ToWire (interest);
+  else
+    {
+      NS_FATAL_ERROR ("Unsupported format requested");
+      return 0;
+    }
+}
+
+Ptr<Interest>
+Wire::ToInterest (Ptr<Packet> packet, int8_t wireFormat/* = WIRE_FORMAT_AUTODETECT*/)
+{
+  if (wireFormat == WIRE_FORMAT_AUTODETECT)
+    {
+      try
+        {
+          HeaderHelper::Type type = HeaderHelper::GetNdnHeaderType (packet);
+          switch (type)
+            {
+            case HeaderHelper::INTEREST_NDNSIM:
+              {
+                return wire::ndnSIM::Interest::FromWire (packet);
+              }
+            case HeaderHelper::INTEREST_CCNB:
+              {
+                return wire::ccnb::Interest::FromWire (packet);
+              }
+            case HeaderHelper::CONTENT_OBJECT_NDNSIM:
+            case HeaderHelper::CONTENT_OBJECT_CCNB:
+              NS_FATAL_ERROR ("Data packet supplied for InterestFromWire function");
+              break;
+            }
+
+          // exception will be thrown if packet is not recognized
+        }
+      catch (UnknownHeaderException)
+        {
+          NS_FATAL_ERROR ("Unknown NDN header");
+          return 0;
+        }
+    }
+  else
+    {
+      if (wireFormat == WIRE_FORMAT_NDNSIM)
+        return wire::ndnSIM::Interest::FromWire (packet);
+      else if (wireFormat == WIRE_FORMAT_CCNB)
+        return wire::ccnb::Interest::FromWire (packet);
+      else
+        {
+          NS_FATAL_ERROR ("Unsupported format requested");
+          return 0;
+        }
+    }
+}
+
+Ptr<Packet>
+Wire::FromData (Ptr<const ContentObject> data, int8_t wireFormat/* = WIRE_FORMAT_DEFAULT*/)
+{
+  if (wireFormat == WIRE_FORMAT_DEFAULT)
+    wireFormat = GetWireFormat ();
+
+  if (wireFormat == WIRE_FORMAT_NDNSIM)
+    return wire::ndnSIM::Data::ToWire (data);
+  else if (wireFormat == WIRE_FORMAT_CCNB)
+    return wire::ccnb::Data::ToWire (data);
+  else
+    {
+      NS_FATAL_ERROR ("Unsupported format requested");
+      return 0;
+    }
+}
+
+Ptr<ContentObject>
+Wire::ToData (Ptr<Packet> packet, int8_t wireFormat/* = WIRE_FORMAT_AUTODETECT*/)
+{
+  if (wireFormat == WIRE_FORMAT_AUTODETECT)
+    {
+      try
+        {
+          HeaderHelper::Type type = HeaderHelper::GetNdnHeaderType (packet);
+          switch (type)
+            {
+            case HeaderHelper::CONTENT_OBJECT_NDNSIM:
+              {
+                return wire::ndnSIM::Data::FromWire (packet);
+              }
+            case HeaderHelper::CONTENT_OBJECT_CCNB:
+              {
+                return wire::ccnb::Data::FromWire (packet);
+              }
+            case HeaderHelper::INTEREST_NDNSIM:
+            case HeaderHelper::INTEREST_CCNB:
+              NS_FATAL_ERROR ("Interest supplied for DataFromWire function");
+              break;
+            }
+
+          // exception will be thrown if packet is not recognized
+        }
+      catch (UnknownHeaderException)
+        {
+          NS_FATAL_ERROR ("Unknown NDN header");
+          return 0;
+        }
+    }
+  else
+    {
+      if (wireFormat == WIRE_FORMAT_NDNSIM)
+        return wire::ndnSIM::Data::FromWire (packet);
+      else if (wireFormat == WIRE_FORMAT_CCNB)
+        return wire::ccnb::Data::FromWire (packet);
+      else
+        {
+          NS_FATAL_ERROR ("Unsupported format requested");
+          return 0;
+        }
+    }
+}
+
+
+uint32_t
+Wire::FromNameSize (Ptr<const Name> name, int8_t wireFormat/* = WIRE_FORMAT_DEFAULT*/)
+{
+  if (wireFormat == WIRE_FORMAT_DEFAULT)
+    wireFormat = GetWireFormat ();
+
+  if (wireFormat == WIRE_FORMAT_NDNSIM)
+    return wire::NdnSim::SerializedSizeName (*name);
+  else if (wireFormat == WIRE_FORMAT_CCNB)
+    return wire::Ccnb::SerializedSizeName (*name);
+  else
+    {
+      NS_FATAL_ERROR ("Unsupported format requested");
+      return 0;
+    }
+}
+  
+void
+Wire::FromName (Buffer::Iterator start, Ptr<const Name> name, int8_t wireFormat/* = WIRE_FORMAT_DEFAULT*/)
+{
+  if (wireFormat == WIRE_FORMAT_DEFAULT)
+    wireFormat = GetWireFormat ();
+
+  if (wireFormat == WIRE_FORMAT_NDNSIM)
+    wire::NdnSim::SerializedSizeName (*name);
+  else if (wireFormat == WIRE_FORMAT_CCNB)
+    wire::Ccnb::SerializedSizeName (*name);
+  else
+    {
+      NS_FATAL_ERROR ("Unsupported format requested");
+    }
+}
+
+Ptr<Name>
+Wire::ToName (Buffer::Iterator start, int8_t wireFormat/* = WIRE_FORMAT_DEFAULT*/)
+{
+  if (wireFormat == WIRE_FORMAT_DEFAULT)
+    wireFormat = GetWireFormat ();
+
+  if (wireFormat == WIRE_FORMAT_NDNSIM)
+    return wire::NdnSim::DeserializeName (start);
+  else if (wireFormat == WIRE_FORMAT_CCNB)
+    {
+      return wire::Ccnb::DeserializeName (start);
+      return 0;
+    }
+  else
+    {
+      NS_FATAL_ERROR ("Unsupported format requested");
+    }
+}
+
+NDN_NAMESPACE_END
diff --git a/model/wire/ndn-wire.h b/model/wire/ndn-wire.h
new file mode 100644
index 0000000..e83c217
--- /dev/null
+++ b/model/wire/ndn-wire.h
@@ -0,0 +1,67 @@
+/** -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil -*- */
+/* 
+ * Copyright (c) 2013, Regents of the University of California
+ *                     Alexander Afanasyev
+ * 
+ * GNU 3.0 license, See the LICENSE file for more information
+ * 
+ * Author: Alexander Afanasyev <alexander.afanasyev@ucla.edu>
+ */
+
+#ifndef NDN_WIRE_H
+#define NDN_WIRE_H
+
+#include "ns3/buffer.h"
+
+#include "ns3/ndn-common.h"
+#include "ns3/ndn-name.h"
+#include "ns3/ndn-interest.h"
+#include "ns3/ndn-content-object.h"
+
+NDN_NAMESPACE_BEGIN
+
+struct Wire
+{
+  enum
+    {
+      WIRE_FORMAT_DEFAULT = -2,
+      WIRE_FORMAT_AUTODETECT = -1,
+    
+      WIRE_FORMAT_NDNSIM = 0,
+      WIRE_FORMAT_CCNB = 1
+    };
+
+  static Ptr<Packet>
+  FromInterest (Ptr<const Interest> interest, int8_t wireFormat = WIRE_FORMAT_DEFAULT);
+
+  static Ptr<Interest>
+  ToInterest (Ptr<Packet> packet, int8_t type = WIRE_FORMAT_AUTODETECT);
+
+  static Ptr<Packet>
+  FromData (Ptr<const ContentObject> data, int8_t wireFormat = WIRE_FORMAT_DEFAULT);
+
+  static Ptr<ContentObject>
+  ToData (Ptr<Packet> packet, int8_t type = WIRE_FORMAT_AUTODETECT);
+
+  /*
+   * @brief Get size of buffer to fit wire-formatted name object
+   */
+  static uint32_t
+  FromNameSize (Ptr<const Name> name, int8_t wireFormat = WIRE_FORMAT_DEFAULT);
+  
+  /**
+   * @brief Convert name to wire format
+   */
+  static void
+  FromName (Buffer::Iterator start, Ptr<const Name> name, int8_t wireFormat = WIRE_FORMAT_DEFAULT);
+
+  /**
+   * @brief Convert name from wire format
+   */
+  static Ptr<Name>
+  ToName (Buffer::Iterator start, int8_t wireFormat = WIRE_FORMAT_DEFAULT);
+};
+
+NDN_NAMESPACE_END
+
+#endif // NDN_WIRE_H
diff --git a/wscript b/wscript
index b33da18..ff2b7f3 100644
--- a/wscript
+++ b/wscript
@@ -150,8 +150,7 @@
         "model/fw/ndn-forwarding-strategy.h",
         "model/fw/ndn-fw-tag.h",
 
-        "model/wire/ndnsim.h",
-        "model/wire/ccnb.h",
+        "model/wire/ndn-wire.h",
 
         "utils/ndn-limits.h",
         "utils/ndn-rtt-estimator.h",