Merge branch 'master' of git.irl.cs.ucla.edu:ndn/sync
diff --git a/include/sync-logic.h b/include/sync-logic.h
index 551cb06..5e32918 100644
--- a/include/sync-logic.h
+++ b/include/sync-logic.h
@@ -101,7 +101,7 @@
    * @param name the data name
    * @param dataBuffer the sync data
    */
-  void respondSyncData (const std::string &name, const std::string &dataBuffer);
+  void respondSyncData (const std::string &name, const char *wireData, size_t len);
 
   /**
    * @brief remove a participant's subtree from the sync tree
@@ -133,7 +133,7 @@
 
   void
   processSyncData (const std::string &name,
-                   DigestConstPtr digest, const std::string &dataBuffer);
+                   DigestConstPtr digest, const char *wireData, size_t len);
   
   void
   processSyncRecoveryInterest (const std::string &name,
diff --git a/include/sync-state.h b/include/sync-state.h
index 826e84d..84c2400 100644
--- a/include/sync-state.h
+++ b/include/sync-state.h
@@ -26,6 +26,7 @@
 #include "sync-state-leaf-container.h"
 #include <boost/exception/all.hpp>
 #include "boost/tuple/tuple.hpp"
+#include "sync-state.pb.h"
 
 /**
  * \defgroup sync SYNC protocol
@@ -74,29 +75,31 @@
   LeafContainer m_leaves;
 };
 
-/**
- * @brief Formats an XML representation of the state
- * @param os output stream
- * @param state state
- * @returns output stream
- */
-std::ostream &
-operator << (std::ostream &os, const State &state);
 
 /**
- * @brief Parses an XML representation to the state
- * @param in input data stream
+ * @brief Formats a protobuf SyncStateMsg msg
+ * @param oss output SyncStateMsg msg
  * @param state state
- * @returns input stream
+ * @returns output SyncStateMsg msg
  */
-std::istream &
-operator >> (std::istream &in, State &state);
+SyncStateMsg &
+operator << (SyncStateMsg &ossm, const State &state);
+
+
+/**
+ * @brief Parse a protobuf SyncStateMsg msg
+ * @param iss input SyncStateMsg msg
+ * @param state state
+ * @returns SyncStateMsg msg
+ */
+SyncStateMsg &
+operator >> (SyncStateMsg &issm, State &state);
 
 namespace Error {
 /**
- * @brief Will be thrown when XML cannot be properly decoded to State
+ * @brief Will be thrown when data cannot be properly decoded to SyncStateMsg
  */
-struct SyncXmlDecodingFailure : virtual boost::exception, virtual std::exception { };
+struct SyncStateMsgDecodingFailure : virtual boost::exception, virtual std::exception { };
 }
 
 } // Sync
diff --git a/model/sync-logic.cc b/model/sync-logic.cc
index 860f119..b72a061 100644
--- a/model/sync-logic.cc
+++ b/model/sync-logic.cc
@@ -29,6 +29,7 @@
 #include "sync-diff-leaf.h"
 #include "sync-full-leaf.h"
 #include "sync-log.h"
+#include "sync-state.h"
 
 #include <boost/make_shared.hpp>
 #include <boost/foreach.hpp>
@@ -178,7 +179,7 @@
 }
 
 void
-SyncLogic::respondSyncData (const std::string &name, const std::string &dataBuffer)
+SyncLogic::respondSyncData (const std::string &name, const char *wireData, size_t len)
 {
   try
     {
@@ -190,13 +191,13 @@
 
       if (type == "normal")
         {
-          processSyncData (name, digest, dataBuffer);
+          processSyncData (name, digest, wireData, len);
         }
       else
         {
           // timer is always restarted when we schedule recovery
           m_scheduler.cancel (REEXPRESSING_RECOVERY_INTEREST);
-          processSyncData (name, digest, dataBuffer);
+          processSyncData (name, digest, wireData, len);
         }
     }
   catch (Error::DigestCalculationError &e)
@@ -263,7 +264,7 @@
 }
 
 void
