Nikhil Marathe avatar Nikhil Marathe committed afb45bc

Initial import

Comments (0)

Files changed (15)

+ENABLE_TESTING ()
+Project ( ddm )
+
+Find_Package ( CURL REQUIRED )
+execute_process ( COMMAND make WORKING_DIRECTORY ${ddm_SOURCE_DIR}/lib/Sockets-2.3.6 )
+
+include_directories ( ${ddm_SOURCE_DIR}/lib/Sockets-2.3.6 )
+link_directories ( ${ddm_SOURCE_DIR}/lib/Sockets-2.3.6 )
+
+set ( CORE_LIBS ddm curl protobuf Sockets )
+
+add_subdirectory ( lib )
+add_subdirectory ( src )
+
+add_subdirectory ( tests )

src/CMakeLists.txt

+include_directories( ${ddm_SOURCE_DIR}/lib/Sockets-2.3.6 )
+link_directories( ${ddm_SOURCE_DIR}/lib/Sockets-2.3.6 )
+
+set ( PROTOBUF_SRC ddm.proto )
+
+execute_process ( COMMAND protoc --cpp_out=. ${PROTOBUF_SRC} WORKING_DIRECTORY ${ddm_SOURCE_DIR}/src )
+
+set ( ddm_SRCS
+    ddm.cpp
+    job.cpp
+)
+
+add_library ( ddm SHARED ${ddm_SRCS} )
+#include <iostream>
+
+#include <curl/curl.h>
+
+#include "ddm.h"
+#include "ddm.pb.h"
+
+using namespace std;
+
+namespace ddm
+{
+/**
+  * Initializes DDM
+  * Starts listening on port `port` and sends out a HELLO
+  * @param port The port to listen on
+  */
+bool DDM::init( int port )
+{
+    if( curl_global_init( CURL_GLOBAL_ALL ) != 0 )
+    {
+        cerr << "Error initializing libcurl\n";
+        return false;
+    }
+
+    GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+    startListening( port );
+    return true;
+}
+
+bool DDM::cleanup()
+{
+    curl_global_cleanup();
+    return true;
+}
+
+void DDM::startListening( int port )
+{
+}
+
+void DDM::addUrl( std::string url )
+{
+}
+}
+
+#ifndef DDM_H
+#define DDM_H
+
+namespace ddm
+{
+class DDM
+{
+public:
+    bool init( int port = DEFAULT_PORT );
+    bool cleanup();
+
+    void addUrl( std::string url );
+
+private:
+    void startListening(int port);
+
+    void msgHello();
+    static const int DEFAULT_PORT = 2345;
+
+};
+
+}
+
+#endif
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+
+#define INTERNAL_SUPPRESS_PROTOBUF_FIELD_DEPRECATION
+#include "ddm.pb.h"
+#include <google/protobuf/stubs/once.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/reflection_ops.h>
+#include <google/protobuf/wire_format.h>
+
+namespace proto {
+
+namespace {
+
+const ::google::protobuf::Descriptor* Segment_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Segment_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Job_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Job_reflection_ = NULL;
+const ::google::protobuf::Descriptor* Packet_descriptor_ = NULL;
+const ::google::protobuf::internal::GeneratedMessageReflection*
+  Packet_reflection_ = NULL;
+const ::google::protobuf::EnumDescriptor* Packet_PacketType_descriptor_ = NULL;
+
+}  // namespace
+
+
+void protobuf_AssignDesc_ddm_2eproto() {
+  protobuf_AddDesc_ddm_2eproto();
+  const ::google::protobuf::FileDescriptor* file =
+    ::google::protobuf::DescriptorPool::generated_pool()->FindFileByName(
+      "ddm.proto");
+  GOOGLE_CHECK(file != NULL);
+  Segment_descriptor_ = file->message_type(0);
+  static const int Segment_offsets_[4] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Segment, index_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Segment, offset_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Segment, size_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Segment, data_),
+  };
+  Segment_reflection_ =
+    new ::google::protobuf::internal::GeneratedMessageReflection(
+      Segment_descriptor_,
+      Segment::default_instance_,
+      Segment_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Segment, _has_bits_[0]),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Segment, _unknown_fields_),
+      -1,
+      ::google::protobuf::DescriptorPool::generated_pool(),
+      ::google::protobuf::MessageFactory::generated_factory(),
+      sizeof(Segment));
+  Job_descriptor_ = file->message_type(1);
+  static const int Job_offsets_[2] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Job, url_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Job, segments_),
+  };
+  Job_reflection_ =
+    new ::google::protobuf::internal::GeneratedMessageReflection(
+      Job_descriptor_,
+      Job::default_instance_,
+      Job_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Job, _has_bits_[0]),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Job, _unknown_fields_),
+      -1,
+      ::google::protobuf::DescriptorPool::generated_pool(),
+      ::google::protobuf::MessageFactory::generated_factory(),
+      sizeof(Job));
+  Packet_descriptor_ = file->message_type(2);
+  static const int Packet_offsets_[3] = {
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Packet, command_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Packet, payload_),
+    GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Packet, job_),
+  };
+  Packet_reflection_ =
+    new ::google::protobuf::internal::GeneratedMessageReflection(
+      Packet_descriptor_,
+      Packet::default_instance_,
+      Packet_offsets_,
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Packet, _has_bits_[0]),
+      GOOGLE_PROTOBUF_GENERATED_MESSAGE_FIELD_OFFSET(Packet, _unknown_fields_),
+      -1,
+      ::google::protobuf::DescriptorPool::generated_pool(),
+      ::google::protobuf::MessageFactory::generated_factory(),
+      sizeof(Packet));
+  Packet_PacketType_descriptor_ = Packet_descriptor_->enum_type(0);
+}
+
+namespace {
+
+GOOGLE_PROTOBUF_DECLARE_ONCE(protobuf_AssignDescriptors_once_);
+inline void protobuf_AssignDescriptorsOnce() {
+  ::google::protobuf::GoogleOnceInit(&protobuf_AssignDescriptors_once_,
+                 &protobuf_AssignDesc_ddm_2eproto);
+}
+
+void protobuf_RegisterTypes(const ::std::string&) {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+    Segment_descriptor_, &Segment::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+    Job_descriptor_, &Job::default_instance());
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedMessage(
+    Packet_descriptor_, &Packet::default_instance());
+}
+
+}  // namespace
+
+void protobuf_ShutdownFile_ddm_2eproto() {
+  delete Segment::default_instance_;
+  delete Segment_reflection_;
+  delete Job::default_instance_;
+  delete Job_reflection_;
+  delete Packet::default_instance_;
+  delete Packet_reflection_;
+}
+
+void protobuf_AddDesc_ddm_2eproto() {
+  static bool already_here = false;
+  if (already_here) return;
+  already_here = true;
+  GOOGLE_PROTOBUF_VERIFY_VERSION;
+
+  ::google::protobuf::DescriptorPool::InternalAddGeneratedFile(
+    "\n\tddm.proto\022\005proto\"O\n\007Segment\022\r\n\005index\030\001"
+    " \002(\r\022\021\n\006offset\030\002 \002(\004:\0010\022\024\n\004size\030\003 \002(\004:\0065"
+    "24288\022\014\n\004data\030\004 \001(\014\"4\n\003Job\022\013\n\003url\030\001 \002(\t\022"
+    " \n\010segments\030\002 \003(\0132\016.proto.Segment\"\237\002\n\006Pa"
+    "cket\022/\n\007command\030\001 \002(\0162\030.proto.Packet.Pac"
+    "ketType:\004PING\022\017\n\007payload\030\002 \001(\014\022\027\n\003job\030\003 "
+    "\001(\0132\n.proto.Job\"\271\001\n\nPacketType\022\t\n\005HELLO\020"
+    "\000\022\007\n\003BYE\020\001\022\010\n\004PING\020\002\022\010\n\004PONG\020\003\022\r\n\tJOB_AD"
+    "DED\020\004\022\016\n\nJOB_ACCEPT\020\005\022\023\n\017SEGMENT_STARTED"
+    "\020\010\022\020\n\014SEGMENT_DONE\020\t\022\023\n\017SEGMENT_REQUEST\020"
+    "\n\022\013\n\007SEGMENT\020\013\022\016\n\nSEGMENT_OK\020\014\022\013\n\007WELCOM"
+    "E\020\r", 443);
+  ::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
+    "ddm.proto", &protobuf_RegisterTypes);
+  Segment::default_instance_ = new Segment();
+  Job::default_instance_ = new Job();
+  Packet::default_instance_ = new Packet();
+  Segment::default_instance_->InitAsDefaultInstance();
+  Job::default_instance_->InitAsDefaultInstance();
+  Packet::default_instance_->InitAsDefaultInstance();
+  ::google::protobuf::internal::OnShutdown(&protobuf_ShutdownFile_ddm_2eproto);
+}
+
+// Force AddDescriptors() to be called at static initialization time.
+struct StaticDescriptorInitializer_ddm_2eproto {
+  StaticDescriptorInitializer_ddm_2eproto() {
+    protobuf_AddDesc_ddm_2eproto();
+  }
+} static_descriptor_initializer_ddm_2eproto_;
+
+
+// ===================================================================
+
+const ::std::string Segment::_default_data_;
+#ifndef _MSC_VER
+const int Segment::kIndexFieldNumber;
+const int Segment::kOffsetFieldNumber;
+const int Segment::kSizeFieldNumber;
+const int Segment::kDataFieldNumber;
+#endif  // !_MSC_VER
+
+Segment::Segment() {
+  SharedCtor();
+}
+
+void Segment::InitAsDefaultInstance() {
+}
+
+Segment::Segment(const Segment& from) {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void Segment::SharedCtor() {
+  _cached_size_ = 0;
+  index_ = 0u;
+  offset_ = GOOGLE_ULONGLONG(0);
+  size_ = GOOGLE_ULONGLONG(524288);
+  data_ = const_cast< ::std::string*>(&_default_data_);
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+Segment::~Segment() {
+  SharedDtor();
+}
+
+void Segment::SharedDtor() {
+  if (data_ != &_default_data_) {
+    delete data_;
+  }
+  if (this != default_instance_) {
+  }
+}
+
+const ::google::protobuf::Descriptor* Segment::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Segment_descriptor_;
+}
+
+const Segment& Segment::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_ddm_2eproto();  return *default_instance_;
+}
+
+Segment* Segment::default_instance_ = NULL;
+
+Segment* Segment::New() const {
+  return new Segment;
+}
+
+void Segment::Clear() {
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    index_ = 0u;
+    offset_ = GOOGLE_ULONGLONG(0);
+    size_ = GOOGLE_ULONGLONG(524288);
+    if (_has_bit(3)) {
+      if (data_ != &_default_data_) {
+        data_->clear();
+      }
+    }
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->Clear();
+}
+
+bool Segment::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required uint32 index = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+          goto handle_uninterpreted;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::ReadUInt32(
+              input, &index_));
+        _set_bit(0);
+        if (input->ExpectTag(16)) goto parse_offset;
+        break;
+      }
+      
+      // required uint64 offset = 2 [default = 0];
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+          goto handle_uninterpreted;
+        }
+       parse_offset:
+        DO_(::google::protobuf::internal::WireFormatLite::ReadUInt64(
+              input, &offset_));
+        _set_bit(1);
+        if (input->ExpectTag(24)) goto parse_size;
+        break;
+      }
+      
+      // required uint64 size = 3 [default = 524288];
+      case 3: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+          goto handle_uninterpreted;
+        }
+       parse_size:
+        DO_(::google::protobuf::internal::WireFormatLite::ReadUInt64(
+              input, &size_));
+        _set_bit(2);
+        if (input->ExpectTag(34)) goto parse_data;
+        break;
+      }
+      
+      // optional bytes data = 4;
+      case 4: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+          goto handle_uninterpreted;
+        }
+       parse_data:
+        DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+              input, this->mutable_data()));
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void Segment::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
+  if (raw_buffer != NULL) {
+    Segment::SerializeWithCachedSizesToArray(raw_buffer);
+    return;
+  }
+  
+  // required uint32 index = 1;
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt32(1, this->index(), output);
+  }
+  
+  // required uint64 offset = 2 [default = 0];
+  if (_has_bit(1)) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(2, this->offset(), output);
+  }
+  
+  // required uint64 size = 3 [default = 524288];
+  if (_has_bit(2)) {
+    ::google::protobuf::internal::WireFormatLite::WriteUInt64(3, this->size(), output);
+  }
+  
+  // optional bytes data = 4;
+  if (_has_bit(3)) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytes(
+      4, this->data(), output);
+  }
+  
+  if (!unknown_fields().empty()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+}
+
+::google::protobuf::uint8* Segment::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // required uint32 index = 1;
+  if (_has_bit(0)) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt32ToArray(1, this->index(), target);
+  }
+  
+  // required uint64 offset = 2 [default = 0];
+  if (_has_bit(1)) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(2, this->offset(), target);
+  }
+  
+  // required uint64 size = 3 [default = 524288];
+  if (_has_bit(2)) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteUInt64ToArray(3, this->size(), target);
+  }
+  
+  // optional bytes data = 4;
+  if (_has_bit(3)) {
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
+        4, this->data(), target);
+  }
+  
+  if (!unknown_fields().empty()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  return target;
+}
+
+int Segment::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required uint32 index = 1;
+    if (has_index()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt32Size(
+          this->index());
+    }
+    
+    // required uint64 offset = 2 [default = 0];
+    if (has_offset()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt64Size(
+          this->offset());
+    }
+    
+    // required uint64 size = 3 [default = 524288];
+    if (has_size()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::UInt64Size(
+          this->size());
+    }
+    
+    // optional bytes data = 4;
+    if (has_data()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->data());
+    }
+    
+  }
+  if (!unknown_fields().empty()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  _cached_size_ = total_size;
+  return total_size;
+}
+
+void Segment::MergeFrom(const ::google::protobuf::Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  const Segment* source =
+    ::google::protobuf::internal::dynamic_cast_if_available<const Segment*>(
+      &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Segment::MergeFrom(const Segment& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from._has_bit(0)) {
+      set_index(from.index());
+    }
+    if (from._has_bit(1)) {
+      set_offset(from.offset());
+    }
+    if (from._has_bit(2)) {
+      set_size(from.size());
+    }
+    if (from._has_bit(3)) {
+      set_data(from.data());
+    }
+  }
+  mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void Segment::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Segment::CopyFrom(const Segment& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Segment::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000007) != 0x00000007) return false;
+  
+  return true;
+}
+
+void Segment::Swap(Segment* other) {
+  if (other != this) {
+    std::swap(index_, other->index_);
+    std::swap(offset_, other->offset_);
+    std::swap(size_, other->size_);
+    std::swap(data_, other->data_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.Swap(&other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::google::protobuf::Metadata Segment::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Segment_descriptor_;
+  metadata.reflection = Segment_reflection_;
+  return metadata;
+}
+
+
+// ===================================================================
+
+const ::std::string Job::_default_url_;
+#ifndef _MSC_VER
+const int Job::kUrlFieldNumber;
+const int Job::kSegmentsFieldNumber;
+#endif  // !_MSC_VER
+
+Job::Job() {
+  SharedCtor();
+}
+
+void Job::InitAsDefaultInstance() {
+}
+
+Job::Job(const Job& from) {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void Job::SharedCtor() {
+  _cached_size_ = 0;
+  url_ = const_cast< ::std::string*>(&_default_url_);
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+Job::~Job() {
+  SharedDtor();
+}
+
+void Job::SharedDtor() {
+  if (url_ != &_default_url_) {
+    delete url_;
+  }
+  if (this != default_instance_) {
+  }
+}
+
+const ::google::protobuf::Descriptor* Job::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Job_descriptor_;
+}
+
+const Job& Job::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_ddm_2eproto();  return *default_instance_;
+}
+
+Job* Job::default_instance_ = NULL;
+
+Job* Job::New() const {
+  return new Job;
+}
+
+void Job::Clear() {
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (_has_bit(0)) {
+      if (url_ != &_default_url_) {
+        url_->clear();
+      }
+    }
+  }
+  segments_.Clear();
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->Clear();
+}
+
+bool Job::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required string url = 1;
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+          goto handle_uninterpreted;
+        }
+        DO_(::google::protobuf::internal::WireFormatLite::ReadString(
+              input, this->mutable_url()));
+        ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+          this->url().data(), this->url().length(),
+          ::google::protobuf::internal::WireFormat::PARSE);
+        if (input->ExpectTag(18)) goto parse_segments;
+        break;
+      }
+      
+      // repeated .proto.Segment segments = 2;
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+          goto handle_uninterpreted;
+        }
+       parse_segments:
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+              input, add_segments()));
+        if (input->ExpectTag(18)) goto parse_segments;
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void Job::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
+  if (raw_buffer != NULL) {
+    Job::SerializeWithCachedSizesToArray(raw_buffer);
+    return;
+  }
+  
+  // required string url = 1;
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->url().data(), this->url().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    ::google::protobuf::internal::WireFormatLite::WriteString(
+      1, this->url(), output);
+  }
+  
+  // repeated .proto.Segment segments = 2;
+  for (int i = 0; i < this->segments_size(); i++) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      2, this->segments(i), output);
+  }
+  
+  if (!unknown_fields().empty()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+}
+
+::google::protobuf::uint8* Job::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // required string url = 1;
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormat::VerifyUTF8String(
+      this->url().data(), this->url().length(),
+      ::google::protobuf::internal::WireFormat::SERIALIZE);
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteStringToArray(
+        1, this->url(), target);
+  }
+  
+  // repeated .proto.Segment segments = 2;
+  for (int i = 0; i < this->segments_size(); i++) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        2, this->segments(i), target);
+  }
+  
+  if (!unknown_fields().empty()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  return target;
+}
+
+int Job::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required string url = 1;
+    if (has_url()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::StringSize(
+          this->url());
+    }
+    
+  }
+  // repeated .proto.Segment segments = 2;
+  total_size += 1 * this->segments_size();
+  for (int i = 0; i < this->segments_size(); i++) {
+    total_size +=
+      ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+        this->segments(i));
+  }
+  
+  if (!unknown_fields().empty()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  _cached_size_ = total_size;
+  return total_size;
+}
+
+void Job::MergeFrom(const ::google::protobuf::Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  const Job* source =
+    ::google::protobuf::internal::dynamic_cast_if_available<const Job*>(
+      &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Job::MergeFrom(const Job& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  segments_.MergeFrom(from.segments_);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from._has_bit(0)) {
+      set_url(from.url());
+    }
+  }
+  mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void Job::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Job::CopyFrom(const Job& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Job::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+  
+  for (int i = 0; i < segments_size(); i++) {
+    if (!this->segments(i).IsInitialized()) return false;
+  }
+  return true;
+}
+
+void Job::Swap(Job* other) {
+  if (other != this) {
+    std::swap(url_, other->url_);
+    segments_.Swap(&other->segments_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.Swap(&other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::google::protobuf::Metadata Job::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Job_descriptor_;
+  metadata.reflection = Job_reflection_;
+  return metadata;
+}
+
+
+// ===================================================================
+
+const ::google::protobuf::EnumDescriptor* Packet_PacketType_descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Packet_PacketType_descriptor_;
+}
+bool Packet_PacketType_IsValid(int value) {
+  switch(value) {
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+    case 4:
+    case 5:
+    case 8:
+    case 9:
+    case 10:
+    case 11:
+    case 12:
+    case 13:
+      return true;
+    default:
+      return false;
+  }
+}
+
+#ifndef _MSC_VER
+const Packet_PacketType Packet::HELLO;
+const Packet_PacketType Packet::BYE;
+const Packet_PacketType Packet::PING;
+const Packet_PacketType Packet::PONG;
+const Packet_PacketType Packet::JOB_ADDED;
+const Packet_PacketType Packet::JOB_ACCEPT;
+const Packet_PacketType Packet::SEGMENT_STARTED;
+const Packet_PacketType Packet::SEGMENT_DONE;
+const Packet_PacketType Packet::SEGMENT_REQUEST;
+const Packet_PacketType Packet::SEGMENT;
+const Packet_PacketType Packet::SEGMENT_OK;
+const Packet_PacketType Packet::WELCOME;
+const Packet_PacketType Packet::PacketType_MIN;
+const Packet_PacketType Packet::PacketType_MAX;
+#endif  // _MSC_VER
+const ::std::string Packet::_default_payload_;
+#ifndef _MSC_VER
+const int Packet::kCommandFieldNumber;
+const int Packet::kPayloadFieldNumber;
+const int Packet::kJobFieldNumber;
+#endif  // !_MSC_VER
+
+Packet::Packet() {
+  SharedCtor();
+}
+
+void Packet::InitAsDefaultInstance() {
+  job_ = const_cast< ::proto::Job*>(&::proto::Job::default_instance());
+}
+
+Packet::Packet(const Packet& from) {
+  SharedCtor();
+  MergeFrom(from);
+}
+
+void Packet::SharedCtor() {
+  _cached_size_ = 0;
+  command_ = 2;
+  payload_ = const_cast< ::std::string*>(&_default_payload_);
+  job_ = NULL;
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+}
+
+Packet::~Packet() {
+  SharedDtor();
+}
+
+void Packet::SharedDtor() {
+  if (payload_ != &_default_payload_) {
+    delete payload_;
+  }
+  if (this != default_instance_) {
+    delete job_;
+  }
+}
+
+const ::google::protobuf::Descriptor* Packet::descriptor() {
+  protobuf_AssignDescriptorsOnce();
+  return Packet_descriptor_;
+}
+
+const Packet& Packet::default_instance() {
+  if (default_instance_ == NULL) protobuf_AddDesc_ddm_2eproto();  return *default_instance_;
+}
+
+Packet* Packet::default_instance_ = NULL;
+
+Packet* Packet::New() const {
+  return new Packet;
+}
+
+void Packet::Clear() {
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    command_ = 2;
+    if (_has_bit(1)) {
+      if (payload_ != &_default_payload_) {
+        payload_->clear();
+      }
+    }
+    if (_has_bit(2)) {
+      if (job_ != NULL) job_->::proto::Job::Clear();
+    }
+  }
+  ::memset(_has_bits_, 0, sizeof(_has_bits_));
+  mutable_unknown_fields()->Clear();
+}
+
+bool Packet::MergePartialFromCodedStream(
+    ::google::protobuf::io::CodedInputStream* input) {
+#define DO_(EXPRESSION) if (!(EXPRESSION)) return false
+  ::google::protobuf::uint32 tag;
+  while ((tag = input->ReadTag()) != 0) {
+    switch (::google::protobuf::internal::WireFormatLite::GetTagFieldNumber(tag)) {
+      // required .proto.Packet.PacketType command = 1 [default = PING];
+      case 1: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_VARINT) {
+          goto handle_uninterpreted;
+        }
+        int value;
+        DO_(::google::protobuf::internal::WireFormatLite::ReadEnum(input, &value));
+        if (::proto::Packet_PacketType_IsValid(value)) {
+          set_command(static_cast< ::proto::Packet_PacketType >(value));
+        } else {
+          mutable_unknown_fields()->AddVarint(1, value);
+        }
+        if (input->ExpectTag(18)) goto parse_payload;
+        break;
+      }
+      
+      // optional bytes payload = 2;
+      case 2: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+          goto handle_uninterpreted;
+        }
+       parse_payload:
+        DO_(::google::protobuf::internal::WireFormatLite::ReadBytes(
+              input, this->mutable_payload()));
+        if (input->ExpectTag(26)) goto parse_job;
+        break;
+      }
+      
+      // optional .proto.Job job = 3;
+      case 3: {
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) !=
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+          goto handle_uninterpreted;
+        }
+       parse_job:
+        DO_(::google::protobuf::internal::WireFormatLite::ReadMessageNoVirtual(
+             input, mutable_job()));
+        if (input->ExpectAtEnd()) return true;
+        break;
+      }
+      
+      default: {
+      handle_uninterpreted:
+        if (::google::protobuf::internal::WireFormatLite::GetTagWireType(tag) ==
+            ::google::protobuf::internal::WireFormatLite::WIRETYPE_END_GROUP) {
+          return true;
+        }
+        DO_(::google::protobuf::internal::WireFormat::SkipField(
+              input, tag, mutable_unknown_fields()));
+        break;
+      }
+    }
+  }
+  return true;
+#undef DO_
+}
+
+void Packet::SerializeWithCachedSizes(
+    ::google::protobuf::io::CodedOutputStream* output) const {
+  ::google::protobuf::uint8* raw_buffer = output->GetDirectBufferForNBytesAndAdvance(_cached_size_);
+  if (raw_buffer != NULL) {
+    Packet::SerializeWithCachedSizesToArray(raw_buffer);
+    return;
+  }
+  
+  // required .proto.Packet.PacketType command = 1 [default = PING];
+  if (_has_bit(0)) {
+    ::google::protobuf::internal::WireFormatLite::WriteEnum(
+      1, this->command(), output);
+  }
+  
+  // optional bytes payload = 2;
+  if (_has_bit(1)) {
+    ::google::protobuf::internal::WireFormatLite::WriteBytes(
+      2, this->payload(), output);
+  }
+  
+  // optional .proto.Job job = 3;
+  if (_has_bit(2)) {
+    ::google::protobuf::internal::WireFormatLite::WriteMessageNoVirtual(
+      3, this->job(), output);
+  }
+  
+  if (!unknown_fields().empty()) {
+    ::google::protobuf::internal::WireFormat::SerializeUnknownFields(
+        unknown_fields(), output);
+  }
+}
+
+::google::protobuf::uint8* Packet::SerializeWithCachedSizesToArray(
+    ::google::protobuf::uint8* target) const {
+  // required .proto.Packet.PacketType command = 1 [default = PING];
+  if (_has_bit(0)) {
+    target = ::google::protobuf::internal::WireFormatLite::WriteEnumToArray(
+      1, this->command(), target);
+  }
+  
+  // optional bytes payload = 2;
+  if (_has_bit(1)) {
+    target =
+      ::google::protobuf::internal::WireFormatLite::WriteBytesToArray(
+        2, this->payload(), target);
+  }
+  
+  // optional .proto.Job job = 3;
+  if (_has_bit(2)) {
+    target = ::google::protobuf::internal::WireFormatLite::
+      WriteMessageNoVirtualToArray(
+        3, this->job(), target);
+  }
+  
+  if (!unknown_fields().empty()) {
+    target = ::google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
+        unknown_fields(), target);
+  }
+  return target;
+}
+
+int Packet::ByteSize() const {
+  int total_size = 0;
+  
+  if (_has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    // required .proto.Packet.PacketType command = 1 [default = PING];
+    if (has_command()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::EnumSize(this->command());
+    }
+    
+    // optional bytes payload = 2;
+    if (has_payload()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::BytesSize(
+          this->payload());
+    }
+    
+    // optional .proto.Job job = 3;
+    if (has_job()) {
+      total_size += 1 +
+        ::google::protobuf::internal::WireFormatLite::MessageSizeNoVirtual(
+          this->job());
+    }
+    
+  }
+  if (!unknown_fields().empty()) {
+    total_size +=
+      ::google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(
+        unknown_fields());
+  }
+  _cached_size_ = total_size;
+  return total_size;
+}
+
+void Packet::MergeFrom(const ::google::protobuf::Message& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  const Packet* source =
+    ::google::protobuf::internal::dynamic_cast_if_available<const Packet*>(
+      &from);
+  if (source == NULL) {
+    ::google::protobuf::internal::ReflectionOps::Merge(from, this);
+  } else {
+    MergeFrom(*source);
+  }
+}
+
+void Packet::MergeFrom(const Packet& from) {
+  GOOGLE_CHECK_NE(&from, this);
+  if (from._has_bits_[0 / 32] & (0xffu << (0 % 32))) {
+    if (from._has_bit(0)) {
+      set_command(from.command());
+    }
+    if (from._has_bit(1)) {
+      set_payload(from.payload());
+    }
+    if (from._has_bit(2)) {
+      mutable_job()->::proto::Job::MergeFrom(from.job());
+    }
+  }
+  mutable_unknown_fields()->MergeFrom(from.unknown_fields());
+}
+
+void Packet::CopyFrom(const ::google::protobuf::Message& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+void Packet::CopyFrom(const Packet& from) {
+  if (&from == this) return;
+  Clear();
+  MergeFrom(from);
+}
+
+bool Packet::IsInitialized() const {
+  if ((_has_bits_[0] & 0x00000001) != 0x00000001) return false;
+  
+  if (has_job()) {
+    if (!this->job().IsInitialized()) return false;
+  }
+  return true;
+}
+
+void Packet::Swap(Packet* other) {
+  if (other != this) {
+    std::swap(command_, other->command_);
+    std::swap(payload_, other->payload_);
+    std::swap(job_, other->job_);
+    std::swap(_has_bits_[0], other->_has_bits_[0]);
+    _unknown_fields_.Swap(&other->_unknown_fields_);
+    std::swap(_cached_size_, other->_cached_size_);
+  }
+}
+
+::google::protobuf::Metadata Packet::GetMetadata() const {
+  protobuf_AssignDescriptorsOnce();
+  ::google::protobuf::Metadata metadata;
+  metadata.descriptor = Packet_descriptor_;
+  metadata.reflection = Packet_reflection_;
+  return metadata;
+}
+
+
+}  // namespace proto
+// Generated by the protocol buffer compiler.  DO NOT EDIT!
+
+#ifndef PROTOBUF_ddm_2eproto__INCLUDED
+#define PROTOBUF_ddm_2eproto__INCLUDED
+
+#include <string>
+
+#include <google/protobuf/stubs/common.h>
+
+#if GOOGLE_PROTOBUF_VERSION < 2002000
+#error This file was generated by a newer version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please update
+#error your headers.
+#endif
+#if 2002000 < GOOGLE_PROTOBUF_MIN_PROTOC_VERSION
+#error This file was generated by an older version of protoc which is
+#error incompatible with your Protocol Buffer headers.  Please
+#error regenerate this file with a newer version of protoc.
+#endif
+
+#include <google/protobuf/generated_message_util.h>
+#include <google/protobuf/repeated_field.h>
+#include <google/protobuf/extension_set.h>
+#include <google/protobuf/generated_message_reflection.h>
+
+namespace proto {
+
+// Internal implementation detail -- do not call these.
+void  protobuf_AddDesc_ddm_2eproto();
+void protobuf_AssignDesc_ddm_2eproto();
+void protobuf_ShutdownFile_ddm_2eproto();
+
+class Segment;
+class Job;
+class Packet;
+
+enum Packet_PacketType {
+  Packet_PacketType_HELLO = 0,
+  Packet_PacketType_BYE = 1,
+  Packet_PacketType_PING = 2,
+  Packet_PacketType_PONG = 3,
+  Packet_PacketType_JOB_ADDED = 4,
+  Packet_PacketType_JOB_ACCEPT = 5,
+  Packet_PacketType_SEGMENT_STARTED = 8,
+  Packet_PacketType_SEGMENT_DONE = 9,
+  Packet_PacketType_SEGMENT_REQUEST = 10,
+  Packet_PacketType_SEGMENT = 11,
+  Packet_PacketType_SEGMENT_OK = 12,
+  Packet_PacketType_WELCOME = 13
+};
+bool Packet_PacketType_IsValid(int value);
+const Packet_PacketType Packet_PacketType_PacketType_MIN = Packet_PacketType_HELLO;
+const Packet_PacketType Packet_PacketType_PacketType_MAX = Packet_PacketType_WELCOME;
+
+const ::google::protobuf::EnumDescriptor* Packet_PacketType_descriptor();
+inline const ::std::string& Packet_PacketType_Name(Packet_PacketType value) {
+  return ::google::protobuf::internal::NameOfEnum(
+    Packet_PacketType_descriptor(), value);
+}
+inline bool Packet_PacketType_Parse(
+    const ::std::string& name, Packet_PacketType* value) {
+  return ::google::protobuf::internal::ParseNamedEnum<Packet_PacketType>(
+    Packet_PacketType_descriptor(), name, value);
+}
+// ===================================================================
+
+class Segment : public ::google::protobuf::Message {
+ public:
+  Segment();
+  virtual ~Segment();
+  
+  Segment(const Segment& from);
+  
+  inline Segment& operator=(const Segment& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _unknown_fields_;
+  }
+  
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+  
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Segment& default_instance();
+  void Swap(Segment* other);
+  
+  // implements Message ----------------------------------------------
+  
+  Segment* New() const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Segment& from);
+  void MergeFrom(const Segment& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const { _cached_size_ = size; }
+  public:
+  
+  ::google::protobuf::Metadata GetMetadata() const;
+  
+  // nested types ----------------------------------------------------
+  
+  // accessors -------------------------------------------------------
+  
+  // required uint32 index = 1;
+  inline bool has_index() const;
+  inline void clear_index();
+  static const int kIndexFieldNumber = 1;
+  inline ::google::protobuf::uint32 index() const;
+  inline void set_index(::google::protobuf::uint32 value);
+  
+  // required uint64 offset = 2 [default = 0];
+  inline bool has_offset() const;
+  inline void clear_offset();
+  static const int kOffsetFieldNumber = 2;
+  inline ::google::protobuf::uint64 offset() const;
+  inline void set_offset(::google::protobuf::uint64 value);
+  
+  // required uint64 size = 3 [default = 524288];
+  inline bool has_size() const;
+  inline void clear_size();
+  static const int kSizeFieldNumber = 3;
+  inline ::google::protobuf::uint64 size() const;
+  inline void set_size(::google::protobuf::uint64 value);
+  
+  // optional bytes data = 4;
+  inline bool has_data() const;
+  inline void clear_data();
+  static const int kDataFieldNumber = 4;
+  inline const ::std::string& data() const;
+  inline void set_data(const ::std::string& value);
+  inline void set_data(const char* value);
+  inline void set_data(const void* value, size_t size);
+  inline ::std::string* mutable_data();
+  
+ private:
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  mutable int _cached_size_;
+  
+  ::google::protobuf::uint32 index_;
+  ::google::protobuf::uint64 offset_;
+  ::google::protobuf::uint64 size_;
+  ::std::string* data_;
+  static const ::std::string _default_data_;
+  friend void  protobuf_AddDesc_ddm_2eproto();
+  friend void protobuf_AssignDesc_ddm_2eproto();
+  friend void protobuf_ShutdownFile_ddm_2eproto();
+  
+  ::google::protobuf::uint32 _has_bits_[(4 + 31) / 32];
+  
+  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+  inline bool _has_bit(int index) const {
+    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+  }
+  inline void _set_bit(int index) {
+    _has_bits_[index / 32] |= (1u << (index % 32));
+  }
+  inline void _clear_bit(int index) {
+    _has_bits_[index / 32] &= ~(1u << (index % 32));
+  }
+  
+  void InitAsDefaultInstance();
+  static Segment* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class Job : public ::google::protobuf::Message {
+ public:
+  Job();
+  virtual ~Job();
+  
+  Job(const Job& from);
+  
+  inline Job& operator=(const Job& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _unknown_fields_;
+  }
+  
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+  
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Job& default_instance();
+  void Swap(Job* other);
+  
+  // implements Message ----------------------------------------------
+  
+  Job* New() const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Job& from);
+  void MergeFrom(const Job& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const { _cached_size_ = size; }
+  public:
+  
+  ::google::protobuf::Metadata GetMetadata() const;
+  
+  // nested types ----------------------------------------------------
+  
+  // accessors -------------------------------------------------------
+  
+  // required string url = 1;
+  inline bool has_url() const;
+  inline void clear_url();
+  static const int kUrlFieldNumber = 1;
+  inline const ::std::string& url() const;
+  inline void set_url(const ::std::string& value);
+  inline void set_url(const char* value);
+  inline void set_url(const char* value, size_t size);
+  inline ::std::string* mutable_url();
+  
+  // repeated .proto.Segment segments = 2;
+  inline int segments_size() const;
+  inline void clear_segments();
+  static const int kSegmentsFieldNumber = 2;
+  inline const ::google::protobuf::RepeatedPtrField< ::proto::Segment >& segments() const;
+  inline ::google::protobuf::RepeatedPtrField< ::proto::Segment >* mutable_segments();
+  inline const ::proto::Segment& segments(int index) const;
+  inline ::proto::Segment* mutable_segments(int index);
+  inline ::proto::Segment* add_segments();
+  
+ private:
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  mutable int _cached_size_;
+  
+  ::std::string* url_;
+  static const ::std::string _default_url_;
+  ::google::protobuf::RepeatedPtrField< ::proto::Segment > segments_;
+  friend void  protobuf_AddDesc_ddm_2eproto();
+  friend void protobuf_AssignDesc_ddm_2eproto();
+  friend void protobuf_ShutdownFile_ddm_2eproto();
+  
+  ::google::protobuf::uint32 _has_bits_[(2 + 31) / 32];
+  
+  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+  inline bool _has_bit(int index) const {
+    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+  }
+  inline void _set_bit(int index) {
+    _has_bits_[index / 32] |= (1u << (index % 32));
+  }
+  inline void _clear_bit(int index) {
+    _has_bits_[index / 32] &= ~(1u << (index % 32));
+  }
+  
+  void InitAsDefaultInstance();
+  static Job* default_instance_;
+};
+// -------------------------------------------------------------------
+
+class Packet : public ::google::protobuf::Message {
+ public:
+  Packet();
+  virtual ~Packet();
+  
+  Packet(const Packet& from);
+  
+  inline Packet& operator=(const Packet& from) {
+    CopyFrom(from);
+    return *this;
+  }
+  
+  inline const ::google::protobuf::UnknownFieldSet& unknown_fields() const {
+    return _unknown_fields_;
+  }
+  
+  inline ::google::protobuf::UnknownFieldSet* mutable_unknown_fields() {
+    return &_unknown_fields_;
+  }
+  
+  static const ::google::protobuf::Descriptor* descriptor();
+  static const Packet& default_instance();
+  void Swap(Packet* other);
+  
+  // implements Message ----------------------------------------------
+  
+  Packet* New() const;
+  void CopyFrom(const ::google::protobuf::Message& from);
+  void MergeFrom(const ::google::protobuf::Message& from);
+  void CopyFrom(const Packet& from);
+  void MergeFrom(const Packet& from);
+  void Clear();
+  bool IsInitialized() const;
+  
+  int ByteSize() const;
+  bool MergePartialFromCodedStream(
+      ::google::protobuf::io::CodedInputStream* input);
+  void SerializeWithCachedSizes(
+      ::google::protobuf::io::CodedOutputStream* output) const;
+  ::google::protobuf::uint8* SerializeWithCachedSizesToArray(::google::protobuf::uint8* output) const;
+  int GetCachedSize() const { return _cached_size_; }
+  private:
+  void SharedCtor();
+  void SharedDtor();
+  void SetCachedSize(int size) const { _cached_size_ = size; }
+  public:
+  
+  ::google::protobuf::Metadata GetMetadata() const;
+  
+  // nested types ----------------------------------------------------
+  
+  typedef Packet_PacketType PacketType;
+  static const PacketType HELLO = Packet_PacketType_HELLO;
+  static const PacketType BYE = Packet_PacketType_BYE;
+  static const PacketType PING = Packet_PacketType_PING;
+  static const PacketType PONG = Packet_PacketType_PONG;
+  static const PacketType JOB_ADDED = Packet_PacketType_JOB_ADDED;
+  static const PacketType JOB_ACCEPT = Packet_PacketType_JOB_ACCEPT;
+  static const PacketType SEGMENT_STARTED = Packet_PacketType_SEGMENT_STARTED;
+  static const PacketType SEGMENT_DONE = Packet_PacketType_SEGMENT_DONE;
+  static const PacketType SEGMENT_REQUEST = Packet_PacketType_SEGMENT_REQUEST;
+  static const PacketType SEGMENT = Packet_PacketType_SEGMENT;
+  static const PacketType SEGMENT_OK = Packet_PacketType_SEGMENT_OK;
+  static const PacketType WELCOME = Packet_PacketType_WELCOME;
+  static inline bool PacketType_IsValid(int value) {
+    return Packet_PacketType_IsValid(value);
+  }
+  static const PacketType PacketType_MIN =
+    Packet_PacketType_PacketType_MIN;
+  static const PacketType PacketType_MAX =
+    Packet_PacketType_PacketType_MAX;
+  static inline const ::google::protobuf::EnumDescriptor*
+  PacketType_descriptor() {
+    return Packet_PacketType_descriptor();
+  }
+  static inline const ::std::string& PacketType_Name(PacketType value) {
+    return Packet_PacketType_Name(value);
+  }
+  static inline bool PacketType_Parse(const ::std::string& name,
+      PacketType* value) {
+    return Packet_PacketType_Parse(name, value);
+  }
+  
+  // accessors -------------------------------------------------------
+  
+  // required .proto.Packet.PacketType command = 1 [default = PING];
+  inline bool has_command() const;
+  inline void clear_command();
+  static const int kCommandFieldNumber = 1;
+  inline ::proto::Packet_PacketType command() const;
+  inline void set_command(::proto::Packet_PacketType value);
+  
+  // optional bytes payload = 2;
+  inline bool has_payload() const;
+  inline void clear_payload();
+  static const int kPayloadFieldNumber = 2;
+  inline const ::std::string& payload() const;
+  inline void set_payload(const ::std::string& value);
+  inline void set_payload(const char* value);
+  inline void set_payload(const void* value, size_t size);
+  inline ::std::string* mutable_payload();
+  
+  // optional .proto.Job job = 3;
+  inline bool has_job() const;
+  inline void clear_job();
+  static const int kJobFieldNumber = 3;
+  inline const ::proto::Job& job() const;
+  inline ::proto::Job* mutable_job();
+  
+ private:
+  ::google::protobuf::UnknownFieldSet _unknown_fields_;
+  mutable int _cached_size_;
+  
+  int command_;
+  ::std::string* payload_;
+  static const ::std::string _default_payload_;
+  ::proto::Job* job_;
+  friend void  protobuf_AddDesc_ddm_2eproto();
+  friend void protobuf_AssignDesc_ddm_2eproto();
+  friend void protobuf_ShutdownFile_ddm_2eproto();
+  
+  ::google::protobuf::uint32 _has_bits_[(3 + 31) / 32];
+  
+  // WHY DOES & HAVE LOWER PRECEDENCE THAN != !?
+  inline bool _has_bit(int index) const {
+    return (_has_bits_[index / 32] & (1u << (index % 32))) != 0;
+  }
+  inline void _set_bit(int index) {
+    _has_bits_[index / 32] |= (1u << (index % 32));
+  }
+  inline void _clear_bit(int index) {
+    _has_bits_[index / 32] &= ~(1u << (index % 32));
+  }
+  
+  void InitAsDefaultInstance();
+  static Packet* default_instance_;
+};
+// ===================================================================
+
+
+// ===================================================================
+
+
+// ===================================================================
+
+// Segment
+
+// required uint32 index = 1;
+inline bool Segment::has_index() const {
+  return _has_bit(0);
+}
+inline void Segment::clear_index() {
+  index_ = 0u;
+  _clear_bit(0);
+}
+inline ::google::protobuf::uint32 Segment::index() const {
+  return index_;
+}
+inline void Segment::set_index(::google::protobuf::uint32 value) {
+  _set_bit(0);
+  index_ = value;
+}
+
+// required uint64 offset = 2 [default = 0];
+inline bool Segment::has_offset() const {
+  return _has_bit(1);
+}
+inline void Segment::clear_offset() {
+  offset_ = GOOGLE_ULONGLONG(0);
+  _clear_bit(1);
+}
+inline ::google::protobuf::uint64 Segment::offset() const {
+  return offset_;
+}
+inline void Segment::set_offset(::google::protobuf::uint64 value) {
+  _set_bit(1);
+  offset_ = value;
+}
+
+// required uint64 size = 3 [default = 524288];
+inline bool Segment::has_size() const {
+  return _has_bit(2);
+}
+inline void Segment::clear_size() {
+  size_ = GOOGLE_ULONGLONG(524288);
+  _clear_bit(2);
+}
+inline ::google::protobuf::uint64 Segment::size() const {
+  return size_;
+}
+inline void Segment::set_size(::google::protobuf::uint64 value) {
+  _set_bit(2);
+  size_ = value;
+}
+
+// optional bytes data = 4;
+inline bool Segment::has_data() const {
+  return _has_bit(3);
+}
+inline void Segment::clear_data() {
+  if (data_ != &_default_data_) {
+    data_->clear();
+  }
+  _clear_bit(3);
+}
+inline const ::std::string& Segment::data() const {
+  return *data_;
+}
+inline void Segment::set_data(const ::std::string& value) {
+  _set_bit(3);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+}
+inline void Segment::set_data(const char* value) {
+  _set_bit(3);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(value);
+}
+inline void Segment::set_data(const void* value, size_t size) {
+  _set_bit(3);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  data_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* Segment::mutable_data() {
+  _set_bit(3);
+  if (data_ == &_default_data_) {
+    data_ = new ::std::string;
+  }
+  return data_;
+}
+
+// -------------------------------------------------------------------
+
+// Job
+
+// required string url = 1;
+inline bool Job::has_url() const {
+  return _has_bit(0);
+}
+inline void Job::clear_url() {
+  if (url_ != &_default_url_) {
+    url_->clear();
+  }
+  _clear_bit(0);
+}
+inline const ::std::string& Job::url() const {
+  return *url_;
+}
+inline void Job::set_url(const ::std::string& value) {
+  _set_bit(0);
+  if (url_ == &_default_url_) {
+    url_ = new ::std::string;
+  }
+  url_->assign(value);
+}
+inline void Job::set_url(const char* value) {
+  _set_bit(0);
+  if (url_ == &_default_url_) {
+    url_ = new ::std::string;
+  }
+  url_->assign(value);
+}
+inline void Job::set_url(const char* value, size_t size) {
+  _set_bit(0);
+  if (url_ == &_default_url_) {
+    url_ = new ::std::string;
+  }
+  url_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* Job::mutable_url() {
+  _set_bit(0);
+  if (url_ == &_default_url_) {
+    url_ = new ::std::string;
+  }
+  return url_;
+}
+
+// repeated .proto.Segment segments = 2;
+inline int Job::segments_size() const {
+  return segments_.size();
+}
+inline void Job::clear_segments() {
+  segments_.Clear();
+}
+inline const ::google::protobuf::RepeatedPtrField< ::proto::Segment >&
+Job::segments() const {
+  return segments_;
+}
+inline ::google::protobuf::RepeatedPtrField< ::proto::Segment >*
+Job::mutable_segments() {
+  return &segments_;
+}
+inline const ::proto::Segment& Job::segments(int index) const {
+  return segments_.Get(index);
+}
+inline ::proto::Segment* Job::mutable_segments(int index) {
+  return segments_.Mutable(index);
+}
+inline ::proto::Segment* Job::add_segments() {
+  return segments_.Add();
+}
+
+// -------------------------------------------------------------------
+
+// Packet
+
+// required .proto.Packet.PacketType command = 1 [default = PING];
+inline bool Packet::has_command() const {
+  return _has_bit(0);
+}
+inline void Packet::clear_command() {
+  command_ = 2;
+  _clear_bit(0);
+}
+inline ::proto::Packet_PacketType Packet::command() const {
+  return static_cast< ::proto::Packet_PacketType >(command_);
+}
+inline void Packet::set_command(::proto::Packet_PacketType value) {
+  GOOGLE_DCHECK(::proto::Packet_PacketType_IsValid(value));
+  _set_bit(0);
+  command_ = value;
+}
+
+// optional bytes payload = 2;
+inline bool Packet::has_payload() const {
+  return _has_bit(1);
+}
+inline void Packet::clear_payload() {
+  if (payload_ != &_default_payload_) {
+    payload_->clear();
+  }
+  _clear_bit(1);
+}
+inline const ::std::string& Packet::payload() const {
+  return *payload_;
+}
+inline void Packet::set_payload(const ::std::string& value) {
+  _set_bit(1);
+  if (payload_ == &_default_payload_) {
+    payload_ = new ::std::string;
+  }
+  payload_->assign(value);
+}
+inline void Packet::set_payload(const char* value) {
+  _set_bit(1);
+  if (payload_ == &_default_payload_) {
+    payload_ = new ::std::string;
+  }
+  payload_->assign(value);
+}
+inline void Packet::set_payload(const void* value, size_t size) {
+  _set_bit(1);
+  if (payload_ == &_default_payload_) {
+    payload_ = new ::std::string;
+  }
+  payload_->assign(reinterpret_cast<const char*>(value), size);
+}
+inline ::std::string* Packet::mutable_payload() {
+  _set_bit(1);
+  if (payload_ == &_default_payload_) {
+    payload_ = new ::std::string;
+  }
+  return payload_;
+}
+
+// optional .proto.Job job = 3;
+inline bool Packet::has_job() const {
+  return _has_bit(2);
+}
+inline void Packet::clear_job() {
+  if (job_ != NULL) job_->::proto::Job::Clear();
+  _clear_bit(2);
+}
+inline const ::proto::Job& Packet::job() const {
+  return job_ != NULL ? *job_ : *default_instance_->job_;
+}
+inline ::proto::Job* Packet::mutable_job() {
+  _set_bit(2);
+  if (job_ == NULL) job_ = new ::proto::Job;
+  return job_;
+}
+
+
+}  // namespace proto
+
+#ifndef SWIG
+namespace google {
+namespace protobuf {
+
+template <>
+inline const EnumDescriptor* GetEnumDescriptor< ::proto::Packet_PacketType>() {
+  return ::proto::Packet_PacketType_descriptor();
+}
+
+}  // namespace google
+}  // namespace protobuf
+#endif  // SWIG
+
+#endif  // PROTOBUF_ddm_2eproto__INCLUDED
+package proto;
+//option optimize_for = LITE_RUNTIME;
+
+// A Segment may or may not contain data
+// When a peer announces that it has begun a segment
+// download, or when it requests a segment,
+// it will send an empty one.
+// Further, the Segment class wraps this Segment
+// and provides status and peer lists.
+message Segment {
+    required uint32 index = 1;
+    required uint64 offset = 2 [ default=0 ];
+    required uint64 size = 3 [ default = 524288 ]; // 512K
+    optional bytes data = 4;
+}
+
+// A Job is sent when a peer requests state information
+// from all existing peers
+// or when a new download is announced by a peer and so on
+message Job {
+    required string url = 1;
+    repeated Segment segments = 2;
+}
+
+message Packet {
+    enum PacketType {
+        HELLO = 0; // sent when a Peer first joins the swarm,                       mcast
+        BYE = 1; // sent when a Peer cleanly exits a swarm                          mcast
+        
+        PING = 2;//                                                                 mcast
+        PONG = 3;//                                                                 mcast
+        
+        JOB_ADDED = 4; // the sending Peer added a new job, payload is a Job        mcast
+        JOB_ACCEPT = 5; // reply to Peer if we accept his job
+        
+        
+        SEGMENT_STARTED = 8; // the sending Peer has started downloading a segment
+        // when this is received, each client should request the segment after a
+        // random interval
+        SEGMENT_DONE = 9; // sending Peer finished downloading a segment        
+        SEGMENT_REQUEST = 10; // request a certain segment
+        SEGMENT = 11; // a full segment is being sent...
+        
+        SEGMENT_OK = 12 ; // sent by reciever to acknowledge successful transfer,
+                          // sender will probably want to update its own Job structure
+        
+        WELCOME = 13; // sent by existing Peers on a HELLO from the new peer
+    }
+
+    required PacketType command = 1 [ default = PING ] ;
+    // The payload itself is some type of message
+    // how to parse that message depends on the command
+    // and is handled at appropriate places
+    optional bytes payload = 2;
+    
+    // some messages (ie. requesting a segment)
+    // require an identifying job
+    // this does it
+    optional Job job = 3;
+}
+/*
+    Copyright (c) <year> <copyright holders>
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use,
+    copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following
+    conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+    OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#include "job.h"
+
+using namespace ddm;
+
+/*
+    Copyright (c) <year> <copyright holders>
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use,
+    copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following
+    conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+    OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifndef DDM_JOB_H
+#define DDM_JOB_H
+
+#include <string>
+#include <list>
+
+#include "segment.h"
+
+namespace ddm
+{
+
+class Peer;
+class Job
+{
+
+public:
+    enum Status {
+        Stopped,
+        Running,
+        Finished,
+        Alone
+    };
+    
+    Job( std::string url, std::string outputPath );
+    void addPeer( Peer * );
+    void removePeer( Peer * );
+    
+protected:
+    virtual void peerJoined( Peer * );
+    virtual void peerLeft( Peer * );
+    
+private:
+    std::string url;
+    std::string outputPath;
+    std::list<Segment> segments;
+    std::list<Peer *> peers;
+};
+ 
+}
+
+#endif // DDM_JOB_H
+#include <UdpSocket.h>
+#include <Utility.h>
+#include <ISocketHandler.h>
+
+#include <stdio.h>
+#include <string.h>
+
+#include "ddm.pb.h"
+using namespace proto;
+
+/**
+ * Listens to multicasts and forwards
+ * them on to the SocketHandler.
+ * Also allows sending multicasts
+ */
+class McastSocket : public UdpSocket
+{
+public:
+    McastSocket(ISocketHandler &h) : UdpSocket(h) {}
+    void OnRawData( const char*, size_t, struct sockaddr *, socklen_t );
+};
+
+void McastSocket::OnRawData( const char* p, size_t sz, struct sockaddr * from, socklen_t )
+{
+    GOOGLE_PROTOBUF_VERIFY_VERSION;
+    Packet pkt;
+    if( !pkt.ParseFromArray( p, sz ) )
+        std::cerr << "Parse failed\n";
+    
+    std::string sender;
+    Utility::l2ip( ((sockaddr_in*)from)->sin_addr, sender );
+    std::cerr << pkt.DebugString() << " from " << sender << std::endl;
+
+    if( pkt.command() != Packet::HELLO )
+        return;
+
+    pkt.Clear();
+    pkt.set_command( Packet::HELLO_REPLY );
+    Packet::Hello *hrep = pkt.mutable_hello();
+    hrep->set_version( 1 );
+    hrep->set_client( "DDM" );
+    hrep->set_urls("http://www.google.com");
+
+    std::string reply;
+    pkt.SerializeToString( &reply );
+    std::cerr << "Sending " << pkt.DebugString() << " to " << sender << "\n";
+
+    UdpSocket *s = new UdpSocket( Handler() );
+    s->Open( sender, 1235 );
+    Handler().Add(s);
+    s->Send( reply );
+}
+
+
+/*
+    Copyright (c) <year> <copyright holders>
+
+    Permission is hereby granted, free of charge, to any person
+    obtaining a copy of this software and associated documentation
+    files (the "Software"), to deal in the Software without
+    restriction, including without limitation the rights to use,
+    copy, modify, merge, publish, distribute, sublicense, and/or sell
+    copies of the Software, and to permit persons to whom the
+    Software is furnished to do so, subject to the following
+    conditions:
+
+    The above copyright notice and this permission notice shall be
+    included in all copies or substantial portions of the Software.
+
+    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
+    OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+    NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
+    HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+    WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+    FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+    OTHER DEALINGS IN THE SOFTWARE.
+
+*/
+
+#ifndef SEGMENT_H
+#define SEGMENT_H
+
+#include <stdint.h>
+#include <list>
+
+namespace ddm
+{
+    
+class Segment
+{
+  public:
+    enum SegmentStatus {
+      AVAILABLE, // available on some Peer
+      DONE, // downloaded already
+      INPROGRESS,
+      ABSENT // no one has it
+    };
+    
+    Segment( SegmentStatus st, uint64_t offset, uint64_t size );
+    Segment( std::string data );
+    inline SegmentStatus Status() { return m_status; }
+    inline uint64_t Offset() { return m_offset; }
+    inline uint64_t Size() { return m_size; }
+    inline void setSegmentStatus( enum SegmentStatus st ) { this->m_status = st; }
+    inline void setSize( uint64_t size ) { this->m_size = size; }
+    inline void setOffset( uint64_t offset ) { this->m_offset = offset; }
+    inline void setData( std::string data );
+    
+  private:
+    SegmentStatus m_status;
+    //std::list<Peer *> m_peers;
+    uint64_t m_offset;
+    uint64_t m_size;
+    std::string m_data;
+};
+
+inline Segment::Segment( SegmentStatus st, uint64_t offset, uint64_t size )
+{
+  setSegmentStatus( st );
+  setOffset( offset );
+  setSize( size );
+}
+
+inline Segment::Segment( std::string data )
+{
+  setData( data );
+}
+
+inline void Segment::setData( std::string data )
+{
+  this->m_data = data;
+  setSize( data.length() );
+  setSegmentStatus( AVAILABLE );
+}
+
+}
+#endif // SEGMENT_H

tests/CMakeLists.txt

+ENABLE_TESTING()
+Project ( ddm_test )
+Find_Package ( CxxTest REQUIRED )
+
+include_directories ( ${CXXTEST_INCLUDE_DIR} )
+
+include_directories ( ${ddm_SOURCE_DIR}/src )
+link_directories ( ${ddm_BINARY_DIR}/src )
+
+set ( DDM_LIBS ddm )
+
+CXXTEST_ADD_TEST ( init_test init_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/init_test.h )
+target_link_libraries ( init_test ${CORE_LIBS} )
+
+CXXTEST_ADD_TEST ( add_url_test add_url_test.cpp ${CMAKE_CURRENT_SOURCE_DIR}/add_url_test.h )
+target_link_libraries ( add_url_test ${CORE_LIBS} )
+Requires CxxTest

tests/add_url_test.h

+#include <cxxtest/TestSuite.h>
+
+#include "ddm.h"
+
+using namespace ddm;
+
+DDM *dd;
+class AddUrlTest : public CxxTest::TestSuite
+{
+public:
+    static void createSuite()
+    {
+        dd = new DDM();
+    }
+    void testAddUrl()
+    {
+        dd->addUrl( "http://localhost/global.html" );
+        dd->addUrl( "http://www.google.com" );
+    }
+    static void destroySuite()
+    {
+        dd->cleanup();
+    }
+};
+// kate: indent-mode cstyle; space-indent on; indent-width 4; replace-tabs on; 

tests/init_test.h

+#include <cxxtest/TestSuite.h>
+
+#include "ddm.h"
+
+using namespace ddm;
+DDM *dd;
+class InitTest : public CxxTest::TestSuite
+{
+public:
+    void testInit()
+    {
+        dd = new DDM();
+        TS_ASSERT( dd->init() );
+    }
+    
+    void testCleanup()
+    {
+        TS_ASSERT( dd->cleanup() );
+        delete dd;
+        dd = NULL;
+    }
+};
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.