-SyncLogic::processSyncData (const std::string &name, DigestConstPtr digest, const string &dataBuffer)
+SyncLogic::processSyncData (const std::string &name, DigestConstPtr digest, const char *wireData, size_t len)
 {
   DiffStatePtr diffLog = make_shared<DiffState> ();
   bool ownInterestSatisfied = false;
@@ -277,8 +278,14 @@
       ownInterestSatisfied = (name == m_outstandingInterestName);
 
       DiffState diff;
-      istringstream ss (dataBuffer);
-      ss >> diff;
+      SyncStateMsg msg;
+      if (!msg.ParseFromArray(wireData, len) || !msg.IsInitialized()) 
+      {
+        //Throw
+        BOOST_THROW_EXCEPTION (Error::SyncStateMsgDecodingFailure () );
+      }
+      msg >> diff;
+
       vector<MissingDataInfo> v;
       BOOST_FOREACH (LeafConstPtr leaf, diff.getLeaves().get<ordered>())
         {
@@ -332,7 +339,7 @@
 
       insertToDiffLog (diffLog);
     }
-  catch (Error::SyncXmlDecodingFailure &e)
+  catch (Error::SyncStateMsgDecodingFailure &e)
     {
       _LOG_TRACE ("Something really fishy happened during state decoding " <<
                   diagnostic_information (e));
@@ -486,8 +493,8 @@
                         bind (&SyncLogic::sendSyncInterest, this),
                         REEXPRESSING_INTEREST);
   
-  m_ccnxHandle->sendInterestForString (os.str (),
-                              bind (&SyncLogic::respondSyncData, this, _1, _2));
+  m_ccnxHandle->sendInterest (os.str (),
+                              bind (&SyncLogic::respondSyncData, this, _1, _2, _3));
 }
 
 void
@@ -508,8 +515,8 @@
                             REEXPRESSING_RECOVERY_INTEREST);
     }
 
-  m_ccnxHandle->sendInterestForString (os.str (),
-                              bind (&SyncLogic::respondSyncData, this, _1, _2));
+  m_ccnxHandle->sendInterest (os.str (),
+                              bind (&SyncLogic::respondSyncData, this, _1, _2, _3));
 }
 
 
@@ -518,9 +525,16 @@
 {
   _LOG_TRACE (">> D " << name);
   // sending
-  m_ccnxHandle->publishStringData (name,
-                             lexical_cast<string> (*state),
+  SyncStateMsg ssm;
+  ssm << (*state);
+  int size = ssm.ByteSize();
+  char *wireData = new char[size];
+  ssm.SerializeToArray(wireData, size);
+  m_ccnxHandle->publishRawData (name,
+                             wireData,
+                             size,
                              m_syncResponseFreshness); // in NS-3 it doesn't have any effect... yet
+  delete wireData;
 
   // checking if our own interest got satisfied
   bool satisfiedOwnInterest = false;
diff --git a/model/sync-state.cc b/model/sync-state.cc
index f6db146..137e8b0 100644
--- a/model/sync-state.cc
+++ b/model/sync-state.cc
@@ -30,7 +30,6 @@
 #include <boost/throw_exception.hpp>
 #include <boost/lexical_cast.hpp>
 
-#define TIXML_USE_STL
 #include <tinyxml.h>
 
 using namespace std;
@@ -42,12 +41,7 @@
 
 namespace Sync {
 
-#ifdef _DEBUG
-#define DEBUG_ENDL os << "\n";
-#else
-#define DEBUG_ENDL
-#endif
-
+/*
 std::ostream &
 operator << (std::ostream &os, const State &state)
 {
@@ -73,7 +67,39 @@
     }
   os << "</state>";
 }
+*/
 
+SyncStateMsg &
+operator << (SyncStateMsg &ossm, const State &state)
+{
+  BOOST_FOREACH (shared_ptr<const Leaf> leaf, state.getLeaves ().get<ordered> ())
+  {
+    SyncState *oss = ossm.add_ss();
+    shared_ptr<const DiffLeaf> diffLeaf = dynamic_pointer_cast<const DiffLeaf> (leaf);
+    if (diffLeaf != 0 && diffLeaf->getOperation() != UPDATE)
+    {
+      oss->set_type(SyncState::DELETE);
+    }
+    else
+    {
+      oss->set_type(SyncState::UPDATE);
+    }
+
+    std::ostringstream os;
+    os << *leaf->getInfo();
+    oss->set_name(os.str());
+
+    if (diffLeaf == 0 || (diffLeaf != 0 && diffLeaf->getOperation () == UPDATE))
+    {
+      SyncState::SeqNo *seqNo = oss->mutable_seqno();
+      seqNo->set_session(leaf->getSeq().getSession());
+      seqNo->set_seq(leaf->getSeq().getSeq());
+    }
+  }
+  return ossm;
+}
+
+/*
 std::istream &
 operator >> (std::istream &in, State &state)
 {
@@ -120,5 +146,29 @@
 
   return in;
 }
+*/
+
+SyncStateMsg &
+operator >> (SyncStateMsg &issm, State &state)
+{
+  int n = issm.ss_size();
+  for (int i = 0; i < n; i++)
+  {
+    const SyncState &ss = issm.ss(i);
+    NameInfoConstPtr info = StdNameInfo::FindOrCreate (ss.name());
+    if (ss.type() == SyncState::UPDATE)
+    {
+      uint32_t session = lexical_cast<uint32_t>(ss.seqno().session());
+      uint32_t seq = lexical_cast<uint32_t>(ss.seqno().seq());
+      SeqNo seqNo(session, seq);
+      state.update(info, seqNo);
+    }
+    else
+    {
+      state.remove(info);
+    }
+  }
+  return issm;
+}
 
 }
diff --git a/sync-state.proto b/sync-state.proto
new file mode 100644
index 0000000..18892fb
--- /dev/null
+++ b/sync-state.proto
@@ -0,0 +1,24 @@
+package Sync;
+
+message SyncState
+{
+  required string name = 1;
+  enum ActionType
+  {
+    UPDATE = 0;
+    DELETE = 1;
+    OTHER = 2;
+  }
+  required ActionType type = 2;
+  message SeqNo
+  {
+    required uint32 seq = 1;
+    required uint32 session = 2;
+  }
+  optional SeqNo seqno = 3;
+}
+
+message SyncStateMsg
+{
+  repeated SyncState ss = 1;
+}
diff --git a/test/test_app_socket.cc b/test/test_app_socket.cc
index df3a3a8..473d117 100644
--- a/test/test_app_socket.cc
+++ b/test/test_app_socket.cc
@@ -211,7 +211,7 @@
   s4.publishRaw(p4, 0,(const char *) num, sizeof(num), 10);
   a1.setNum(p4, (const char *) num, sizeof (num));
 
-  this_thread::sleep (posix_time::milliseconds (200));
+  this_thread::sleep (posix_time::milliseconds (1000));
   BOOST_CHECK(a1.sum == a2.sum && a1.sum == 10);
 
   int newNum[5] = {9, 7, 2, 1, 1};
diff --git a/test/test_state.cc b/test/test_state.cc.outdated
similarity index 100%
rename from test/test_state.cc
rename to test/test_state.cc.outdated
diff --git a/waf-tools/protobuf.py b/waf-tools/protobuf.py
new file mode 100644
index 0000000..71d8bdf
--- /dev/null
+++ b/waf-tools/protobuf.py
@@ -0,0 +1,76 @@
+#! /usr/bin/env python
+# encoding: utf-8
+
+'''
+
+When using this tool, the wscript will look like:
+
+	def options(opt):
+	        opt.tool_options('protobuf', tooldir=["waf-tools"])
+
+	def configure(conf):
+		conf.load('compiler_cxx protobuf')
+
+	def build(bld):
+		bld(source='main.cpp', target='app', use='PROTOBUF')
+
+Options are generated, in order to specify the location of protobuf includes/libraries.
+
+
+'''
+import sys
+import re
+from waflib import Utils,Logs,Errors
+from waflib.Configure import conf
+PROTOBUF_DIR=['/usr','/usr/local','/opt/local','/sw']
+PROTOBUF_VERSION_FILE='google/protobuf/stubs/common.h'
+PROTOBUF_VERSION_CODE='''
+#include <iostream>
+#include <google/protobuf/stubs/common.h>
+int main() { std::cout << GOOGLE_PROTOBUF_VERSION ;}
+'''
+
+def options(opt):
+	opt.add_option('--protobuf',type='string',default='',dest='protobuf_dir',help='''path to where protobuf is installed, e.g. /usr/local''')
+@conf
+def __protobuf_get_version_file(self,dir):
+	try:
+		return self.root.find_dir(dir).find_node('%s/%s' % ('include', PROTOBUF_VERSION_FILE))
+	except:
+		return None
+@conf
+def protobuf_get_version(self,dir):
+	val=self.check_cxx(fragment=PROTOBUF_VERSION_CODE,includes=['%s/%s' % (dir, 'include')], execute=True, define_ret = True, mandatory=True)
+	return val
+@conf
+def protobuf_get_root(self,*k,**kw):
+	root=k and k[0]or kw.get('path',None)
+	# Logs.pprint ('RED', '   %s' %root)
+	if root and self.__protobuf_get_version_file(root):
+		return root
+	for dir in PROTOBUF_DIR:
+		if self.__protobuf_get_version_file(dir):
+			return dir
+	if root:
+		self.fatal('Protobuf not found in %s'%root)
+	else:
+		self.fatal('Protobuf not found, please provide a --protobuf argument (see help)')
+@conf
+def check_protobuf(self,*k,**kw):
+	if not self.env['CXX']:
+		self.fatal('load a c++ compiler first, conf.load("compiler_cxx")')
+
+	var=kw.get('uselib_store','PROTOBUF')
+	self.start_msg('Checking Protocol Buffer')
+	root = self.protobuf_get_root(*k,**kw);
+	self.env.PROTOBUF_VERSION=self.protobuf_get_version(root)
+
+	self.env['INCLUDES_%s'%var]= '%s/%s' % (root, "include");
+	self.env['LIB_%s'%var] = "protobuf"
+	self.env['LIBPATH_%s'%var] = '%s/%s' % (root, "lib")
+
+	self.end_msg(self.env.PROTOBUF_VERSION)
+	if Logs.verbose:
+		Logs.pprint('CYAN','	Protocol Buffer include : %s'%self.env['INCLUDES_%s'%var])
+		Logs.pprint('CYAN','	Protocol Buffer lib     : %s'%self.env['LIB_%s'%var])
+		Logs.pprint('CYAN','	Protocol Buffer libpath : %s'%self.env['LIBPATH_%s'%var])
diff --git a/waf-tools/tinyxml.py b/waf-tools/tinyxml.py
deleted file mode 100644
index 3908b38..0000000
--- a/waf-tools/tinyxml.py
+++ /dev/null
@@ -1,76 +0,0 @@
-#! /usr/bin/env python
-# encoding: utf-8
-
-'''
-
-When using this tool, the wscript will look like:
-
-	def options(opt):
-	        opt.tool_options('tinyxml', tooldir=["waf-tools"])
-
-	def configure(conf):
-		conf.load('compiler_cxx tiny')
-
-	def build(bld):
-		bld(source='main.cpp', target='app', use='TINYXML')
-
-Options are generated, in order to specify the location of tinyxml includes/libraries.
-
-
-'''
-import sys
-import re
-from waflib import Utils,Logs,Errors
-from waflib.Configure import conf
-TINYXML_DIR=['/usr','/usr/local','/opt/local','/sw']
-TINYXML_VERSION_FILE='tinyxml.h'
-TINYXML_VERSION_CODE='''
-#include <iostream>
-#include <tinyxml.h>
-int main() { std::cout << TIXML_MAJOR_VERSION << "." << TIXML_MINOR_VERSION << "." << TIXML_PATCH_VERSION; }
-'''
-
-def options(opt):
-	opt.add_option('--tinyxml',type='string',default='',dest='tinyxml_dir',help='''path to where TinyXML is installed, e.g. /usr/local''')
-@conf
-def __tinyxml_get_version_file(self,dir):
-	try:
-		return self.root.find_dir(dir).find_node('%s/%s' % ('include', TINYXML_VERSION_FILE))
-	except:
-		return None
-@conf
-def tinyxml_get_version(self,dir):
-	val=self.check_cxx(fragment=TINYXML_VERSION_CODE,includes=['%s/%s' % (dir, 'include')], execute=True, define_ret = True, mandatory=True)
-	return val
-@conf
-def tinyxml_get_root(self,*k,**kw):
-	root=k and k[0]or kw.get('path',None)
-	# Logs.pprint ('RED', '   %s' %root)
-	if root and self.__tinyxml_get_version_file(root):
-		return root
-	for dir in TINYXML_DIR:
-		if self.__tinyxml_get_version_file(dir):
-			return dir
-	if root:
-		self.fatal('TinyXML not found in %s'%root)
-	else:
-		self.fatal('TinyXML not found, please provide a --tinyxml argument (see help)')
-@conf
-def check_tinyxml(self,*k,**kw):
-	if not self.env['CXX']:
-		self.fatal('load a c++ compiler first, conf.load("compiler_cxx")')
-
-	var=kw.get('uselib_store','TINYXML')
-	self.start_msg('Checking TinyXML')
-	root = self.tinyxml_get_root(*k,**kw);
-	self.env.TINYXML_VERSION=self.tinyxml_get_version(root)
-
-	self.env['INCLUDES_%s'%var]= '%s/%s' % (root, "include");
-	self.env['LIB_%s'%var] = "tinyxml"
-	self.env['LIBPATH_%s'%var] = '%s/%s' % (root, "lib")
-
-	self.end_msg(self.env.TINYXML_VERSION)
-	if Logs.verbose:
-		Logs.pprint('CYAN','	TinyXML include : %s'%self.env['INCLUDES_%s'%var])
-		Logs.pprint('CYAN','	TinyXML lib     : %s'%self.env['LIB_%s'%var])
-		Logs.pprint('CYAN','	TinyXML libpath : %s'%self.env['LIBPATH_%s'%var])
diff --git a/wscript b/wscript
index df97940..c87bf89 100644
--- a/wscript
+++ b/wscript
@@ -13,7 +13,7 @@
     opt.load('compiler_cxx')
     opt.load('boost')
     opt.load('doxygen')
-    opt.load('ccnx tinyxml ns3', tooldir=["waf-tools"])
+    opt.load('ccnx protobuf ns3', tooldir=["waf-tools"])
 
 def configure(conf):
     conf.load("compiler_cxx")
@@ -61,10 +61,18 @@
     except:
         pass
 
-    conf.load('tinyxml')
-    conf.check_tinyxml ()
+    conf.load('protobuf')
+    conf.check_protobuf (path=conf.options.protobuf_dir)
                    
+
+def pre(bld):
+  bld.exec_command('protoc --cpp_out=. sync-state.proto')
+  bld.exec_command('mv sync-state.pb.h include/')
+  bld.exec_command('mv sync-state.pb.cc model/')
+
 def build (bld):
+    bld.add_pre_fun(pre)
+
     if bld.get_define ("NS3_MODULE"):
         sync_ns3 = bld.shlib (
             target = "sync-ns3",
@@ -91,8 +99,9 @@
                 'model/sync-seq-no.cc',
                 'model/sync-state.cc',
                 'model/sync-std-name-info.cc',
+                'model/sync-state.pb.cc',
                 ],
-            use = 'BOOST BOOST_IOSTREAMS SSL TINYXML ' + ' '.join (['ns3_'+dep for dep in ['core', 'network', 'internet', 'NDNabstraction']]).upper (),
+            use = 'BOOST BOOST_IOSTREAMS SSL PROTOBUF ' + ' '.join (['ns3_'+dep for dep in ['core', 'network', 'internet', 'NDNabstraction']]).upper (),
             includes = ['include', 'include/ns3', 'helper'],
             )
 
@@ -139,8 +148,9 @@
                 'model/sync-seq-no.cc',
                 'model/sync-state.cc',
                 'model/sync-std-name-info.cc',
+                'model/sync-state.pb.cc',
                 ],
-            use = 'BOOST BOOST_IOSTREAMS BOOST_THREAD SSL TINYXML CCNX',
+            use = 'BOOST BOOST_IOSTREAMS BOOST_THREAD SSL PROTOBUF CCNX',
             includes = ['include', 'helper'],
             )