--- /dev/null
+
+CXX=g++
+#CXX=clang
+CXX_FLAGS=-std=c++11 -Wall -pthread -ggdb
+CXX_INC=-I./include/ -I./csdk/stack/include -I./csdk/ocsocket/include -I./csdk/ocrandom/include -I./csdk/logger/include
+
+# Force metatargets to build:
+.PHONY: c_sdk single_resource client examples
+
+all: .PHONY
+
+c_sdk:
+ cd csdk && $(MAKE)
+
+examples:
+ cd examples && $(MAKE)
+
+single_resource: OCLib.a single_resource.o
+ $(CXX) $(CXX_FLAGS) -o single_resource single_resource.o OCLib.a csdk/liboctbstack.a
+
+client: OCLib.a OCClient.o
+ $(CXX) $(CXX_FLAGS) -o client OCClient.o OCLib.a csdk/liboctbstack.a
+
+OCLib.a: OCPlatform.o OCResource.o OCReflect.o InProcServerWrapper.o InProcClientWrapper.o
+ ar -cvq OCLib.a OCPlatform.o OCResource.o OCReflect.o InProcServerWrapper.o InProcClientWrapper.o
+
+OCReflect.o: OCLib/OCReflect.cpp
+ $(CXX) $(CXX_FLAGS) -c OCLib/OCReflect.cpp $(CXX_INC)
+
+OCPlatform.o: OCLib/OCPlatform.cpp
+ $(CXX) $(CXX_FLAGS) -c OCLib/OCPlatform.cpp $(CXX_INC)
+
+OCResource.o: OCLib/OCResource.cpp
+ $(CXX) $(CXX_FLAGS) -c OCLib/OCResource.cpp $(CXX_INC)
+
+InProcServerWrapper.o: OCLib/InProcServerWrapper.cpp
+ $(CXX) $(CXX_FLAGS) -c OCLib/InProcServerWrapper.cpp $(CXX_INC)
+
+InProcClientWrapper.o: OCLib/InProcClientWrapper.cpp
+ $(CXX) $(CXX_FLAGS) -c OCLib/InProcClientWrapper.cpp $(CXX_INC)
+
+single_resource.o : examples/server/single_resource.cpp
+ $(CXX) $(CXX_FLAGS) -c examples/server/single_resource.cpp $(CXX_INC)
+
+OCClient.o : examples/client/OCClient.cpp
+ $(CXX) $(CXX_FLAGS) -c examples/client/OCClient.cpp $(CXX_INC)
+
+clean:
+ rm -f -v OCLib.a *.o single_resource client
+ cd examples && $(MAKE) clean
+
+ cd csdk && $(MAKE) clean
+ cd csdk && $(MAKE) deepclean
+
+
+# Force metatargets to build:
+.PHONY: c_sdk single_resource client examples
+
+all: .PHONY
+
+c_sdk:
+ cd csdk && $(MAKE)
+
+examples:
+ cd examples && $(MAKE)
+
+single_resource: OCLib.a single_resource.o
+ $(CXX) $(CXX_FLAGS) -o single_resource single_resource.o OCLib.a csdk/liboctbstack.a
+
+client: OCLib.a OCClient.o
+ $(CXX) $(CXX_FLAGS) -o client OCClient.o OCLib.a csdk/liboctbstack.a
+
+OCLib.a: OCPlatform.o OCResource.o OCReflect.o InProcServerWrapper.o InProcClientWrapper.o
+ ar -cvq OCLib.a OCPlatform.o OCResource.o OCReflect.o InProcServerWrapper.o InProcClientWrapper.o
+
+OCReflect.o: OCLib/OCReflect.cpp
+ $(CXX) $(CXX_FLAGS) -c OCLib/OCReflect.cpp $(CXX_INC)
+
+OCPlatform.o: OCLib/OCPlatform.cpp
+ $(CXX) $(CXX_FLAGS) -c OCLib/OCPlatform.cpp $(CXX_INC)
+
+OCResource.o: OCLib/OCResource.cpp
+ $(CXX) $(CXX_FLAGS) -c OCLib/OCResource.cpp $(CXX_INC)
+
+InProcServerWrapper.o: OCLib/InProcServerWrapper.cpp
+ $(CXX) $(CXX_FLAGS) -c OCLib/InProcServerWrapper.cpp $(CXX_INC)
+
+InProcClientWrapper.o: OCLib/InProcClientWrapper.cpp
+ $(CXX) $(CXX_FLAGS) -c OCLib/InProcClientWrapper.cpp $(CXX_INC)
+
+single_resource.o : examples/server/single_resource.cpp
+ $(CXX) $(CXX_FLAGS) -c examples/server/single_resource.cpp $(CXX_INC)
+
+OCClient.o : examples/client/OCClient.cpp
+ $(CXX) $(CXX_FLAGS) -c examples/client/OCClient.cpp $(CXX_INC)
+
+clean:
+ rm -f -v OCLib.a *.o single_resource client
+ cd examples && $(MAKE) clean
+
+ cd csdk && $(MAKE) clean
+ cd csdk && $(MAKE) deepclean
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include "OCResource.h"
+#include "InProcClientWrapper.h"
+
+#include "ocstack.h"
+
+using namespace std;
+
+
+namespace OC
+{
+ InProcClientWrapper::InProcClientWrapper(PlatformConfig cfg)
+ {
+ OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, OC_CLIENT);
+
+ if(OC_STACK_OK != result)
+ {
+ throw InitializeException("Error Initializing Stack", result);
+ }
+
+ m_threadRun = true;
+ m_listeningThread = std::thread(&InProcClientWrapper::listeningFunc, this);
+ }
+
+ InProcClientWrapper::~InProcClientWrapper()
+ {
+ if(m_listeningThread.joinable())
+ {
+ m_threadRun = false;
+ m_listeningThread.join();
+ }
+
+ OCStop();
+ }
+
+ void InProcClientWrapper::listeningFunc()
+ {
+ while(m_threadRun)
+ {
+ OCStackResult result;
+ {
+ std::lock_guard<std::mutex> lock(m_csdkLock);
+ result = OCProcess();
+ }
+
+ if(result != OC_STACK_OK)
+ {
+ // TODO: @Erich do something with result if failed?
+ }
+
+ std::this_thread::yield();
+ // To minimize CPU utilization we may wish to do this with sleep
+ //std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+ }
+
+
+
+ std::string convertOCAddrToString(OCDevAddr* addr)
+ {
+ if(addr->size != 4) { return "NOT SUPPORTED ADDR;";}
+
+ if(addr->size == 4) // IPV4
+ {
+ std::ostringstream address;
+ address<<"coap://"<<addr->addr[0]<<"."<<addr->addr[1]<<"."<<addr->addr[2]<<"."<<addr->addr[3]<<"/";
+ return address.str();
+ }
+
+ // TODO: @Erich Convert the device address to a valid string!
+ return "";
+ }
+
+
+ OCStackApplicationResult listenCallback(void* ctx, OCClientResponse* clientResponse)
+ {
+ auto &callback =*(std::function <void(OCResource::Ptr)>*)ctx;
+ std::stringstream requestStream;
+ requestStream << clientResponse->resJSONPayload;
+
+
+ boost::property_tree::ptree root;
+ boost::property_tree::read_json(requestStream, root);
+
+ boost::property_tree::ptree payload = root.get_child("oc.payload", boost::property_tree::ptree());
+
+
+ for(auto payloadItr : payload)
+ {
+ try
+ {
+ std::string host = convertOCAddrToString(clientResponse->addr);
+ OCResource::Ptr resource = std::make_shared<OCResource>(host, payloadItr.second);
+
+ // Note: the call to detach allows the underlying thread to continue until completion
+ // and allows us to destroy the exec object.
+ // This is apparently NOT a memory leak, as the thread will apparently take care of itself.
+ // Additionally, the only parameter here is
+ // a shared ptr, so OCResource will be disposed of properly upon completion of the callback handler.
+ std::thread exec(callback,resource);
+ exec.detach();
+ }
+ catch(ResourceInitException)
+ {
+ // TODO: Do we want to handle this somehow? Perhaps we need to log this?
+ }
+
+ }
+ delete clientResponse;
+
+ return OC_STACK_KEEP_TRANSACTION;
+ }
+
+ int InProcClientWrapper::ListenForResource(const std::string& serviceUrl, const std::string& resourceType, std::function<void (OCResource::Ptr)>& callback)
+ {
+ OCStackResult result;
+
+ OCCallbackData* cbdata = new OCCallbackData();
+ cbdata->context = (void*)(&callback);
+ cbdata->cb = &listenCallback;
+ {
+ std::lock_guard<std::mutex> lock(m_csdkLock);
+
+ result = OCDoResource(OC_REST_GET, resourceType.c_str(), nullptr, nullptr, OC_NON_CONFIRMABLE, cbdata);
+
+ }
+ return result;
+ }
+ }
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <random>
+#include <cstring>
+#include <cstdlib>
+#include <iostream>
+#include <algorithm>
+
+#include "InProcServerWrapper.h"
+#include <InitializeException.h>
+#include <OCReflect.h>
+#include <ocstack.h>
+
+
+using namespace OC::OCReflect;
+
+using namespace std;
+
+void entityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest* eHandlerReq)
+{
+ cout << "Resource Handler: " << eHandlerReq->resource << endl;
+ cout << "Method: " << eHandlerReq->method << endl;
+ cout << "reqJSONPayLoad: " << eHandlerReq->reqJSONPayload << endl;
+}
+
+namespace OC
+{
+ InProcServerWrapper::InProcServerWrapper(PlatformConfig cfg)
+ {
+ OCStackResult result = OCInit(cfg.ipAddress.c_str(), cfg.port, OC_SERVER);
+
+ if(OC_STACK_OK != result)
+ {
+ throw InitializeException("Error Initializing Stack", result);
+ }
+
+ m_threadRun = true;
+ m_processThread = std::thread(&InProcServerWrapper::processFunc, this);
+ }
+
+ void InProcServerWrapper::processFunc()
+ {
+ while(m_threadRun)
+ {
+ OCStackResult result;
+ {
+ std::lock_guard<std::mutex> lock(m_csdkLock);
+ result = OCProcess();
+ }
+
+ if(result != OC_STACK_OK)
+ {
+ cout << "Something wrong in OCProcess" << endl;
+ // TODO: SASHI
+ }
+
+ std::this_thread::yield();
+ // To minimize CPU utilization we may wish to do this with sleep
+ //std::this_thread::sleep_for(std::chrono::milliseconds(1));
+ }
+ }
+
+ void InProcServerWrapper::registerResource(const std::string& resourceURI,
+ const std::string& resourceTypeName,
+ named_property_binding_vector properties)
+ {
+ using OC::OCReflect::property_type;
+ using OC::OCReflect::named_property_binding;
+ using namespace OC::OCReflect::to_OCStack;
+
+ std::vector<std::string> reps { convert(properties) };
+
+ for(const auto& r : reps)
+ std::cout << r << '\n';
+
+ char *resourTypeRepresentation = flatten(reps);
+
+ std::cout << resourTypeRepresentation << "\n";
+
+ OCResourceHandle resourceHandle;
+
+ {
+ std::lock_guard<std::mutex> lock(m_csdkLock);
+
+ cout << "Creating a resource" << endl;
+
+ OCStackResult result;
+
+ result = OCCreateResource(&resourceHandle, // OCResourceHandle *handl
+ resourceTypeName.c_str(), // const char * resourceTypeName
+ resourTypeRepresentation, //const char * resourceTypeRepresentation
+ "core.rw", //const char * resourceInterfaceName
+ OC_REST_GET | OC_REST_PUT, // uint8_t allowedMethods
+ resourceURI.c_str(), // const char * uri
+ entityHandler, // OCEntityHandler entityHandler
+ OC_DISCOVERABLE | OC_OBSERVABLE // uint8_t resourceProperties
+ );
+
+ if(result != OC_STACK_OK)
+ {
+ cout << "Something wrong in OCCreateResource" << endl;
+ // TODO: SASHI
+ }
+ else
+ {
+ cout << "Resource creation is successful" << endl;
+ }
+
+ }
+
+ }
+
+ InProcServerWrapper::~InProcServerWrapper()
+ {
+ if(m_processThread.joinable())
+ {
+ m_threadRun = false;
+ m_processThread.join();
+ }
+
+ OCStop();
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "ocapi.h"
+
+OC::OCReflect::entity OC::OCResourceResult::property(const std::string& name)
+{
+ return OC::OCReflect::entity();
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "OCObject.h"
+
+namespace OC {
+ OCObject::OCObject(void)
+ {
+ }
+
+
+ OCObject::~OCObject(void)
+ {
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "OCObserver.h"
+
+namespace OC {
+ OCObserver::OCObserver(void)
+ {
+ }
+
+
+ OCObserver::~OCObserver(void)
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+//******************************************************************
+// File name:
+// OCPlatform.cpp
+//
+// Description: Implementation of the OCPlatform.
+//
+//
+//
+//*********************************************************************
+
+#include <random>
+
+#include "OCPlatform.h"
+
+namespace OC
+{
+ // Constructor. Internally calls private init function
+ OCPlatform::OCPlatform(const PlatformConfig& config)
+ {
+ init(config);
+ }
+
+ // Destructor
+ OCPlatform::~OCPlatform(void)
+ {
+ std::cout << "platform destructor called" << std::endl;
+ cleanup();
+ }
+
+ void OCPlatform::init(const PlatformConfig& config)
+ {
+ std::unique_ptr<WrapperFactory> wrapperInstance(new WrapperFactory());
+ m_WrapperInstance = std::move(wrapperInstance);
+
+ if(config.mode == ModeType::Server)
+ {
+ // Call server wrapper init
+ m_server = m_WrapperInstance->CreateServerWrapper(config);
+ }
+ else if(config.mode == ModeType::Client)
+ {
+ // Call client wrapper init
+ m_client = m_WrapperInstance->CreateClientWrapper(config);
+ }
+ else
+ {
+ // This must be both server and client
+ m_server = m_WrapperInstance->CreateServerWrapper(config);
+ m_client = m_WrapperInstance->CreateClientWrapper(config);
+ }
+ }
+
+ void OCPlatform::cleanup()
+ {
+ if(m_server)
+ {
+ //delete m_server;
+ }
+
+ if(m_client)
+ {
+ //delete m_client;
+ }
+ }
+
+
+ void OCPlatform::findResource(const std::string& host, const std::string& resourceName,
+ std::function<void(OCResource::Ptr)> resourceHandler)
+ {
+ if(m_client)
+ {
+ m_client->ListenForResource(host, resourceName, resourceHandler);
+ }
+ }
+
+
+ void OCPlatform::registerResource(const std::string& resourceURI, const std::string& resourceTypeName,
+ named_property_binding_vector properties)
+ {
+ if(m_server)
+ {
+ try{
+ m_server->registerResource(resourceURI, resourceTypeName, properties);
+ }catch(std::exception e) // define our own expception.
+ {
+ throw e;
+ }
+ }
+ }
+
+} //namespace OC
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "OCReflect.h"
+#include "OCProperties.h"
+
+using OC::OCReflect::property_type;
+
+namespace OC { namespace OCReflect {
+
+std::ostream& operator<<(std::ostream& os, const property_type& pt)
+{
+ using ocpt = property_type;
+
+ switch(pt)
+ {
+ case ocpt::nil: os << "nil"; break;
+ case ocpt::boolean: os << "boolean"; break;
+ case ocpt::integer: os << "integer"; break;
+ case ocpt::rational: os << "rational"; break;
+ case ocpt::string: os << "string"; break;
+ case ocpt::list: os << "list"; break;
+
+ case ocpt::INVALID: os << "INVALID"; break;
+ }
+
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_attribute& pa)
+{
+ using ocpa = OC::OCReflect::property_attribute;
+
+ switch(pa)
+ {
+ case ocpa::r: os << 'r'; break;
+ case ocpa::w: os << 'w'; break;
+ case ocpa::rw: os << "rw"; break;
+ }
+
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_signature& ps)
+{
+ os << '(' << ps.type << ':' << ps.attribute << ')';
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property& p)
+{
+ using std::get;
+
+ const auto& npb = get<0>(p);
+ const auto& npb_name = get<0>(npb);
+ const auto& npb_sig = get<1>(npb);
+
+ const auto& pd = std::get<1>(p);
+
+ os << "property \"" << npb_name << "\": " << npb_sig << "\"\n";
+
+ os << '\"' << npb_name << ' ' << npb_sig;
+
+ os << "\nDATA {\n";
+
+ for(const unsigned char c : pd)
+ {
+ os << static_cast<int>(c);
+
+ if(std::isprint(c))
+ os << ' ' << c;
+
+ os << '\n';
+ }
+
+ os << "}\n";
+
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const property_type_vector& ptv)
+{
+ for(const auto& pt : ptv)
+ os << pt << "; ";
+
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_vector& pv)
+{
+ for(const auto& p : pv)
+ os << p << "; ";
+
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_signature_vector& psv)
+{
+ for(const auto& ps : psv)
+ os << '[' << ps.attribute << ']' << ps.type << "; ";
+
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::method_signature& ms)
+{
+ os << ms.param_signatures << " -> " << ms.ret_signature;
+ return os;
+}
+
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::method_binding& mb)
+{
+ os << mb.name << " :: " << mb.signature;
+ return os;
+}
+
+}} // namespace OC::OCReflect
+
+namespace OC { namespace OCReflect { namespace to_property { namespace detail {
+
+// Convert a memory representation to bytes:
+template <class InT>
+OC::OCReflect::property_data static_rep(const InT& in)
+{
+ return OC::OCReflect::property_data(reinterpret_cast<const char *>(&in),
+ reinterpret_cast<const char *>(&in) + sizeof(in));
+}
+
+// Apply a typetag to a representation:
+template <class RepT>
+OC::OCReflect::tagged_property tag_rep(const property_type pt, const RepT& rep)
+{
+ return OC::OCReflect::tagged_property({ pt }, { rep });
+}
+
+template <class SeqIterT>
+OC::OCReflect::tagged_property tag_rep(const property_type pt, const SeqIterT& begin, const SeqIterT& end)
+{
+ return OC::OCReflect::tagged_property({ pt },
+ { begin, end });
+}
+
+}}}} // namespace OC::OCReflect::to_property::detail
+
+namespace OC { namespace OCReflect { namespace to_property {
+
+OC::OCReflect::tagged_property convert(const bool& in)
+{
+ return detail::tag_rep(property_type::boolean, static_cast<char>(in));
+}
+
+OC::OCReflect::tagged_property convert(const int64_t& in)
+{
+ return detail::tag_rep(property_type::integer, detail::static_rep(in));
+}
+
+// Convenience sugar for default platform int:
+OC::OCReflect::tagged_property convert(const int& in)
+{
+ static_assert(sizeof(int) <= sizeof(int64_t),
+ "conversion to int64_t may be dangerous on your platform: use int64_t explicitly");
+
+ return convert(static_cast<int64_t>(in));
+}
+
+OC::OCReflect::tagged_property convert(const double& in)
+{
+ return detail::tag_rep(property_type::rational, detail::static_rep(in));
+}
+
+OC::OCReflect::tagged_property convert(const std::string& in)
+{
+ return detail::tag_rep(property_type::string,
+ in.begin(), in.end());
+}
+
+}}} // namespace OC::OCReflect::to_property
+
+pd_iter_tuple consume_typecheck(const property_type expected_pt, const OC::OCReflect::property_data& in)
+{
+ OC::OCReflect::property_data::const_iterator begin = in.begin();
+
+ auto found_pt = static_cast<property_type>(*begin);
+
+ std::cout << "val ept=" << (int)expected_pt << ", ept: " << (int)found_pt << '\n';
+
+ if(expected_pt != found_pt)
+ {
+ std::ostringstream os;
+ os << "type error: " << "expected " << expected_pt << ", found " << found_pt;
+ throw OC::OCReflect::reflection_exception(os.str());
+ }
+
+ return std::forward_as_tuple(++begin, in.end());
+}
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <string>
+#include <cstring>
+
+#include "OCReflect.h"
+
+OC::OCReflect::entity OC::OCReflect::remote_resource::operator()(const std::string& name)
+{
+ return OC::OCReflect::entity();
+}
+
+namespace OC { namespace OCReflect { namespace to_OCStack {
+
+// Free a C array of char *:
+void release(char **in)
+{
+ if(nullptr == in)
+ return;
+
+ for(char **cursor = in; nullptr != *cursor; ++cursor)
+ {
+ if(nullptr != *cursor)
+ free(*cursor);
+ }
+
+ free(in);
+}
+
+char *strdup(const char *s)
+{
+ if(nullptr == s)
+ return nullptr;
+
+ char *ret = static_cast<char *>(malloc(1 + strlen(s)));
+
+ if(nullptr == ret)
+ return nullptr;
+
+ return strcpy(ret, s);
+}
+
+char *strdup(const std::string& s)
+{
+ char *ret = static_cast<char *>(malloc(1 + s.length()));
+
+ if(nullptr == ret)
+ return nullptr;
+
+ return strcpy(ret, s.c_str());
+}
+
+// Count the number of elements in a NULL-terminated C array of char*:
+size_t length(char **in)
+{
+ if(nullptr == in)
+ return 0;
+
+ size_t ret = 0;
+
+ for(char **cursor = in; nullptr != *cursor; ++cursor)
+ ++ret;
+
+ return ret;
+}
+
+// Note: caller is responsible for the returned memory:
+char **convert(const std::vector<std::string>& vs)
+{
+ char **out;
+
+ try
+ {
+ out = (char **)malloc(vs.size()*sizeof(char *));
+
+ if(nullptr == out)
+ throw;
+
+ size_t i = 0;
+ for(; vs.size() != i; ++i)
+ {
+ out[i] = to_OCStack::strdup(vs[i]);
+
+ if(nullptr == out[i])
+ throw;
+ }
+
+ out[i] = nullptr;
+
+ return out;
+ }
+ catch(...)
+ {
+ if(nullptr != out)
+ release(out);
+ }
+
+ return nullptr;
+}
+
+std::string convert(const OC::OCReflect::named_property_binding& npb)
+{
+ const std::string& name = std::get<0>(npb);
+ const OC::OCReflect::property_signature ps = std::get<1>(npb);
+
+ std::ostringstream os;
+
+ os << name << ':' << "oc.";
+
+ using OC::OCReflect::property_type;
+
+ switch(ps.type)
+ {
+ case property_type::nil:
+ case property_type::rational:
+ case property_type::string:
+ case property_type::list:
+ case property_type::INVALID:
+ throw std::runtime_error("not implemented");
+ break;
+
+ case property_type::boolean: os << "bt." << 'b';
+ break;
+
+ case property_type::integer: os << "bt." << 'i';
+ break;
+ }
+
+ return os.str();
+}
+
+std::vector<std::string> convert(const OC::OCReflect::named_property_binding_vector& psv)
+{
+ std::vector<std::string> out;
+
+ for(const auto& ps : psv)
+ out.emplace_back(convert(ps));
+
+ return out;
+}
+
+char *flatten(const std::vector<std::string>& input, const std::string& delim)
+{
+ std::string out;
+
+ for(size_t i = 0; input.size() != i; ++i)
+ {
+ out += input[i];
+
+ if(i < input.size() - 1)
+ out += ";";
+ }
+
+ return OC::OCReflect::to_OCStack::strdup(out);
+}
+
+}}} // namespace OC::OCReflect::to_OCStack
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "OCResource.h"
+#include "OCReflect.h"
+
+namespace OC {
+ OCResource::OCResource(std::string host, boost::property_tree::ptree& resourceNode) : m_isCollection(false)
+ {
+ m_host = host;
+ m_uri = resourceNode.get<std::string>("href","");
+ m_isObservable = resourceNode.get<int>("obs",0)==1;
+
+ boost::property_tree::ptree resourceTypes = resourceNode.get_child("rt", boost::property_tree::ptree());
+ for(auto itr : resourceTypes)
+ {
+ m_resourceTypes.push_back(itr.second.data());
+ }
+
+ boost::property_tree::ptree interfaces = resourceNode.get_child("if", boost::property_tree::ptree());
+ for(auto itr : interfaces)
+ {
+ if(itr.second.data() == "oc.mi.ll")
+ {
+ m_isCollection = true;
+ }
+
+ m_interfaces.push_back(itr.second.data());
+ }
+
+ // TODO: If collection, load children, assuming this becomes a thing
+
+ // TODO: Load attributes, assuming this becomes a 'thing'
+
+ if (m_uri.empty() || resourceTypes.empty() || interfaces.empty())
+ {
+ throw ResourceInitException(m_uri.empty(), resourceTypes.empty(), interfaces.empty());
+ }
+ }
+
+ OCResource::~OCResource()
+ {
+ }
+} // namespace OC
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "OCSecurityModel.h"
+
+namespace OC {
+ OCSecurityModel::OCSecurityModel(void)
+ {
+ }
+
+
+ OCSecurityModel::~OCSecurityModel(void)
+ {
+ }
+}
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "OCServer.h"
+#include "OCReflect.h"
+
+namespace OC {
+ OCServer::OCServer(void)
+ {
+ }
+
+
+ OCServer::~OCServer(void)
+ {
+ }
+
+ void OCServer::setSecurityModel(OCSecurityModel model) {
+ }
+
+ void OCServer::registerResource(OCObject *object, std::string url/* TODO: , AccessControl accessControl */) {
+ }
+
+ void OCServer::unregisterResource(OCObject *object) {
+ }
+
+ void OCServer::start() {
+ }
+
+ void OCServer::stop() {
+ }
+
+ void OCServer::bind(const OC::OCReflect::method_binding& mb)
+ {
+ method_bindings[mb.name] = mb;
+ }
+}
--- /dev/null
+CXX=g++
+#CXX=clang -lstdc++ -g
+
+CXX_FLAGS=-std=c++11 -Wall -pthread
+
+CXX_INC=-I../OCProject/include/ -I../OCProject/OCLib/ -I../OCProject/OCLib/OCWrapper/ -I../OCProject/OCLib/OCWrapper/server -I../OCProject/OCLib/OCWrapper/client/ -I../OCProject/csdk/
+
+LIB_SRC0=../OCProject/OCLib/OCPlatform.cpp ../OCProject/OCLib/OCWrapper/server/InProcServerWrapper.cpp ../OCProject/OCLib/OCWrapper/client/InProcClientWrapper.cpp ../OCProject/csdk/ocstack_stub.c ../OCProject/OCLib/OCReflect.cpp ../OCProject/OCLib/OCResource.cpp
+
+
+platform:
+ $(CXX) $(CXX_FLAGS) -o OCPlatformTestApp OCPlatformTestApp.cpp $(LIB_SRC0) $(CXX_INC)
+
+server:
+ $(CXX) $(CXX_FLAGS) -o OCServerTestApp OCServerTestApp.cpp $(LIB_SRC0) $(CXX_INC)
+
+client:
+ $(CXX) $(CXX_FLAGS) -o OCClientTestApp OCClientTestApp.cpp $(LIB_SRC0) $(CXX_INC)
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "OCTestApp.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include <string.h>
+#include <iostream>
+
+// Headers Required For the Tests
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "OCResource.h"
+
+using namespace std;
+using namespace OC;
+
+// Create A Function That Matches...
+// std::function<void(OCResource::Ptr)> callback
+
+void InProcClientResourceCallback(OCResource::Ptr pValue);
+void OutProcClientResourceCallback(OCResource::Ptr pValue);
+
+void Test_OCFunction_0(int functionIndex);
+void Test_OCFunction_1(int functionIndex);
+void Test_OCFunction_2(int functionIndex);
+void Test_OCFunction_3(int functionIndex);
+void Test_OCFunction_4(int functionIndex);
+void Test_OCFunction_5(int functionIndex);
+void Test_OCFunction_6(int functionIndex);
+void Test_OCFunction_7(int functionIndex);
+void Test_OCFunction_8(int functionIndex);
+void Test_OCFunction_9(int functionIndex);
+void Test_OCFunction_10(int functionIndex);
+void Test_OCFunction_11(int functionIndex);
+void Test_OCFunction_12(int functionIndex);
+void Test_OCFunction_13(int functionIndex);
+void Test_OCFunction_14(int functionIndex);
+void Test_OCFunction_15(int functionIndex);
+void Test_OCFunction_16(int functionIndex);
+void Test_OCFunction_17(int functionIndex);
+
+FunctionStruct functionStruct[] = {
+ { &Test_OCFunction_0, "InProcClient", "DNRT" },
+ { &Test_OCFunction_1, "InProcClient - ListenForResource", "DNRT" },
+ { &Test_OCFunction_2, "InProcClient - Callback Called", "DNRT" },
+ { &Test_OCFunction_3, "OCOutOfProcClient", "DNRT" },
+ { &Test_OCFunction_4, "OCOutOfProcClient - ListenForResource", "DNRT" },
+ { &Test_OCFunction_5, "OCOutOfProcClient - Callback Called", "DNRT" },
+ { &Test_OCFunction_6, "~InProcClientWrapper", "DNRT" },
+ { &Test_OCFunction_7, "~OCOutOfProcClient", "DNRT" },
+ { &Test_OCFunction_8, "OCResource", "DNRT" },
+ { &Test_OCFunction_9, "OCResource - host", "DNRT" },
+ { &Test_OCFunction_10, "OCResource - uri", "DNRT" },
+ { &Test_OCFunction_11, "OCResource - isObservable", "DNRT" },
+ { &Test_OCFunction_12, "OCResource - isCollection", "DNRT" },
+ { &Test_OCFunction_13, "OCResource - resourceTypes", "DNRT" },
+ { &Test_OCFunction_14, "OCResource - interfaces", "DNRT" },
+ { &Test_OCFunction_15, "OCResource - properties", "DNRT" },
+ { &Test_OCFunction_16, "OCResource - children", "DNRT" },
+ { &Test_OCFunction_17, "~OCResource", "DNRT" },
+ };
+
+InProcClientWrapper *pInClient = nullptr;
+OutOfProcClientWrapper *pOutClient = nullptr;
+OCResource *pResource = nullptr;
+
+int main(void)
+{
+ int functionIndex = 0, functionNameSize = 0, functionNameLen = 0, functionCount = 0;
+ int resultSize = 0, resultLen = 0, lenOfResult = 0;
+ char rightSide[MaxResultSize], a;
+
+
+ // Get The Size Of Each Of The Structure Elements
+ functionCount = ElementCount(functionStruct);
+
+ // Run The Tests
+ Test_OCFunction_0(0);
+ Test_OCFunction_1(1);
+ Test_OCFunction_3(3);
+ Test_OCFunction_4(4);
+ Test_OCFunction_5(5);
+ Test_OCFunction_6(6);
+ Test_OCFunction_7(7);
+ Test_OCFunction_8(8);
+ Test_OCFunction_9(9);
+ Test_OCFunction_10(10);
+ Test_OCFunction_11(11);
+ Test_OCFunction_12(12);
+ Test_OCFunction_13(13);
+ Test_OCFunction_14(14);
+ Test_OCFunction_15(15);
+ Test_OCFunction_16(16);
+ Test_OCFunction_17(17);
+
+ for (functionIndex = 0; functionIndex < functionCount; functionIndex++)
+ {
+ functionNameLen = strlen((char*)&functionStruct[functionIndex].m_FunctionName);
+ if (functionNameLen > functionNameSize)
+ functionNameSize = functionNameLen;
+
+ resultLen = strlen((char*)&functionStruct[functionIndex].m_Result);
+ if (resultLen > resultSize)
+ resultSize = resultLen;
+ }
+
+ for (functionIndex = 0; functionIndex < functionCount; functionIndex++)
+ {
+ // Set The Width Of This Line
+ cout.width(ResultColumn);
+
+ // Print The Function Name
+ cout << left << functionStruct[functionIndex].m_FunctionName;
+
+ // Print The Result
+ strcpy((char*)&rightSide, (char*)&functionStruct[functionIndex].m_Result);
+ lenOfResult = strlen((char*)&functionStruct[functionIndex].m_Result);
+ memset((char*)&rightSide[lenOfResult], ' ', MaxResultSize - lenOfResult);
+ rightSide[MaxResultSize - 1] = 0;
+ cout << right << rightSide << endl;
+ }
+
+ cin >> a; // Wait For Keyboard Input
+ return 0;
+}
+
+void Test_OCFunction_0(int functionIndex)
+{
+ bool bResult = true;
+ PlatformConfig cfg;
+ named_property_binding_vector vc;
+
+ try
+ {
+ cfg.serviceType = ServiceType::InProc;
+ cfg.mode = ModeType::Server;
+ cfg.ipAddress = "192.168.1.5";
+ cfg.port = 8080;
+
+ pInClient = new InProcClientWrapper(cfg);
+
+ bResult = true;
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_1(int functionIndex)
+{
+ bool bResult = false;
+ string resName, resType;
+ int retVal = 0;
+
+ try
+ {
+ if (pInClient != nullptr)
+ {
+ resName = "ResourceName";
+ resType = "ResourceType";
+
+ retVal = pInClient->ListenForResource(resName, resType, &InProcClientResourceCallback);
+
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult && retVal == 0)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void InProcClientResourceCallback(OCResource::Ptr pValue)
+{
+ Test_OCFunction_2(2);
+}
+
+void Test_OCFunction_2(int functionIndex)
+{
+ bool bResult = false;
+
+ try
+ {
+
+ bResult = true;
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_3(int functionIndex)
+{
+ bool bResult = true;
+ PlatformConfig cfg;
+ named_property_binding_vector vc;
+
+ try
+ {
+ cfg.serviceType = ServiceType::InProc;
+ cfg.mode = ModeType::Server;
+ cfg.ipAddress = "192.168.1.5";
+ cfg.port = 8080;
+
+ pOutClient = new OutOfProcClientWrapper(cfg);
+
+ bResult = true;
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_4(int functionIndex)
+{
+ bool bResult = false;
+ string resName, resType;
+ int retVal = 0;
+
+ try
+ {
+ if (pOutClient != nullptr)
+ {
+ resName = "ResourceName";
+ resType = "ResourceType";
+
+ retVal = pOutClient->ListenForResource(resName, resType, &InProcClientResourceCallback);
+
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult && retVal == 0)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void OutProcClientResourceCallback(OCResource::Ptr pValue)
+{
+ Test_OCFunction_5(5);
+}
+
+void Test_OCFunction_5(int functionIndex)
+{
+ bool bResult = true;
+
+ try
+ {
+
+ bResult = true;
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_6(int functionIndex)
+{
+ bool bResult = false;
+
+ try
+ {
+ if (pInClient != NULL)
+ {
+ delete pInClient;
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_7(int functionIndex)
+{
+ bool bResult = true;
+
+ try
+ {
+
+ if (pOutClient != NULL)
+ {
+ delete pOutClient;
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_8(int functionIndex)
+{
+ bool bResult = true;
+ string str, exceptionStr;
+ boost::property_tree::ptree tree;
+
+ try
+ {
+ str = "Host";
+ pResource = new OCResource(str, tree);
+
+ bResult = true;
+ }
+
+ catch (ResourceInitException rie)
+ {
+ exceptionStr =rie.Reason()
+ cout << exceptionStr.c_str() << endl;
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_9(int functionIndex)
+{
+ string str;
+
+ if (pResource != nullptr)
+ str = pResource->host();
+
+
+ if (strcmp(str.c_str(), "Host") == 0)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_10(int functionIndex)
+{
+ string str;
+
+ if (pResource != nullptr)
+ str = pResource->uri();
+
+
+ if (strcmp(str.c_str(), "Host") == 0)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_11(int functionIndex)
+{
+ bool bResult = false;
+
+ if (pResource != nullptr)
+ bResult = pResource->isObservable();
+
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_12(int functionIndex)
+{
+ bool bResult = false;
+
+ if (pResource != nullptr)
+ bResult = pResource->isCollection();
+
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_13(int functionIndex)
+{
+ std::vector<std::string> vStr;
+
+ if (pResource != nullptr)
+ vStr = pResource->resourceTypes();
+
+
+ if (vStr.size() > 0)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_14(int functionIndex)
+{
+ std::vector<std::string> vStr;
+
+ if (pResource != nullptr)
+ vStr = pResource->interfaces();
+
+
+ if (vStr.size() > 0)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_15(int functionIndex)
+{
+ std::vector<std::string> vStr;
+
+ if (pResource != nullptr)
+ vStr = pResource->properties();
+
+
+ if (vStr.size() > 0)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_16(int functionIndex)
+{
+ std::vector<std::string> vStr;
+
+ if (pResource != nullptr)
+ vStr = pResource->children();
+
+
+ if (vStr.size() > 0)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_17(int functionIndex)
+{
+ bool bResult = false;
+
+ try
+ {
+ if (pResource != nullptr)
+ {
+ delete pResource;
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "OCTestApp.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include <string.h>
+#include <iostream>
+
+// Headers Required For the Tests
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+using namespace std;
+using namespace OC;
+
+void Test_OCPlatform_0(int functionIndex);
+void Test_OCPlatform_1(int functionIndex);
+void Test_OCPlatform_2(int functionIndex);
+void Test_OCPlatform_3(int functionIndex);
+void Test_OCPlatform_4(int functionIndex);
+void Test_OCPlatform_5(int functionIndex);
+
+void PlatformCallback_1(OCResource::Ptr pParam);
+void PlatformCallback_2(OCResource::Ptr pParam);
+
+FunctionStruct functionStruct[] = {
+ { &Test_OCPlatform_0, "OCPlatform", "DNRT" },
+ { &Test_OCPlatform_1, "OCPlatform - findResource", "DNRT" },
+ { &Test_OCPlatform_2, "OCPlatform - Callback", "DNRT" },
+ { &Test_OCPlatform_3, "OCPlatform - findResourceByType", "DNRT" },
+ { &Test_OCPlatform_4, "OCPlatform - Resource Callback", "DNRT" },
+ { &Test_OCPlatform_5, "~OCPlatform", "DNRT" },
+ };
+
+OCPlatform *pPlatform = nullptr;
+
+int main(void)
+{
+ int functionIndex = 0, functionNameSize = 0, functionNameLen = 0, functionCount = 0;
+ int resultSize = 0, resultLen = 0, lenOfResult = 0;
+ char rightSide[MaxResultSize], a;
+
+
+ // Get The Size Of Each Of The Structure Elements
+ functionCount = ElementCount(functionStruct);
+
+ // Run The Tests
+ Test_OCPlatform_0(0);
+ Test_OCPlatform_1(1);
+ Test_OCPlatform_2(2);
+ Test_OCPlatform_3(3);
+ Test_OCPlatform_4(4);
+ Test_OCPlatform_5(5);
+
+ for (functionIndex = 0; functionIndex < functionCount; functionIndex++)
+ {
+ functionNameLen = strlen((char*)&functionStruct[functionIndex].m_FunctionName);
+ if (functionNameLen > functionNameSize)
+ functionNameSize = functionNameLen;
+
+ resultLen = strlen((char*)&functionStruct[functionIndex].m_Result);
+ if (resultLen > resultSize)
+ resultSize = resultLen;
+ }
+
+ for (functionIndex = 0; functionIndex < functionCount; functionIndex++)
+ {
+ // Set The Width Of This Line
+ cout.width(ResultColumn);
+
+ // Print The Function Name
+ cout << left << functionStruct[functionIndex].m_FunctionName;
+
+ // Print The Result
+ strcpy((char*)&rightSide, (char*)&functionStruct[functionIndex].m_Result);
+ lenOfResult = strlen((char*)&functionStruct[functionIndex].m_Result);
+ memset((char*)&rightSide[lenOfResult], ' ', MaxResultSize - lenOfResult);
+ rightSide[MaxResultSize - 1] = 0;
+ cout << right << rightSide << endl;
+ }
+
+ cin >> a; // Wait For Keyboard Input
+
+ return 0;
+}
+
+
+void Test_OCPlatform_0(int functionIndex)
+{
+ bool bResult = true;
+ PlatformConfig cfg;
+
+ try
+ {
+ cfg.serviceType = ServiceType::InProc;
+ cfg.mode = ModeType::Server;
+ cfg.ipAddress = "192.168.1.5";
+ cfg.port = 8080;
+
+ pPlatform = new OCPlatform(cfg);
+
+ bResult = true;
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCPlatform_1(int functionIndex)
+{
+ bool bResult = false;
+ PlatformConfig cfg;
+ string resType, hostName;
+ named_property_binding_vector vc;
+
+ try
+ {
+ if (pPlatform != nullptr)
+ {
+ hostName = "Host";
+ resType = "ResourceType";
+ pPlatform->findResource(hostName, resType, &PlatformCallback_1);
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void PlatformCallback_1(OCResource::Ptr pParam)
+{
+ Test_OCPlatform_2(2);
+}
+
+void Test_OCPlatform_2(int functionIndex)
+{
+ bool bResult = true;
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCPlatform_3(int functionIndex)
+{
+ bool bResult = false;
+ PlatformConfig cfg;
+ string serviceURL, resourceType;
+ named_property_binding_vector vc;
+
+ try
+ {
+ if (pPlatform != nullptr)
+ {
+ serviceURL = "ServiceURL";
+ resourceType = "Type";
+ //pPlatform->findResourceByType(serviceURL, resourceType, &PlatformCallback_2);
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void PlatformCallback_2(OCResource::Ptr pParam)
+{
+ Test_OCPlatform_4(4);
+}
+
+void Test_OCPlatform_4(int functionIndex)
+{
+ bool bResult = false;
+ string resourceURI, resourceTypeName;
+ named_property_binding_vector vc;
+
+ try
+ {
+ if (pPlatform != nullptr)
+ {
+ resourceURI = "URI";
+ resourceTypeName = "NAME";
+ pPlatform->registerResource(resourceURI, resourceTypeName, vc);
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCPlatform_5(int functionIndex)
+{
+ bool bResult = false;
+
+ try
+ {
+ if (pPlatform != nullptr)
+ {
+ delete pPlatform;
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+
+
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "OCTestApp.h"
+#include "stdlib.h"
+#include "stdio.h"
+#include <string.h>
+#include <iostream>
+
+// Headers Required For the Tests
+#include "OCPlatform.h"
+#include "OCApi.h"
+#include "OCReflect.h"
+
+
+using namespace std;
+using namespace OC;
+using namespace OC::OCReflect;
+
+void Test_OCFunction_0(int functionIndex);
+void Test_OCFunction_1(int functionIndex);
+void Test_OCFunction_2(int functionIndex);
+void Test_OCFunction_3(int functionIndex);
+void Test_OCFunction_4(int functionIndex);
+void Test_OCFunction_5(int functionIndex);
+void Test_OCFunction_6(int functionIndex);
+void Test_OCFunction_7(int functionIndex);
+void Test_OCFunction_8(int functionIndex);
+void Test_OCFunction_9(int functionIndex);
+void Test_OCFunction_10(int functionIndex);
+void Test_OCFunction_11(int functionIndex);
+void Test_OCFunction_12(int functionIndex);
+
+FunctionStruct functionStruct[] = {
+ { &Test_OCFunction_0, "OCInProcServer", "DNRT" },
+ { &Test_OCFunction_1, "OCOutOfProcServer", "DNRT" },
+ { &Test_OCFunction_2, "OCInProcServer - registerResource", "DNRT" },
+ { &Test_OCFunction_3, "OCOutOfProcServer - registerResource", "DNRT" },
+ { &Test_OCFunction_4, "remote_resource", "DNRT" },
+ { &Test_OCFunction_5, "remoteResource - operator", "DNRT" },
+ { &Test_OCFunction_6, "method", "DNRT" },
+ { &Test_OCFunction_7, "method - operator", "DNRT" },
+ { &Test_OCFunction_8, "~OCInProcServer", "DNRT" },
+ { &Test_OCFunction_9, "~OCOutOfProcServer", "DNRT" },
+ { &Test_OCFunction_10, "~remote_resource", "DNRT" },
+ { &Test_OCFunction_11, "~OCResource", "DNRT" },
+ { &Test_OCFunction_12, "~method", "DNRT" },
+ };
+
+InProcServerWrapper *pInProcServer = nullptr;
+OutOfProcServerWrapper *pOutProcServer = nullptr;
+remote_resource *pRemoteResource = nullptr;
+OCResource *pResource = nullptr;
+method *pMethod = nullptr;
+
+int main(void)
+{
+ int functionIndex = 0, functionNameSize = 0, functionNameLen = 0, functionCount = 0;
+ int resultSize = 0, resultLen = 0, lenOfResult = 0;
+ char rightSide[MaxResultSize], a;
+
+
+ // Get The Size Of Each Of The Structure Elements
+ functionCount = ElementCount(functionStruct);
+
+ // Run The Tests
+ Test_OCFunction_0(0);
+ Test_OCFunction_1(1);
+ Test_OCFunction_2(2);
+ Test_OCFunction_3(3);
+ Test_OCFunction_4(4);
+ Test_OCFunction_5(5);
+ Test_OCFunction_6(6);
+ Test_OCFunction_7(7);
+ Test_OCFunction_8(8);
+ Test_OCFunction_9(9);
+ Test_OCFunction_10(10);
+ Test_OCFunction_11(11);
+ Test_OCFunction_12(12);
+
+ for (functionIndex = 0; functionIndex < functionCount; functionIndex++)
+ {
+ functionNameLen = strlen((char*)&functionStruct[functionIndex].m_FunctionName);
+ if (functionNameLen > functionNameSize)
+ functionNameSize = functionNameLen;
+
+ resultLen = strlen((char*)&functionStruct[functionIndex].m_Result);
+ if (resultLen > resultSize)
+ resultSize = resultLen;
+ }
+
+ for (functionIndex = 0; functionIndex < functionCount; functionIndex++)
+ {
+ // Set The Width Of This Line
+ cout.width(ResultColumn);
+
+ // Print The Function Name
+ cout << left << functionStruct[functionIndex].m_FunctionName;
+
+ // Print The Result
+ strcpy((char*)&rightSide, (char*)&functionStruct[functionIndex].m_Result);
+ lenOfResult = strlen((char*)&functionStruct[functionIndex].m_Result);
+ memset((char*)&rightSide[lenOfResult], ' ', MaxResultSize - lenOfResult);
+ rightSide[MaxResultSize - 1] = 0;
+ cout << right << rightSide << endl;
+ }
+
+ cin >> a; // Wait For Keyboard Input
+ return 0;
+}
+
+void Test_OCFunction_0(int functionIndex)
+{
+ bool bResult = true;
+ PlatformConfig cfg;
+
+ try
+ {
+ cfg.serviceType = ServiceType::InProc;
+ cfg.mode = ModeType::Server;
+ cfg.ipAddress = "192.168.1.5";
+ cfg.port = 8080;
+
+ pInProcServer = new InProcServerWrapper(cfg);
+
+ bResult = true;
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_1(int functionIndex)
+{
+ bool bResult = true;
+ PlatformConfig cfg;
+
+ try
+ {
+ cfg.serviceType = ServiceType::InProc;
+ cfg.mode = ModeType::Server;
+ cfg.ipAddress = "192.168.1.5";
+ cfg.port = 8080;
+
+ pOutProcServer = new OutOfProcServerWrapper(cfg);
+
+ bResult = true;
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_2(int functionIndex)
+{
+ bool bResult = true;
+ string resName, resType;
+ named_property_binding_vector vc;
+
+ try
+ {
+ if (pInProcServer != nullptr)
+ {
+ resName = "ResourceName";
+ resType = "ResourceType";
+ pInProcServer->registerResource(resName, resType, vc);
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_3(int functionIndex)
+{
+ bool bResult = true;
+ string resName, resType;
+ named_property_binding_vector vc;
+
+ try
+ {
+ if (pOutProcServer != nullptr)
+ {
+ resName = "ResourceName";
+ resType = "ResourceType";
+ pOutProcServer->registerResource(resName, resType, vc);
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_4(int functionIndex)
+{
+ bool bResult = false;
+ string host, loc;
+ boost::property_tree::ptree tree;
+
+ try
+ {
+ host = "Host";
+ loc = "Nowhere Special";
+ pResource = new OCResource(host, tree);
+ pRemoteResource = new remote_resource(*pResource, loc);
+ bResult = true;
+ }
+
+ catch (...)
+ {
+cout << "Ouch!" << endl;
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_5(int functionIndex)
+{
+ bool bResult = false;
+ OC::OCReflect::entity localEntity;
+ string str;
+
+ try
+ {
+ if (pRemoteResource)
+ {
+ str = "SomeEntity";
+ //localEntity = pRemoteResource;//(str);
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_6(int functionIndex)
+{
+ bool bResult = false;
+ string str;
+
+ try
+ {
+ if (pResource != nullptr)
+ {
+ str = "SomeName";
+ pMethod = new method(*pResource, str);
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_7(int functionIndex)
+{
+ bool bResult = false;
+ OC::OCReflect::tagged_property prop;
+
+ try
+ {
+ if (pMethod != nullptr)
+ {
+ //prop = pMethod(TS ...xs);
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_8(int functionIndex)
+{
+ bool bResult = false;
+
+ try
+ {
+ if (pInProcServer != nullptr)
+ {
+ delete pInProcServer;
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_9(int functionIndex)
+{
+ bool bResult = false;
+
+ try
+ {
+ if (pOutProcServer != nullptr)
+ {
+ delete pOutProcServer;
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_10(int functionIndex)
+{
+ bool bResult = false;
+
+ try
+ {
+ if (pRemoteResource != nullptr)
+ {
+ delete pRemoteResource;
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+
+void Test_OCFunction_11(int functionIndex)
+{
+ bool bResult = false;
+
+ try
+ {
+ if (pResource != nullptr)
+ {
+ delete pResource;
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
+
+void Test_OCFunction_12(int functionIndex)
+{
+ bool bResult = false;
+
+ try
+ {
+ if (pMethod != nullptr)
+ {
+ delete pMethod;
+ bResult = true;
+ }
+ }
+
+ catch (...)
+ {
+ bResult = false;
+ }
+
+ if (bResult)
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Pass");
+ }
+ else
+ {
+ strcpy((char*)&functionStruct[functionIndex].m_Result, "Fail");
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#if ! defined (OCCLIENTTESTAPP__INCLUDED_)
+#define OCCLIENTTESTAPP__INCLUDED_
+
+#pragma once
+
+#define ElementCount(a) (sizeof(a) / sizeof(a[0]))
+
+enum
+{
+ IndentSpaces = 5,
+ MaxParams = 6,
+ MaxResultSize = 16,
+ MaxNameSize = 64,
+ ResultColumn = 80, // Start of 'Results' Column
+ ResultIndex = ResultColumn + 1, // 'Results' Column + 1
+ MaxFunctionNameSize = 64,
+};
+
+typedef void (Test_OCFunc)(int);
+
+typedef struct
+{
+ Test_OCFunc *m_pTest;
+ char m_FunctionName[MaxNameSize];
+ char m_Result[MaxResultSize];
+
+}FunctionStruct;
+
+
+#endif
+
--- /dev/null
+
+
+Builds with g++ 4.6, 4.8, 4.9.
+
+Run "make" to build OCLib.a and the examples.
+
+OCProject/
+├── csdk
+│ ├── examples :: TODO :: Unused remove??
+│ │ ├── occlient.c
+│ │ └── ocserver.c
+│ ├── ocstack.h
+│ └── ocstack_stub.c
+├── examples
+│ ├── client
+│ │ ├── MyMultiResourceHandler.cpp
+│ │ ├── MyMultiResourceHandler.h
+│ │ ├── MyObserverHandler.cpp
+│ │ ├── MyObserverHandler.h
+│ │ ├── MyResourceHandler.cpp
+│ │ ├── MyResourceHandler.h
+│ │ └── OCClient.cpp
+│ ├── Makefile
+│ ├── OCWrapper :: TODO :: Unused remove??
+│ │ ├── Makefile
+│ │ ├── parsetest.cpp
+│ │ ├── testClient.cpp
+│ │ ├── testServerApp.cpp
+│ │ └── testServer.cpp
+│ ├── server
+│ │ ├── multiple_resources.cpp
+│ │ └── single_resource.cpp
+│ ├── test_OCClient.cpp
+│ ├── test_OCReflect.cpp
+│ └── test_properties.cpp
+├── include - TODO : Seperate what we expose and what we don't
+│ ├── IClientWrapper.h
+│ ├── InitializeException.h
+│ ├── InProcClientWrapper.h
+│ ├── InProcServerWrapper.h
+│ ├── IServerWrapper.h
+│ ├── OCApi.h
+│ ├── OCException.h
+│ ├── OCObject.h
+│ ├── OCObserver.h
+│ ├── OCObserverHandler.h
+│ ├── OCPlatform.h
+│ ├── OCPlatformHandler.h
+│ ├── OCProperties.h
+│ ├── OCReflect.h
+│ ├── OCResource.h
+│ ├── OCResourceHandler.h
+│ ├── OCSecurityModel.h
+│ ├── OCServer.h :: TODO :: Unused remove??
+│ ├── OutOfProcClientWrapper.h
+│ ├── OutOfProcServerWrapper.h
+│ ├── ResourceInitException.h
+│ └── WrapperFactory.h
+├── Makefile
+├── OCLib
+│ ├── InProcClientWrapper.cpp
+│ ├── InProcServerWrapper.cpp
+│ ├── OCApi.cpp
+│ ├── OCObject.cpp
+│ ├── OCObserver.cpp
+│ ├── OCPlatform.cpp
+│ ├── OCProperties.cpp
+│ ├── OCReflect.cpp
+│ ├── OCResource.cpp
+│ ├── OCSecurityModel.cpp
+│ └── OCServer.cpp :: TODO :: Unused remove??
+└── README - You are reading this.
+
--- /dev/null
+To make the OCTBStack library, run "make" from this directory.
+
+To clean, you have two options:
+
+make clean //Cleans all the *.o and *.a files generated directly from this makefile.
+
+make deepclean //Also cleans the *.o and *.a files generated indirecty from this makefile.
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.oc.ub.sampleclient"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.oc.ub.sampleclient.OCClient"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+</lint>
\ No newline at end of file
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
+android.library.reference.1=../OCLib
--- /dev/null
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="com.oc.ub.sampleclient.OCClient"
+ tools:ignore="MergeRootFrame" />
--- /dev/null
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="com.oc.ub.sampleclient.OCClient$PlaceholderFragment" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/hello_world" />
+
+</RelativeLayout>
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="com.oc.ub.sampleclient.OCClient" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">OCClient</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.ub.sample;
+
+import com.oc.OCObserver;
+import com.oc.annotations.OCInterface;
+import com.oc.annotations.OCProperty;
+
+/**
+ * APPLICATION NOTE: This interface is exposed to via the framework because of the @OCInterface
+ * annotation. Without the annotation, this interface would be ignored by the framework.
+ *
+ * APPLICATION NOTE: This interface needs to be accessible on the client and the server as the
+ * contract for operation.
+ *
+ */
+@OCInterface
+public interface LightControl {
+ /**
+ * APPLICATION NOTE: This is a synchronous request. It will throw immediately if the stack is down
+ * or the network is otherwise not available. It may throw is the remote side does not responds or
+ * returns an error.
+ *
+ * @param powered - The new power state of this implemented interface.
+ */
+ @OCProperty(name = "powered")
+ void setPowered(boolean powered);
+
+ /**
+ * APPLICATION NOTE: This is a synchronous request. It will throw immediately if the stack is down
+ * or the network is otherwise not available. It may throw is the remote side does not responds or
+ * returns an error.
+ *
+ * @return Returns power state of this implemented interface.
+ */
+ @OCProperty(name = "powered")
+ boolean isPowered();
+
+ /**
+ * APPLICATION NOTE: It is the objects responsibility to throw an exception (TBD) if it cannot
+ * handle an additional observers which will in turn return an error to the requestor.
+ *
+ * @param observer the observer that will be notified when a change to the power property has
+ * occurred.
+ */
+ @OCProperty(name = "powered")
+ void addPoweredObserver(OCObserver<Boolean> observer);
+
+ /**
+ * APPLICATION NOTE: Even properties (or methods) that are not annotated are exposed, by default,
+ * via the framework. Getter and setter methods are assumed to be properties unless annotated
+ * otherwise.
+ *
+ * @param level - Sets the power level of this implemented interface.
+ */
+ void setLevel(int level);
+
+ int getLevel();
+
+ /**
+ * APPLICATION NOTE: This is an example of a method. The annotation is not required except to
+ * override the defaults.
+ */
+ void flash();
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.ub.sample;
+
+import com.oc.OCDiscovery;
+import com.oc.OCObserver;
+import com.oc.OCResource;
+import com.oc.OCResourceResultHandler;
+import com.oc.OCServer;
+import com.oc.ub.sampleclient.R;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class OCClient extends Activity {
+ private static String TAG = "OCCLIENT";
+ private OCServer ocServer = null;
+ private OCDiscovery ocDiscovery = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_occlient);
+
+ if (savedInstanceState == null) {
+ getFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment())
+ .commit();
+ }
+
+ ocServer = new OCServer();
+ ocServer.start();
+ ocDiscovery = ocServer.getDiscoverySingleton();
+
+ /*
+ * APPLICATION NOTE: All callbacks will come through on a new thread and will not interfere with
+ * the UI thread or the Framework Thread (i.e. Networking Thread) which means that you need to
+ * use a Handler() to post back to the UI.
+ */
+ ocDiscovery.findResourceByType(null, null, new OCResourceResultHandler() {
+ @Override
+ public void onResourcesFound(String serviceURL, OCResource[] resources) {
+ // NOTE: This means that a service is reporting back zero or more resources
+ // During the callback, lets check to see if the resource supports the
+ // light control interface and turn the light on and then subscribe to any changes in the
+ // light's power state.
+ for (OCResource resource : resources) {
+ try {
+ LightControl control = resource.getInterface(LightControl.class);
+
+ if (control != null) {
+ control.setPowered(true);
+ control.isPowered();
+ /*
+ * APPLICATION NOTE: All callbacks will come through on a new thread and will not
+ * interfere with the UI thread or the Framework Thread (i.e. Networking Thread) which
+ * means that you need to use a Handler() to post back to the UI.
+ */
+ control.addPoweredObserver(new OCObserver<Boolean>() {
+ @Override
+ public void onChanged(Boolean data) {
+ // TODO: Tell the UI! The state of the Light has changed.
+
+ }
+
+ @Override
+ public void onFailed(Throwable throwable) {
+ // TODO: Tell the UI! We are no longer subscribed to events for the Light's power
+ // state.
+ }
+ });
+ }
+ } catch (Exception exception) {
+ // TODO: Ooops
+ }
+ }
+
+ }
+
+ @Override
+ public void onFailed(Throwable throwable) {
+ // TODO: Handle the error. The request to find resources has failed.
+ }
+
+ @Override
+ public void onCompleted() {
+ // Nothing to do here... we are just done finding resources is all.
+ }
+ });
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.occlient, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will automatically handle clicks on the
+ // Home/Up button, so long as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ if (id == R.id.action_settings) {
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ ocServer.stop();
+ }
+
+ /**
+ * A placeholder fragment containing a simple view.
+ */
+ public static class PlaceholderFragment extends Fragment {
+
+ public PlaceholderFragment() {}
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_occlient, container, false);
+ return rootView;
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="com.android.toolchain.gcc.575561395">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.android.toolchain.gcc.575561395" moduleId="org.eclipse.cdt.core.settings" name="Default">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildProperties="" description="" id="com.android.toolchain.gcc.575561395" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+ <folderInfo id="com.android.toolchain.gcc.575561395.1582318103" name="/" resourcePath="">
+ <toolChain id="com.android.toolchain.gcc.1302176685" name="com.android.toolchain.gcc" superClass="com.android.toolchain.gcc">
+ <targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="com.android.targetPlatform.1922697366" isAbstract="false" superClass="com.android.targetPlatform"/>
+ <builder id="com.android.builder.1865026421" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Android Builder" superClass="com.android.builder">
+ <outputEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="obj"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="libs"/>
+ </outputEntries>
+ </builder>
+ <tool id="com.android.gcc.compiler.1723447420" name="Android GCC Compiler" superClass="com.android.gcc.compiler">
+ <inputType id="com.android.gcc.inputType.182436521" superClass="com.android.gcc.inputType"/>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ <sourceEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="jni"/>
+ </sourceEntries>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="OCCoap.null.1195553815" name="OCCoap"/>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <scannerConfigBuildInfo instanceId="com.android.toolchain.gcc.575561395;com.android.toolchain.gcc.575561395.1582318103;com.android.gcc.compiler.1723447420;com.android.gcc.inputType.182436521">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.android.AndroidPerProjectProfile"/>
+ </scannerConfigBuildInfo>
+ </storageModule>
+</cproject>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.oc.coap"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.oc.coap.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+# OCCOAP #
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(CCFL_CORE), )
+CCFL_CORE := $(HOME)/peg_ccfl-core
+endif
+
+ifeq ($(LOGGER_OBJ), )
+LOGGER_OBJ := $(CCFL_CORE)/logger
+endif
+
+ifeq ($(COAP_OBJ), )
+COAP_OBJ := $(CCFL_CORE)/libcoap-4.1.1
+endif
+
+ifeq ($(OCCOAP_OBJ), )
+OCCOAP_OBJ := $(CCFL_CORE)/occoap
+endif
+
+ifeq ($(TB_OBJ), )
+TB_OBJ := $(CCFL_CORE)/stack
+endif
+
+ifeq ($(SOCKET_OBJ), )
+SOCKET_OBJ := $(CCFL_CORE)/ocsocket
+endif
+
+ifeq ($(ANDROID_OBJ), )
+ANDROID_OBJ := $(CCFL_CORE)/android
+endif
+
+#
+# OCSocket
+#
+
+#
+# OCLogger
+#
+include $(CLEAR_VARS)
+TARGET_PLATFORM := android-16
+LOCAL_MODULE := oclogger
+LOCAL_SRC_FILES := $(ANDROID_OBJ)/OCLogger/obj/local/$(TARGET_ARCH_ABI)/libOCLogger.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+# ==============================================================
+# OCCoap - Android
+# ==============================================================
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-16
+
+LOCAL_CPPFLAGS += -D_GLIBCXX__PTHREADS
+LOCAL_CPPFLAGS += -D_THREAD_SAFE
+LOCAL_CPPFLAGS += -D_REENTRANT
+LOCAL_CPPFLAGS += -std=gnu++11
+LOCAL_CPPFLAGS += -s
+LOCAL_CPPFLAGS += -DHAVE_SOCKET_ERRNO
+
+LOCAL_CFLAGS += -DWITH_POSIX
+
+ifneq ($(TARGET_ARCH), $(X86_ARCH))
+ LOCAL_CPPFLAGS += -D__arm__
+endif
+
+X86_ARCH := x86
+
+LOCAL_MODULE := OCCoap
+
+LOCAL_SRC_FILES := $(COAP_OBJ)/async.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/block.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/coap_list.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/debug.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/encode.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/hashkey.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/net.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/option.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/pdu.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/resource.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/str.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/subscribe.c
+LOCAL_SRC_FILES += $(COAP_OBJ)/uri.c
+
+LOCAL_C_INCLUDES := $(COAP_OBJ)
+
+#==
+#== OC STUFF -> Consumes LibCoap stuff
+LOCAL_SRC_FILES += $(OCCOAP_OBJ)/src/occoap.c
+
+LOCAL_C_INCLUDES := $(OCCOAP_OBJ)/include
+LOCAL_C_INCLUDES += $(LOGGER_OBJ)/include
+LOCAL_C_INCLUDES += $(TB_OBJ)/include/
+LOCAL_C_INCLUDES += $(TB_OBJ)/include/internal
+LOCAL_C_INCLUDES += $(SOCKET_OBJ)/include
+
+LOCAL_STATIC_LIBRARIES := oclogger
+#==
+#==
+include $(BUILD_STATIC_LIBRARY)
\ No newline at end of file
--- /dev/null
+APP_STL := gnustl_static #stlport_static
+APP_PLATFORM := android-16
+APP_ABI := armeabi armeabi-v7a x86
+APP_OPTIM := release
+#APP_OPTIM := debug
+APP_CPPFLAGS += -fno-strict-aliasing
+APP_CPPFLAGS += -std=gnu++11
+APP_CPPFLAGS += -D_GLIBCXX_USE_WCHAR_T
+APP_CPPFLAGS += -fexceptions
+APP_CPPFLAGS += -frtti
+#NDK_TOOLCHAIN_VERSION=4.8
\ No newline at end of file
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="com.oc.coap.MainActivity" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">OCCoap</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.oc.sdk"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.oc.DoNotUseUI"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
+android.library=true
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="com.oc.sdk.DoNotUseUI" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">OCLib</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc;
+
+import java.util.HashMap;
+
+public class OCDiscovery {
+ static private native void jniFindResource(String host, HashMap<String, String> filter,
+ OCResourceResultHandler handler);
+
+ /**
+ * Internal API for Service and Resource Discovery
+ *
+ * @param host - Host IP Address of a service to direct resource discovery query. If null or
+ * empty, performs service discovery OR resource discovery query to ALL group members.
+ * @param filter<String FilterType, String Value> - Filter Type - Can be one of two of the link
+ * format equivalent attribute types declared in table 7 of the
+ * OC-Lite-Product-Specification-V1 Document. Either "n" (i.e. Resource Name) or "rt"
+ * (i.e. Resource Type). Value - Can be any valid String that's defined to work with CoRE
+ * Link Attributes as defined in the RFC6690.
+ * @param handler - Handles callbacks, success states and failure states.
+ *
+ * Four modes of discovery defined as follows:
+ * (NULL/Empty, NULL/Empty) - Performs ALL service discovery AND ALL resource discovery.
+ * (NULL/Empty, Not Empty) - Performs query for a filtered/scoped/particular resource(s)
+ * from ALL services.
+ * (Not Empty, NULL/Empty) - Performs ALL resource discovery on a particular service.
+ * (Not Empty, Not Empty) - Performs query for a filtered/scoped/particular resource(s)
+ * from a particular service.
+ *
+ * Thread-Safety: TODO Determine if it is going to be safe to call in a UI thread
+ */
+ private void findResource(String host, HashMap<String, String> filter,
+ OCResourceResultHandler handler) {
+ /*** Have to make sure all values are valid so the pass down to JNI runs smoothly. ***/
+ String tempHost = host;
+ HashMap<String, String> tempFilter = filter;
+ if (host == null) {
+ tempHost = "";
+ }
+ if (filter == null) {
+ tempFilter = new HashMap<String, String>();
+ tempFilter.put("", ""); // TODO: NOt sure if putting an empty key is necessary if the hashmap is empty.
+ }
+ // Todo: Throw exception if handler is invalid (i.e. null).
+ /*** Done ensuring all values are valid. ***/
+ jniFindResource(tempHost, tempFilter, handler);
+ }
+
+ /**
+ * Queries the network for available resources.
+ *
+ * NOTE: This gets posted to a new thread so it doesn't hold the UI or network thread.
+ *
+ * @param serviceURL - The URL to the service. NULL for a broadcast/multicast.
+ * @param resourceType - The resource type filter. NULL for match any.
+ *
+ * @throws This may throw if the service is not started, network is bad, etc.
+ *
+ * Thread-Safety: TODO Determine if it is going to be safe to call in a UI thread
+ */
+ public void findResourceByType(String serviceURL, String resourceType,
+ OCResourceResultHandler handler) {
+ HashMap<String, String> filteredMap = new HashMap<String, String>();
+ filteredMap.put("rt", resourceType);
+ findResource(serviceURL, filteredMap, handler);
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc;
+
+/**
+ *
+ * Represents a basic local resource to be offered to remote services.
+ *
+ */
+public interface OCObject {
+ /**
+ * Determines if the resource should be listed in the well-known core list.
+ *
+ * NOTE: This may be better handled at a different location.
+ *
+ * @return Returns true if resource should be listed.
+ */
+ boolean isVisible();
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc;
+
+import java.util.UUID;
+
+/**
+ *
+ * TODO: Consider including Attachment like java.nio.CompletionHandler
+ *
+ * @param <T>
+ */
+public class OCObserver<T> implements Comparable<OCObserver<T>> {
+ private static UUID observerId = UUID.randomUUID();
+
+ /**
+ *
+ * The OC service calls this at intervals n until the expired callback occurs.
+ *
+ */
+ public void onChanged(T data) {}
+
+ /**
+ * Called if a failure occurred. No more events will occur after this is callback.
+ *
+ * @param throwable - The error that caused this callback sequence to fail.
+ */
+ public void onFailed(Throwable throwable) {}
+
+ @Override
+ public int compareTo(OCObserver<T> another) {
+ return observerId.compareTo(another.getObserverId());
+ }
+
+ /**
+ *
+ * @return observerId associated with this OCObserver object.
+ */
+ UUID getObserverId() {
+ return observerId;
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc;
+
+import java.net.URI;
+import java.util.ArrayList;
+
+/**
+ * Static methods allow you to call to the OC stack, while non-static methods provide traversal
+ * through the tree of hierarchical resources. Non-static methods also retrieve properties of the
+ * current OCResource object.
+ */
+public class OCResource {
+ private OCResource _parent = null;
+ private ArrayList<OCResource> _children = null;
+ private boolean _isContainer = false;
+
+ public OCResource(OCResource parent, ArrayList<OCResource> children, boolean isContainer) {
+ _parent = parent;
+ _children = children;
+ _isContainer = isContainer;
+ }
+
+ OCResource getParent() {
+ return _parent;
+ }
+
+ ArrayList<OCResource> getChildren() {
+ return _children;
+ }
+
+ /**
+ * Recursively gets all the operable resources below this in the tree to a depth of 2.
+ *
+ * @return Returns an ArrayList of operable OCResource objects below this OCResource's position in
+ * the tree.
+ */
+ ArrayList<OCResource> getResource() {
+ return getResources(2);
+ }
+
+ /**
+ * Recursively gets all the operable resources below this in the tree.
+ *
+ * @param depth - The depth to traverse the tree downward.
+ * @return Returns an ArrayList of operable OCResource objects below this OCResource's position in
+ * the tree.
+ */
+ ArrayList<OCResource> getResources(int depth) {
+ if (depth - 1 <= 0) {
+ return null;
+ }
+ ArrayList<OCResource> retRes = new ArrayList<OCResource>();
+ if (_isContainer == true) { // If this is a resource container, add all the resources below me
+ // in my tree.
+ for (OCResource child : getChildren()) {
+ retRes.addAll(child.getResources(depth - 1));
+ }
+ } else {
+ retRes.add(OCResource.this);
+ }
+ return retRes;
+ }
+
+ /**
+ * Recursively gets all the container (i.e. inoperable) resources below this in the tree to a
+ * depth of 2.
+ *
+ * @return Returns an ArrayList of inoperable OCResource objects below this OCResource's position
+ * in the tree.
+ */
+ ArrayList<OCResource> getResourceContainers() {
+ return getResourceContainers(2);
+ }
+
+ /**
+ * Recursively gets all the container (i.e. inoperable) resources below this in the tree.
+ *
+ * @param depth - The depth to traverse the tree downward.
+ *
+ * @return Returns an ArrayList of inoperable OCResource objects below this OCResource's position
+ * in the tree.
+ */
+ ArrayList<OCResource> getResourceContainers(int depth) {
+ if (depth - 1 <= 0) {
+ return null;
+ }
+ ArrayList<OCResource> retRes = new ArrayList<OCResource>();
+ if (_isContainer == true) {
+ for (OCResource child : getChildren()) {
+ retRes.addAll(child.getResourceContainers(depth - 1));
+ }
+ retRes.add(OCResource.this);
+ }
+ return retRes;
+ }
+ /**
+ * Recursively gets all the resources (operable & inoperable) resources below this in the tree
+ * to a depth of 2.
+ *
+ * @return Returns an ArrayList of operable & inoperable OCResource objects below this
+ * OCResource's position in the tree.
+ */
+ ArrayList<OCResource> getAllResources() {
+ return getAllResources(2);
+ }
+
+ /**
+ * Recursively gets all the resources (operable & inoperable) resources below this in the tree.
+ *
+ * @param depth - The depth to traverse the tree downward.
+ *
+ * @return Returns an ArrayList of operable & inoperable OCResource objects below this
+ * OCResource's position in the tree.
+ */
+ ArrayList<OCResource> getAllResources(int depth) {
+ if (depth - 1 <= 0) {
+ return null;
+ }
+ ArrayList<OCResource> retRes = new ArrayList<OCResource>();
+ if (_isContainer == true) {
+ for (OCResource child : getChildren()) {
+ retRes.addAll(child.getAllResources(depth - 1));
+ }
+ retRes.add(OCResource.this);
+ } else {
+ retRes.add(OCResource.this);
+ }
+ return retRes;
+ }
+
+ /**
+ *
+ * @return Returns the resource URI to address this Resource. You can determine the service that
+ * is hosting this resource by parsing this URI.
+ */
+ URI getURI() {
+ return null;
+ }
+
+ /**
+ * Returns the requested interface for this resource
+ *
+ * @param interfaceClass - The interface that is desired.
+ *
+ * @return The interface requested or NULL if not supported.
+ */
+ public <T> T getInterface(java.lang.Class<T> interfaceClass) {
+ return null;
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc;
+
+import java.io.Serializable;
+
+/**
+ *
+ * When a request or command is issued to a resource, an OCResourceResultHandler object must be
+ * passed as a parameter to handle the callback(s).
+ *
+ */
+public interface OCResourceResultHandler extends Serializable {
+ /**
+ *
+ * The OC service calls this repeatedly until completed() or failed() is called.
+ *
+ * @param serviceURI - The URI of the reporting service.
+ * @param resources - The list of resources found on the remote service.
+ */
+ void onResourcesFound(String serviceURI, OCResource[] resources);
+
+ /**
+ * Called after all of the found resource(s) are reported.
+ */
+ void onCompleted();
+
+ /**
+ * Called if a failure occurred. No resources will be reported after this callback.
+ *
+ * @param throwable - The error that caused this callback sequence to fail.
+ */
+ void onFailed(Throwable throwable);
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc;
+
+import java.net.URI;
+
+/**
+ *
+ * This class (or interface) provides methods to determine whether a remote request is allowed to a
+ * resource.
+ *
+ */
+public class OCSecurityModel {
+
+ public OCSecurityModel() {
+ // TODO Auto-generated constructor stub
+ }
+
+ public void checkAccess(URI sourceURI, URI destinationURI, int encryptionLevel, int remoteIdentity) {
+ // TODO: Need to define...
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc;
+
+/**
+ * This represents a running open connection server.
+ *
+ * WARNING: This may change to an interface so that we may transition to a factory pattern
+ *
+ */
+public class OCServer {
+ private native void jniRegisterResource(OCObject object, String url);
+
+ private native void jniUnregisterResource(OCObject object);
+
+ private native void jniStartOCServer();
+
+ private native void jniStopOCServer();
+
+ private native OCDiscovery jniGetDiscoverySingleton();
+
+ /**
+ * Constructor for OCService.
+ */
+ public OCServer() {}
+
+ /**
+ * This registers a security model for access control to resources under this service.
+ *
+ * @param model - Security Model required for access to this service and control/view of it's
+ * services.
+ */
+ public void setSecurityModel(OCSecurityModel model) {
+ // Todo: Pat, What will we do here?
+ }
+
+ /**
+ * Registers a resource with the service.
+ *
+ * @param object - The OCObject that handles the resource requests
+ * @param url - The URL under the resource.
+ * @param accessControl - The access control handler that determines whether the remote device is
+ * allowed to access this resource. If NULL, all access is granted.
+ */
+ public void registerResource(OCObject object, String url/* TODO: , AccessControl accessControl */) {
+ jniRegisterResource(object, url);
+ }
+
+ /**
+ * Unregisters a resource with the service.
+ *
+ * @param object - The OCObject to be unregistered.
+ */
+ public void unregisterResource(OCObject object) {
+ jniUnregisterResource(object);
+ }
+
+ /**
+ * Starts the open connectivity service.
+ *
+ * Thread-Safety: TODO Determine if it is going to be safe to call in a UI thread
+ */
+ public void start() {
+ jniStartOCServer();
+ }
+
+ /**
+ * Stops the open connectivity service.
+ *
+ * Thread-Safety: TODO Determine if it is going to be safe to call in a UI thread
+ */
+ public void stop() {
+ jniStopOCServer();
+ }
+
+ /**
+ * Retrieves access to discovery APIs via the Discovery Singleton delegated by the SDK. Delegation
+ * is limited to just one singleton per OCServer object.
+ *
+ * @return Returns an object which permits access to the open connectivity discovery APIs to just
+ * one discovery singleton object.
+ *
+ * @throws //TODO throws an exception when the discovery singleton has already been checked out.
+ */
+ public OCDiscovery getDiscoverySingleton() {
+ return jniGetDiscoverySingleton();
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.annotations;
+
+/**
+ *
+ * Base OCInterface Interface. Integral piece used to describe a resource's functionality OTA.
+ *
+ */
+public @interface OCInterface {
+ String name() default "";
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.annotations;
+
+/**
+ *
+ * Base OCMethod Interface. Integral piece used to describe a resource's functionality OTA.
+ *
+ */
+public @interface OCMethod {
+ String name() default "";
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.annotations;
+
+/**
+ *
+ * Base OCProperty Interface. Integral piece used to describe a resource's functionality OTA.
+ *
+ */
+public @interface OCProperty {
+ String name() default "";
+
+ String type() default "";
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="com.android.toolchain.gcc.1440046252">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.android.toolchain.gcc.1440046252" moduleId="org.eclipse.cdt.core.settings" name="Default">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildProperties="" description="" id="com.android.toolchain.gcc.1440046252" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+ <folderInfo id="com.android.toolchain.gcc.1440046252.1314584192" name="/" resourcePath="">
+ <toolChain id="com.android.toolchain.gcc.1881071196" name="com.android.toolchain.gcc" superClass="com.android.toolchain.gcc">
+ <targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="com.android.targetPlatform.1013766009" isAbstract="false" superClass="com.android.targetPlatform"/>
+ <builder id="com.android.builder.1764929546" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Android Builder" superClass="com.android.builder">
+ <outputEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="obj"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="libs"/>
+ </outputEntries>
+ </builder>
+ <tool id="com.android.gcc.compiler.1727775847" name="Android GCC Compiler" superClass="com.android.gcc.compiler">
+ <inputType id="com.android.gcc.inputType.352036501" superClass="com.android.gcc.inputType"/>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ <sourceEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="jni"/>
+ </sourceEntries>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="OCLogger.null.1557157764" name="OCLogger"/>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <scannerConfigBuildInfo instanceId="com.android.toolchain.gcc.1440046252;com.android.toolchain.gcc.1440046252.1314584192;com.android.gcc.compiler.1727775847;com.android.gcc.inputType.352036501">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.android.AndroidPerProjectProfile"/>
+ </scannerConfigBuildInfo>
+ </storageModule>
+</cproject>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.oc.logger"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.oc.logger.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+# LOGGER #
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(CCFL_CORE), )
+CCFL_CORE := $(HOME)/peg_ccfl-core
+endif
+
+ifeq ($(LOGGER_OBJ), )
+LOGGER_OBJ := $(CCFL_CORE)/logger
+endif
+
+# ==============================================================
+# OCLogger - Android
+# ==============================================================
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-16
+
+LOCAL_CPPFLAGS += -D_GLIBCXX__PTHREADS
+LOCAL_CPPFLAGS += -D_THREAD_SAFE
+LOCAL_CPPFLAGS += -D_REENTRANT
+LOCAL_CPPFLAGS += -std=gnu++11
+LOCAL_CPPFLAGS += -s
+LOCAL_CPPFLAGS += -DHAVE_SOCKET_ERRNO
+
+ifneq ($(TARGET_ARCH), $(X86_ARCH))
+ LOCAL_CPPFLAGS += -D__arm__
+endif
+
+X86_ARCH := x86
+
+LOCAL_MODULE := OCLogger
+
+LOCAL_SRC_FILES := $(LOGGER_OBJ)/src/logger.c
+
+LOCAL_C_INCLUDES := $(LOGGER_OBJ)/include
+
+LOCAL_STATIC_LIBRARIES += tbstack
+
+include $(BUILD_STATIC_LIBRARY)
\ No newline at end of file
--- /dev/null
+APP_STL := gnustl_static #stlport_static
+APP_PLATFORM := android-16
+APP_ABI := armeabi armeabi-v7a x86
+APP_OPTIM := release
+#APP_OPTIM := debug
+APP_CPPFLAGS += -fno-strict-aliasing
+APP_CPPFLAGS += -std=gnu++11
+APP_CPPFLAGS += -D_GLIBCXX_USE_WCHAR_T
+APP_CPPFLAGS += -fexceptions
+APP_CPPFLAGS += -frtti
+#NDK_TOOLCHAIN_VERSION=4.8
\ No newline at end of file
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="com.oc.logger.MainActivity" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">OCLogger</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.oc.ub.sampleclient"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.oc.ub.sample.OCService"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8"?>
+<lint>
+</lint>
\ No newline at end of file
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
+android.library.reference.1=../OCLib
--- /dev/null
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="com.oc.ub.sample.OCService"
+ tools:ignore="MergeRootFrame" />
--- /dev/null
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="com.oc.ub.sample.OCClient$PlaceholderFragment" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/hello_world" />
+
+</RelativeLayout>
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="com.oc.ub.sampleclient.OCClient" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">OCClient</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.ub.sample;
+
+import com.oc.OCObserver;
+import com.oc.annotations.OCInterface;
+import com.oc.annotations.OCProperty;
+
+/**
+ * APPLICATION NOTE: This interface is exposed to via the framework because of the @OCInterface
+ * annotation. Without the annotation, this interface would be ignored by the framework.
+ *
+ * APPLICATION NOTE: This interface needs to be accessible on the client and the server as the
+ * contract for operation.
+ *
+ */
+@OCInterface
+public interface LightControl {
+ /**
+ * APPLICATION NOTE: This is a synchronous request. It will throw immediately if the stack is down
+ * or the network is otherwise not available. It may throw is the remote side does not responds or
+ * returns an error.
+ *
+ * @param powered - The new power state of this implemented interface.
+ */
+ @OCProperty(name = "powered")
+ void setPowered(boolean powered);
+
+ /**
+ * APPLICATION NOTE: This is a synchronous request. It will throw immediately if the stack is down
+ * or the network is otherwise not available. It may throw is the remote side does not responds or
+ * returns an error.
+ *
+ * @return Returns power state of this implemented interface.
+ */
+ @OCProperty(name = "powered")
+ boolean isPowered();
+
+ /**
+ * APPLICATION NOTE: It is the objects responsibility to throw an exception (TBD) if it cannot
+ * handle an additional observers which will in turn return an error to the requestor.
+ *
+ * @param observer the observer that will be notified when a change to the power property has
+ * occurred.
+ */
+ @OCProperty(name = "powered")
+ void addPoweredObserver(OCObserver<Boolean> observer);
+
+ /**
+ *
+ * @param observer the observer that will be no longer notified when a change to the power
+ * property has occurred.
+ */
+ @OCProperty(name = "powered")
+ void removePoweredObserver(OCObserver<Boolean> observer);
+
+ /**
+ * APPLICATION NOTE: Even properties (or methods) that are not annotated are exposed, by default,
+ * via the framework. Getter and setter methods are assumed to be properties unless annotated
+ * otherwise.
+ *
+ * @param level - Sets the power level of this implemented interface.
+ */
+ void setLevel(int level);
+
+ int getLevel();
+
+ /**
+ * APPLICATION NOTE: This is an example of a method. The annotation is not required except to
+ * override the defaults.
+ */
+ void flash();
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.ub.sample;
+
+import com.oc.OCObject;
+import com.oc.OCObserver;
+
+public class MyLight implements OCObject, LightControl {
+
+ public MyLight() {
+ // TODO Auto-generated constructor stub
+ }
+
+ @Override
+ public boolean isVisible() {
+ return true;
+ }
+
+ @Override
+ public void setPowered(boolean powered) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean isPowered() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void setLevel(int level) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public int getLevel() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ @Override
+ public void flash() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void addPoweredObserver(OCObserver<Boolean> observer) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public void removePoweredObserver(OCObserver<Boolean> observer) {
+ // TODO Auto-generated method stub
+
+ }
+
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.ub.sample;
+
+import com.oc.OCSecurityModel;
+import com.oc.OCServer;
+import com.oc.ub.sampleclient.R;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.os.Bundle;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+
+public class OCService extends Activity {
+ private static String TAG = "OCCLIENT";
+ private OCServer service = null;
+ private MyLight resource = null;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.activity_occlient);
+
+ if (savedInstanceState == null) {
+ getFragmentManager().beginTransaction().add(R.id.container, new PlaceholderFragment())
+ .commit();
+ }
+
+ // NOTE: We throw exceptions for the bad errors... so no return codes
+ try {
+ // In a complete example, the MyLight class should have callback to
+ // update the UI
+ resource = new MyLight();
+ service = new OCServer();
+ service.setSecurityModel(new OCSecurityModel());
+ // TODO: Mats, will we allow one resource to be mapped to two URLs???
+ service.registerResource(resource, "/light/a");
+ // TODO: Mats, will we allow one resource to be mapped to two URLs???
+ // service.registerResource(resource, "/light/b", new OCAccessHandler());
+ service.start();
+ } catch (Exception exception) {
+ finish();
+ }
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+
+ // Inflate the menu; this adds items to the action bar if it is present.
+ getMenuInflater().inflate(R.menu.occlient, menu);
+ return true;
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ // Handle action bar item clicks here. The action bar will automatically handle clicks on the
+ // Home/Up button, so long as you specify a parent activity in AndroidManifest.xml.
+ int id = item.getItemId();
+ if (id == R.id.action_settings) {
+ return true;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ try {
+ service.unregisterResource(resource);
+ service.stop();
+ } catch (Exception exception) {
+ // TODO: Handle exception
+ }
+ }
+
+ /**
+ * A placeholder fragment containing a simple view.
+ */
+ public static class PlaceholderFragment extends Fragment {
+
+ public PlaceholderFragment() {}
+
+ @Override
+ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ View rootView = inflater.inflate(R.layout.fragment_occlient, container, false);
+ return rootView;
+ }
+ }
+}
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="com.android.toolchain.gcc.1426311490">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.android.toolchain.gcc.1426311490" moduleId="org.eclipse.cdt.core.settings" name="Default">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildProperties="" description="" id="com.android.toolchain.gcc.1426311490" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+ <folderInfo id="com.android.toolchain.gcc.1426311490.1733532201" name="/" resourcePath="">
+ <toolChain id="com.android.toolchain.gcc.352787744" name="com.android.toolchain.gcc" superClass="com.android.toolchain.gcc">
+ <targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="com.android.targetPlatform.337072217" isAbstract="false" superClass="com.android.targetPlatform"/>
+ <builder id="com.android.builder.1915838722" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Android Builder" superClass="com.android.builder">
+ <outputEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="obj"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="libs"/>
+ </outputEntries>
+ </builder>
+ <tool id="com.android.gcc.compiler.1402101219" name="Android GCC Compiler" superClass="com.android.gcc.compiler">
+ <inputType id="com.android.gcc.inputType.1695670066" superClass="com.android.gcc.inputType"/>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ <sourceEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="jni"/>
+ </sourceEntries>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="OCSocket.null.794191193" name="OCSocket"/>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <scannerConfigBuildInfo instanceId="com.android.toolchain.gcc.1426311490;com.android.toolchain.gcc.1426311490.1733532201;com.android.gcc.compiler.1402101219;com.android.gcc.inputType.1695670066">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.android.AndroidPerProjectProfile"/>
+ </scannerConfigBuildInfo>
+ </storageModule>
+</cproject>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.oc.socket"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.oc.socket.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+# LOGGER #
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(CCFL_CORE), )
+CCFL_CORE := $(HOME)/peg_ccfl-core
+endif
+
+ifeq ($(LOGGER_OBJ), )
+LOGGER_OBJ := $(CCFL_CORE)/logger
+endif
+
+ifeq ($(SOCKET_OBJ), )
+SOCKET_OBJ := $(CCFL_CORE)/ocsocket
+endif
+
+ifeq ($(ANDROID_OBJ), )
+ANDROID_OBJ := $(CCFL_CORE)/android
+endif
+
+#
+# OCLogger
+#
+include $(CLEAR_VARS)
+TARGET_PLATFORM := android-16
+LOCAL_MODULE := oclogger
+LOCAL_SRC_FILES := $(ANDROID_OBJ)/OCLogger/obj/local/$(TARGET_ARCH_ABI)/libOCLogger.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+# ==============================================================
+# OCLogger - Android
+# ==============================================================
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-16
+
+LOCAL_CPPFLAGS += -D_GLIBCXX__PTHREADS
+LOCAL_CPPFLAGS += -D_THREAD_SAFE
+LOCAL_CPPFLAGS += -D_REENTRANT
+LOCAL_CPPFLAGS += -std=gnu++11
+LOCAL_CPPFLAGS += -s
+LOCAL_CPPFLAGS += -DHAVE_SOCKET_ERRNO
+
+ifneq ($(TARGET_ARCH), $(X86_ARCH))
+ LOCAL_CPPFLAGS += -D__arm__
+endif
+
+X86_ARCH := x86
+
+LOCAL_MODULE := OCSocket
+
+LOCAL_SRC_FILES := $(SOCKET_OBJ)/src/ocsocket.c
+
+LOCAL_C_INCLUDES := $(SOCKET_OBJ)/include
+LOCAL_C_INCLUDES += $(LOGGER_OBJ)/include
+
+LOCAL_STATIC_LIBRARIES := oclogger
+
+include $(BUILD_STATIC_LIBRARY)
\ No newline at end of file
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
--- /dev/null
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="com.oc.socket.MainActivity"
+ tools:ignore="MergeRootFrame" />
--- /dev/null
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="com.oc.socket.MainActivity$PlaceholderFragment" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/hello_world" />
+
+</RelativeLayout>
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="com.oc.socket.MainActivity" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">OCSocket</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="com.android.toolchain.gcc.349996057">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.android.toolchain.gcc.349996057" moduleId="org.eclipse.cdt.core.settings" name="Default">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildProperties="" description="" id="com.android.toolchain.gcc.349996057" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+ <folderInfo id="com.android.toolchain.gcc.349996057.1780633097" name="/" resourcePath="">
+ <toolChain id="com.android.toolchain.gcc.125309616" name="com.android.toolchain.gcc" superClass="com.android.toolchain.gcc">
+ <targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="com.android.targetPlatform.1214096925" isAbstract="false" superClass="com.android.targetPlatform"/>
+ <builder id="com.android.builder.835771544" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Android Builder" superClass="com.android.builder">
+ <outputEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="obj"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="libs"/>
+ </outputEntries>
+ </builder>
+ <tool id="com.android.gcc.compiler.1899262912" name="Android GCC Compiler" superClass="com.android.gcc.compiler">
+ <inputType id="com.android.gcc.inputType.525348316" superClass="com.android.gcc.inputType"/>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ <sourceEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="jni"/>
+ </sourceEntries>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="OCTBStack.null.2079343911" name="OCTBStack"/>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <scannerConfigBuildInfo instanceId="com.android.toolchain.gcc.349996057;com.android.toolchain.gcc.349996057.1780633097;com.android.gcc.compiler.1899262912;com.android.gcc.inputType.525348316">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.android.AndroidPerProjectProfile"/>
+ </scannerConfigBuildInfo>
+ </storageModule>
+</cproject>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.oc.tbstack"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.oc.tbstack.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+# TBSTACK #
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(CCFL_CORE), )
+CCFL_CORE := $(HOME)/peg_ccfl-core
+endif
+
+ifeq ($(OCCOAP_OBJ), )
+OCCOAP_OBJ := $(CCFL_CORE)/occoap
+endif
+
+ifeq ($(TB_OBJ), )
+TB_OBJ := $(CCFL_CORE)/stack
+endif
+
+ifeq ($(LOGGER_OBJ), )
+LOGGER_OBJ := $(CCFL_CORE)/logger
+endif
+
+ifeq ($(ANDROID_OBJ), )
+ANDROID_OBJ := $(CCFL_CORE)/android
+endif
+
+#
+# OCCoap
+#
+include $(CLEAR_VARS)
+TARGET_PLATFORM := android-16
+LOCAL_MODULE := occoap
+LOCAL_SRC_FILES := $(ANDROID_OBJ)/OCCoap/obj/local/$(TARGET_ARCH_ABI)/libOCCoap.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+# ==============================================================
+# OCLib - Android
+# ==============================================================
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-16
+
+LOCAL_CPPFLAGS += -D_GLIBCXX__PTHREADS
+LOCAL_CPPFLAGS += -D_THREAD_SAFE
+LOCAL_CPPFLAGS += -D_REENTRANT
+LOCAL_CPPFLAGS += -std=gnu++11
+LOCAL_CPPFLAGS += -s
+LOCAL_CPPFLAGS += -DHAVE_SOCKET_ERRNO
+
+ifneq ($(TARGET_ARCH), $(X86_ARCH))
+ LOCAL_CPPFLAGS += -D__arm__
+endif
+
+X86_ARCH := x86
+
+LOCAL_MODULE := TBStack
+
+LOCAL_SRC_FILES := $(TB_OBJ)/src/ocstack.c
+
+LOCAL_C_INCLUDES := $(TB_OBJ)/include/
+LOCAL_C_INCLUDES += $(TB_OBJ)/include/internal
+LOCAL_C_INCLUDES += $(OCCOAP_OBJ)/include
+LOCAL_C_INCLUDES += $(LOGGER_OBJ)/include
+
+LOCAL_STATIC_LIBRARIES += occoap
+
+include $(BUILD_STATIC_LIBRARY)
\ No newline at end of file
--- /dev/null
+APP_STL := gnustl_static #stlport_static
+APP_PLATFORM := android-16
+APP_ABI := armeabi armeabi-v7a x86
+APP_OPTIM := release
+#APP_OPTIM := debug
+APP_CPPFLAGS += -fno-strict-aliasing
+APP_CPPFLAGS += -std=gnu++11
+APP_CPPFLAGS += -D_GLIBCXX_USE_WCHAR_T
+APP_CPPFLAGS += -fexceptions
+APP_CPPFLAGS += -frtti
+#NDK_TOOLCHAIN_VERSION=4.8
\ No newline at end of file
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="com.oc.tbstack.MainActivity" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">OCTBStack</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="com.android.toolchain.gcc.381295911">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="com.android.toolchain.gcc.381295911" moduleId="org.eclipse.cdt.core.settings" name="Default">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.VCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.MakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration artifactName="${ProjName}" buildProperties="" description="" id="com.android.toolchain.gcc.381295911" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+ <folderInfo id="com.android.toolchain.gcc.381295911.1997622459" name="/" resourcePath="">
+ <toolChain id="com.android.toolchain.gcc.151998350" name="com.android.toolchain.gcc" superClass="com.android.toolchain.gcc">
+ <targetPlatform binaryParser="org.eclipse.cdt.core.ELF" id="com.android.targetPlatform.290641337" isAbstract="false" superClass="com.android.targetPlatform"/>
+ <builder id="com.android.builder.304245466" keepEnvironmentInBuildfile="false" managedBuildOn="false" name="Android Builder" superClass="com.android.builder">
+ <outputEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="obj"/>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="outputPath" name="libs"/>
+ </outputEntries>
+ </builder>
+ <tool id="com.android.gcc.compiler.452595244" name="Android GCC Compiler" superClass="com.android.gcc.compiler">
+ <inputType id="com.android.gcc.inputType.1076381239" superClass="com.android.gcc.inputType"/>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ <sourceEntries>
+ <entry flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name="jni"/>
+ </sourceEntries>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="OCUBStack.null.1393135280" name="OCUBStack"/>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ <scannerConfigBuildInfo instanceId="com.android.toolchain.gcc.381295911;com.android.toolchain.gcc.381295911.1997622459;com.android.gcc.compiler.452595244;com.android.gcc.inputType.1076381239">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.android.AndroidPerProjectProfile"/>
+ </scannerConfigBuildInfo>
+ </storageModule>
+</cproject>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.oc.ubstack"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+
+ <application
+ android:allowBackup="true"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <activity
+ android:name="com.oc.ubstack.MainActivity"
+ android:label="@string/app_name" >
+ <intent-filter>
+ <action android:name="android.intent.action.MAIN" />
+
+ <category android:name="android.intent.category.LAUNCHER" />
+ </intent-filter>
+ </activity>
+ </application>
+
+</manifest>
--- /dev/null
+# UBSTACK #
+LOCAL_PATH := $(call my-dir)
+
+ifeq ($(CCFL_CORE), )
+CCFL_CORE := $(HOME)/peg_ccfl-core
+endif
+
+ifeq ($(UB_OBJ), )
+UB_OBJ := $(CCFL_CORE)/ubstack
+endif
+
+ifeq ($(TB_OBJ), )
+TB_OBJ := $(CCFL_CORE)/stack
+endif
+
+ifeq ($(ANDROID_OBJ), )
+ANDROID_OBJ := $(CCFL_CORE)/android
+endif
+
+ifeq ($(LOGGER_OBJ), )
+LOGGER_OBJ := $(CCFL_CORE)/logger
+endif
+
+ifeq ($(BOOST_OBJ), )
+BOOST_OBJ := $(HOME)/android-dev/boost/android
+endif
+
+#
+# TBStack
+#
+include $(CLEAR_VARS)
+TARGET_PLATFORM := android-16
+LOCAL_MODULE := tbstack
+LOCAL_SRC_FILES := $(ANDROID_OBJ)/OCTBStack/obj/local/$(TARGET_ARCH_ABI)/libTBStack.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+#
+# OCCoap
+#
+include $(CLEAR_VARS)
+TARGET_PLATFORM := android-16
+LOCAL_MODULE := occoap
+LOCAL_SRC_FILES := $(ANDROID_OBJ)/OCCoap/obj/local/$(TARGET_ARCH_ABI)/libOCCoap.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+#
+# OCLogger
+#
+include $(CLEAR_VARS)
+TARGET_PLATFORM := android-16
+LOCAL_MODULE := oclogger
+LOCAL_SRC_FILES := $(ANDROID_OBJ)/OCLogger/obj/local/$(TARGET_ARCH_ABI)/libOCLogger.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+#
+# Boost
+#
+include $(CLEAR_VARS)
+TARGET_PLATFORM := android-16
+LOCAL_MODULE := boost_thread
+LOCAL_SRC_FILES := $(BOOST_OBJ)/$(TARGET_ARCH_ABI)/lib/libboost_thread-gcc-mt-1_49.a
+include $(PREBUILT_STATIC_LIBRARY)
+
+# ==============================================================
+# UBStack - Android
+# ==============================================================
+include $(CLEAR_VARS)
+
+TARGET_PLATFORM := android-16
+
+LOCAL_CPPFLAGS += -D_GLIBCXX__PTHREADS
+LOCAL_CPPFLAGS += -D_THREAD_SAFE
+LOCAL_CPPFLAGS += -D_REENTRANT
+LOCAL_CPPFLAGS += -std=gnu++11
+LOCAL_CPPFLAGS += -s
+LOCAL_CPPFLAGS += -DHAVE_SOCKET_ERRNO
+
+ifneq ($(TARGET_ARCH), $(X86_ARCH))
+ LOCAL_CPPFLAGS += -D__arm__
+endif
+
+X86_ARCH := x86
+
+LOCAL_MODULE := UBStack
+
+LOCAL_SRC_FILES := $(UB_OBJ)/src/ocmodelimpl.cpp
+
+LOCAL_C_INCLUDES := $(UB_OBJ)/src
+LOCAL_C_INCLUDES += $(UB_OBJ)/include
+LOCAL_C_INCLUDES += $(TB_OBJ)/include
+LOCAL_C_INCLUDES += $(TB_OBJ)/internal
+LOCAL_C_INCLUDES += $(LOGGER_OBJ)/include
+
+LOCAL_C_INCLUDES += $(BOOST_OBJ)/include
+
+LOCAL_STATIC_LIBRARIES := tbstack
+LOCAL_STATIC_LIBRARIES += oclogger
+LOCAL_STATIC_LIBRARIES += boost_thread
+LOCAL_STATIC_LIBRARIES += occoap
+
+include $(BUILD_SHARED_LIBRARY)
\ No newline at end of file
--- /dev/null
+APP_STL := gnustl_static #stlport_static
+APP_PLATFORM := android-16
+APP_ABI := armeabi armeabi-v7a x86
+APP_OPTIM := release
+#APP_OPTIM := debug
+APP_CPPFLAGS += -fno-strict-aliasing
+APP_CPPFLAGS += -std=gnu++11
+APP_CPPFLAGS += -D_GLIBCXX_USE_WCHAR_T
+APP_CPPFLAGS += -fexceptions
+APP_CPPFLAGS += -frtti
+#NDK_TOOLCHAIN_VERSION=4.8
\ No newline at end of file
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="com.oc.ubstack.MainActivity" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">OCUBStack</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.oc.unittests"
+ android:versionCode="1"
+ android:versionName="1.0" >
+
+ <uses-sdk
+ android:minSdkVersion="16"
+ android:targetSdkVersion="16" />
+
+
+ <instrumentation android:name="android.test.InstrumentationTestRunner"
+ android:targetPackage="com.oc.unittests"
+ android:label="All Unit Tests" />
+
+ <application
+ android:allowBackup="true"
+ android:icon="@drawable/ic_launcher"
+ android:label="@string/app_name"
+ android:theme="@style/AppTheme" >
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+</manifest>
--- /dev/null
+# To enable ProGuard in your project, edit project.properties
+# to define the proguard.config property as described in that file.
+#
+# Add project specific ProGuard rules here.
+# By default, the flags in this file are appended to flags specified
+# in ${sdk.dir}/tools/proguard/proguard-android.txt
+# You can edit the include path and order by changing the ProGuard
+# include property in project.properties.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# Add any project specific keep options here:
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
--- /dev/null
+# This file is automatically generated by Android Tools.
+# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
+#
+# This file must be checked in Version Control Systems.
+#
+# To customize properties used by the Ant build system edit
+# "ant.properties", and override values to adapt the script to your
+# project structure.
+#
+# To enable ProGuard to shrink and obfuscate your code, uncomment this (available properties: sdk.dir, user.home):
+#proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
+
+# Project target.
+target=android-16
+android.library.reference.1=../OCLib
--- /dev/null
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:id="@+id/container"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ tools:context="com.oc.unittests.UnitTestsActivity"
+ tools:ignore="MergeRootFrame" />
--- /dev/null
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingBottom="@dimen/activity_vertical_margin"
+ android:paddingLeft="@dimen/activity_horizontal_margin"
+ android:paddingRight="@dimen/activity_horizontal_margin"
+ android:paddingTop="@dimen/activity_vertical_margin"
+ tools:context="com.oc.unittests.UnitTestsActivity$PlaceholderFragment" >
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:text="@string/hello_world" />
+
+</RelativeLayout>
--- /dev/null
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ tools:context="com.oc.unittests.UnitTestsActivity" >
+
+ <item
+ android:id="@+id/action_settings"
+ android:orderInCategory="100"
+ android:showAsAction="never"
+ android:title="@string/action_settings"/>
+
+</menu>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 11+. This theme completely replaces
+ AppBaseTheme from res/values/styles.xml on API 11+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light">
+ <!-- API 11 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme for API 14+. This theme completely replaces
+ AppBaseTheme from BOTH res/values/styles.xml and
+ res/values-v11/styles.xml on API 14+ devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Holo.Light.DarkActionBar">
+ <!-- API 14 theme customizations can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Example customization of dimensions originally defined in res/values/dimens.xml
+ (such as screen margins) for screens with more than 820dp of available width. This
+ would include 7" and 10" devices in landscape (~960dp and ~1280dp respectively).
+ -->
+ <dimen name="activity_horizontal_margin">64dp</dimen>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!-- Default screen margins, per the Android Design guidelines. -->
+ <dimen name="activity_horizontal_margin">16dp</dimen>
+ <dimen name="activity_vertical_margin">16dp</dimen>
+
+</resources>
--- /dev/null
+<?xml version="1.0" encoding="utf-8"?>
+<resources>
+
+ <string name="app_name">UnitTests</string>
+ <string name="hello_world">Hello world!</string>
+ <string name="action_settings">Settings</string>
+
+</resources>
--- /dev/null
+<resources>
+
+ <!--
+ Base application theme, dependent on API level. This theme is replaced
+ by AppBaseTheme from res/values-vXX/styles.xml on newer devices.
+ -->
+ <style name="AppBaseTheme" parent="android:Theme.Light">
+ <!--
+ Theme customizations available in newer API levels can go in
+ res/values-vXX/styles.xml, while customizations related to
+ backward-compatibility can go here.
+ -->
+ </style>
+
+ <!-- Application theme. -->
+ <style name="AppTheme" parent="AppBaseTheme">
+ <!-- All customizations that are NOT specific to a particular API-level can go here. -->
+ </style>
+
+</resources>
--- /dev/null
+To run this project as a unit test:
+
+Right-click on project->Run As->JUnit Test (Do not select "Android JUnit Test"!!!!!!)
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.unittests;
+
+import static org.junit.Assert.*;
+import junit.framework.Assert;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.oc.OCDiscovery;
+import com.oc.OCObserver;
+import com.oc.OCResource;
+import com.oc.OCResourceResultHandler;
+import com.oc.OCSecurityModel;
+import com.oc.OCServer;
+
+public class UnitTest {
+ private OCServer clientService = null;
+ private OCServer serverService = null;
+ private OCDiscovery ocDiscovery = null;
+ private UnitTestResource serverResource = null;
+
+ @Before
+ public void init() throws Exception {
+ clientService = new OCServer();
+ clientService.start();
+ ocDiscovery = clientService.getDiscoverySingleton();
+ }
+
+ @After
+ public void destroy() throws Exception {
+ try {
+ clientService.stop();
+ clientService = null;
+ serverService.unregisterResource(serverResource);
+ serverService.stop();
+ } catch (Exception exception) {
+ // TODO: Handle exception
+ }
+ }
+
+ @Test
+ public void findMyself() {
+ client();
+ server();
+ }
+
+ @SuppressWarnings("serial")
+ public void client() {
+ assertNotNull(clientService);
+
+ /*
+ * APPLICATION NOTE: All callbacks will come through on a new thread and will not interfere with
+ * the UI thread or the Framework Thread (i.e. Networking Thread) which means that you need to
+ * use a Handler() to post back to the UI.
+ */
+ ocDiscovery.findResourceByType(null, null, new OCResourceResultHandler() {
+ @Override
+ public void onResourcesFound(String serviceURL, OCResource[] resources) {
+ // NOTE: This means that a service is reporting back zero or more resources
+ // During the callback, lets check to see if the resource supports the
+ // light control interface and turn the light on and then subscribe to any changes in the
+ // light's power state.
+ for (OCResource resource : resources) {
+ try {
+ UnitTestControlItf control = resource.getInterface(UnitTestControlItf.class);
+ assertNotNull(control);
+ if (control != null) {
+ control.setState(true);
+ control.isTrue();
+
+ Assert.assertEquals(true, control.isTrue());
+
+ /*
+ * APPLICATION NOTE: All callbacks will come through on a new thread and will not
+ * interfere with the UI thread or the Framework Thread (i.e. Networking Thread) which
+ * means that you need to use a Handler() to post back to the UI.
+ */
+ control.addMyUnitTestObserver(new OCObserver<Boolean>() {
+ @Override
+ public void onChanged(Boolean data) {
+ // TODO: Tell the UI! The state of the Light has changed.
+
+ }
+
+ @Override
+ public void onFailed(Throwable throwable) {
+ // TODO: Tell the UI! We are no longer subscribed to events for the Light's power
+ // state.
+ }
+ });
+ }
+ } catch (Exception exception) {
+ // TODO: Ooops
+ }
+ }
+
+ }
+
+ @Override
+ public void onFailed(Throwable throwable) {
+ // TODO: Handle the error. The request to find resources has failed.
+ }
+
+ @Override
+ public void onCompleted() {
+ // Nothing to do here... we are just done finding resources is all.
+ }
+ });
+ }
+
+ public void server() {
+ // NOTE: We throw exceptions for the bad errors... so no return codes
+ try {
+ // In a complete example, the MyLight class should have callback to
+ // update the UI
+ serverResource = new UnitTestResource();
+ serverService = new OCServer();
+ serverService.setSecurityModel(new OCSecurityModel());
+ // TODO: Mats, will we allow one resource to be mapped to two URLs???
+ serverService.registerResource(serverResource, "/ResourceTypeGoesHere/a");
+ // TODO: Mats, will we allow one resource to be mapped to two URLs???
+ // service.registerResource(resource, "/light/b", new OCAccessHandler());
+ serverService.start();
+ } catch (Exception exception) {
+ // finish();
+ return; // End the application.
+ }
+ }
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.unittests;
+
+import com.oc.OCObserver;
+import com.oc.annotations.OCInterface;
+import com.oc.annotations.OCProperty;
+
+@OCInterface
+public interface UnitTestControlItf {
+ /**
+ * APPLICATION NOTE: This is a synchronous request. It will throw immediately if the stack is down
+ * or the network is otherwise not available. It may throw if the remote side does not responds or
+ * returns an error.
+ *
+ * @param state - The new state of this implemented interface.
+ */
+ @OCProperty(name = "UnitTestName")
+ void setState(boolean state);
+
+ /**
+ * APPLICATION NOTE: This is a synchronous request. It will throw immediately if the stack is down
+ * or the network is otherwise not available. It may throw is the remote side does not responds or
+ * returns an error.
+ *
+ * @return Returns state of this implemented interface.
+ */
+ @OCProperty(name = "UnitTestName")
+ boolean isTrue();
+
+ /**
+ * APPLICATION NOTE: It is the objects responsibility to throw an exception if it cannot handle
+ * any additional observers which will in turn return an error to the requestor.
+ *
+ * @param observer the observer that will be notified when a change to the state property has
+ * occurred.
+ */
+ @OCProperty(name = "UnitTestName")
+ void addMyUnitTestObserver(OCObserver<Boolean> observer);
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+package com.oc.unittests;
+
+import com.oc.OCObject;
+import com.oc.OCObserver;
+
+public class UnitTestResource implements OCObject, UnitTestControlItf {
+
+ @Override
+ public void setState(boolean state) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean isTrue() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public void addMyUnitTestObserver(OCObserver<Boolean> observer) {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean isVisible() {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+}
--- /dev/null
+2014-02-25 Doug Hudson
+Created core subdir for C++ API and CCFL Core. Makefile builds a test Linux executable.
+
+2014-02-14 Doug Hudson
+Added current C++ source files for remoting. The remoting controller code interfaces to the
+CCF Stack. The remoting code compiles in CCF, but have not yet added the ability to build in
+the CCF-Lite repo.
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef CHARACTERISTIC_H_
+#define CHARACTERISTIC_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <string>
+#include <memory>
+#include <functional>
+#include <stdint.h>
+#include "Core.h"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace API {
+
+// ============================================================================
+// Class
+// ============================================================================
+class PropertyGetResult {
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~PropertyGetResult() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual QueryResultType getResult() const = 0;
+ virtual const std::string& getName() const = 0;
+ virtual const std::string& getValue() const = 0;
+};
+
+typedef std::function<void (const PropertyGetResult&)> PropertyGetFunction;
+
+// ============================================================================
+// Class
+// ============================================================================
+class PropertySetResult {
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~PropertySetResult() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual QueryResultType getResult() const = 0;
+ virtual const std::string& getName() const = 0;
+ virtual const std::string& getValue() const = 0;
+};
+
+typedef std::function<void (const PropertySetResult&)> PropertySetFunction;
+
+// ============================================================================
+// Class
+// ============================================================================
+
+class Characteristic {
+ // ============================================================
+ // Type Definition(s)
+ // ============================================================
+ public:
+ typedef std::shared_ptr<Characteristic> SharedPtr;
+ typedef std::weak_ptr<Characteristic> WeakPtr;
+
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~Characteristic() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual const std::string& getName() const = 0;
+ virtual bool isReadable() const = 0;
+ virtual bool isWritable() const = 0;
+ virtual bool isConstant() const = 0;
+};
+
+}
+}
+}
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef CORE_H_
+#define CORE_H_
+
+#include <boost/uuid/uuid.hpp>
+typedef boost::uuids::uuid UUID_t;
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace API {
+
+// ============================================================================
+// Enums
+// ============================================================================
+enum QueryResultType {
+ SUCCESS,
+ FAILURE
+};
+
+}
+}
+}
+
+#ifdef CPPV11
+#include <mutex>
+ namespace Intel {
+ namespace CCFL {
+ namespace API {
+ typedef std::mutex mutex;
+ typedef std::lock_guard<std::mutex> mutex_lock_guard;
+ }
+ }
+ }
+#else
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/locks.hpp>
+ namespace Intel {
+ namespace CCFL {
+ namespace API {
+ typedef boost::mutex mutex;
+ typedef boost::lock_guard<boost::mutex> mutex_lock_guard;
+ }
+ }
+ }
+#endif
+
+#endif /* CORE_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef DESCRIPTION_H_
+#define DESCRIPTION_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <string>
+#include <memory>
+#include <functional>
+#include "Service.hpp"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace API {
+
+// ============================================================================
+// Class
+// ============================================================================
+class DescriptionGetResult {
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~DescriptionGetResult() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual QueryResultType getResult() const = 0;
+ virtual const std::set<Service::SharedPtr>& getServices() const = 0;
+};
+
+typedef std::function<void (const DescriptionGetResult&)> DescriptionGetFunction;
+
+// ============================================================================
+// Class
+// ============================================================================
+class Description {
+ // ============================================================
+ // Type Definition(s)
+ // ============================================================
+ public:
+ typedef std::shared_ptr<Description> SharedPtr;
+ typedef std::weak_ptr<Description> WeakPtr;
+
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~Description() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual const std::set<Service::SharedPtr>& getServices() const = 0;
+};
+
+}
+}
+}
+
+#endif /* DESCRIPTION_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef DEVICE_H_
+#define DEVICE_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <string>
+#include <list>
+#include <cassert>
+#include <stdint.h>
+
+#include "Core.h"
+#include "UUIDLess.hpp"
+#include "Link.hpp"
+#include "SimpleLogger.h"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace API {
+
+static const char DEVICE_TAG[] = "Device";
+
+class Device {
+ // ============================================================
+ // Type Definition(s)
+ // ============================================================
+public:
+ typedef std::shared_ptr<Device> SharedPtr;
+ typedef std::weak_ptr<Device> WeakPtr;
+ typedef std::list<Link::SharedPtr> LinkList;
+
+public:
+ Device(const UUID_t& deviceId) {
+ deviceId_ = deviceId;
+ name_ = "";
+ }
+ virtual ~Device() {
+ linkList_.clear();
+ };
+
+public:
+ const UUID_t& getId() {
+ mutex_lock_guard lock(deviceMutex_);
+ return deviceId_;
+ };
+
+ const std::string& getName() {
+ mutex_lock_guard lock(deviceMutex_);
+ return name_;
+ };
+
+ void setName(const std::string& name) {
+ mutex_lock_guard lock(deviceMutex_);
+ name_ = name;
+ };
+
+ void addLink(const Link::SharedPtr& link) {
+ logDebug(DEVICE_TAG, "Entering Link::addLink");
+ assert(link);
+ mutex_lock_guard lock(deviceMutex_);
+
+ // If list is empty, go ahead and add
+ if (linkList_.empty())
+ {
+ logDebug(DEVICE_TAG, "Link::addLink, linkList empty, adding");
+ linkList_.push_back(link);
+ return;
+ }
+
+ // Search list for the link. If already in list, return
+ for (auto iter = linkList_.begin(); iter != linkList_.end(); ++iter) {
+ if (*iter == link) {
+ logDebug(DEVICE_TAG, "Link::addLink, link already in linkList");
+ return;
+ }
+ }
+
+ // Not already in list, so add
+ logDebug(DEVICE_TAG, "Link::addLink, adding link");
+ linkList_.push_back(link);
+ }
+
+ bool removeLink(const Link::SharedPtr& link) {
+ logDebug(DEVICE_TAG, "Entering Link::removeLink");
+ assert(link);
+
+ mutex_lock_guard lock(deviceMutex_);
+ // Return immediately if the list is empty
+ if (linkList_.empty()) {
+ logDebug(DEVICE_TAG, "Link::removeLink, linkList empty");
+ return false;
+ }
+
+ // Search list for the link. If in the list, return
+ for (auto iter = linkList_.begin(); iter != linkList_.end(); ++iter) {
+ if (*iter == link) {
+ linkList_.erase(iter);
+ logDebug(DEVICE_TAG, "Link::removeLink, removing link");
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ LinkList getLinks() {
+ mutex_lock_guard lock(deviceMutex_);
+ return linkList_;
+ }
+
+ uint32_t getLinkCount() {
+ mutex_lock_guard lock(deviceMutex_);
+ return (uint32_t)linkList_.size();
+ }
+
+private:
+ UUID_t deviceId_;
+ std::string name_;
+ LinkList linkList_;
+ mutex deviceMutex_;
+};
+
+}
+}
+}
+
+
+
+#endif /* DEVICE_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef INTERNALAPI_H_
+#define INTERNALAPI_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <memory>
+#include <functional>
+#include <string>
+#include <list>
+#include "Core.h"
+#include "Description.hpp"
+#include "Characteristic.hpp"
+#include "Protocol.hpp"
+#include "Device.hpp"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace API {
+
+
+// ============================================================================
+// Device Class(es)
+// ============================================================================
+
+#if 0
+// ============================================================================
+// Class
+// ============================================================================
+class DeviceIdsGetResult {
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~DeviceIdsGetResult() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual QueryResultType getResult() const = 0;
+ virtual const std::set<UUID_t>& getDeviceIds() const = 0;
+};
+
+typedef std::function<void (const DeviceIdsGetResult&)> DeviceIdsGetFunction;
+
+// ============================================================================
+// Class
+// ============================================================================
+class DeviceGetInfoResult {
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~DeviceGetInfoResult() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual QueryResultType getResult() const = 0;
+ virtual const std::string& getName() const = 0;
+ virtual const Description::SharedPtr& getDescription() const = 0;
+ virtual bool isLocal() = 0;
+};
+
+typedef std::function<void (const DeviceGetInfoResult&)> DeviceGetInfoFunction;
+#endif
+
+// ============================================================================
+// Class
+// ============================================================================
+class GetDevicesResult {
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~GetDevicesResult() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual QueryResultType getResult() const = 0;
+ virtual const std::list<Device::SharedPtr>& getDeviceList() const = 0;
+};
+
+typedef std::function<void (const GetDevicesResult&)> GetDevicesFunction;
+
+
+// ============================================================================
+// Class
+// ============================================================================
+typedef uint32_t DeviceObserverHandle;
+const DeviceObserverHandle INVALID_DEVICE_OBSERVER_HANDLE = (DeviceObserverHandle)0;
+
+class DeviceEvent {
+public:
+ enum DeviceChange {
+ DEVICE_CURRENT_COLLECTION,
+ DEVICE_ADDED,
+ DEVICE_REMOVED
+ };
+
+ struct DeviceEventInfo {
+ UUID_t deviceId;
+ DeviceChange deviceChange;
+ };
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~DeviceEvent() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual QueryResultType getResult() const = 0;
+ virtual DeviceObserverHandle getObserverHandle() const = 0;
+ virtual const std::list<DeviceEventInfo>& getDeviceIdList() const = 0;
+};
+
+typedef std::function<void (const DeviceEvent&)> DeviceEventFunction;
+
+
+// ============================================================================
+// Class
+// ============================================================================
+class Model : public std::enable_shared_from_this<Model> {
+ // ============================================================
+ // Type Definition(s)
+ // ============================================================
+ public:
+ typedef std::shared_ptr<Model> SharedPtr;
+ typedef std::weak_ptr<Model> WeakPtr;
+
+ // ============================================================
+ // Factory
+ // ============================================================
+ public:
+ static SharedPtr createModel();
+
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~Model() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual void getDevices(GetDevicesFunction& asyncReturnFunc) = 0;
+
+ // Add/remove device observer
+ virtual void removeDeviceObserver(DeviceObserverHandle observerHandle) = 0;
+ virtual void setDeviceObserver(DeviceEventFunction& asyncEventFunction) = 0;
+
+ // Register/unregister a protocol
+ virtual const Protocols::Protocol::Handle registerProtocol(const Protocols::Protocol::SharedPtr& protocol) = 0;
+ virtual bool unregisterProtocol(const Protocols::Protocol::Handle protocolHandle) = 0;
+ virtual Device::SharedPtr getDevice(const UUID_t& deviceId) = 0;
+ virtual void signalDeviceChange(const UUID_t& deviceId, DeviceEvent::DeviceChange deviceEvent) = 0;
+
+};
+
+
+}
+}
+}
+
+#endif /* INTERNALAPI_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef LINK_HPP_
+#define LINK_HPP_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <string>
+#include <memory>
+#include "Description.hpp"
+#include "Service.hpp"
+#include "Characteristic.hpp"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace API {
+
+class Link {
+ // ============================================================
+ // Type Definition(s)
+ // ============================================================
+public:
+ typedef std::shared_ptr<Link> SharedPtr;
+ typedef std::weak_ptr<Link> WeakPtr;
+
+ typedef std::function<void (const std::string& propertyName, const PropertyGetFunction& asyncReturnFunc)> RegisteredGetPropFunction;
+ typedef std::function<void (const std::string& propertyName, const std::string& propertyValue, const PropertySetFunction& asyncReturnFunc)> RegisteredSetPropFunction;
+ typedef std::function<void (const DescriptionGetFunction& asyncReturnFunc)> RegisteredGetDescriptionFunction;
+
+public:
+ Link() {
+ name_ = "unknown link name";
+ registeredGetPropFunction_ = nullptr;
+ registeredSetPropFunction_ = nullptr;
+ registeredGetDescriptionFunction_ = nullptr;
+ };
+
+ virtual ~Link() {};
+
+ virtual const std::string& getName() {
+ return name_;
+ }
+
+ virtual void setName(const std::string name) {
+ name_ = name;
+ }
+
+ // Used at application interface
+ virtual void getProperty(const std::string& propertyName, PropertyGetFunction& asyncReturnFunc) {
+ // Call registered function
+ if (nullptr != registeredGetPropFunction_) {
+ registeredGetPropFunction_(propertyName, asyncReturnFunc);
+ }
+ }
+
+ virtual void setProperty(const std::string& propertyName, const std::string& propertyValue, PropertySetFunction& asyncReturnFunc) {
+ if (nullptr != registeredSetPropFunction_) {
+ registeredSetPropFunction_(propertyName, propertyValue, asyncReturnFunc);
+ }
+ }
+
+ virtual void getDescription(DescriptionGetFunction& asyncReturnFunc) {
+ if (nullptr != registeredGetDescriptionFunction_) {
+ registeredGetDescriptionFunction_(asyncReturnFunc);
+ }
+ }
+
+ // Used at protocol interface
+ virtual void registerGetPropertyFunction(RegisteredGetPropFunction& registeredGetPropFunction) {
+ registeredGetPropFunction_ = registeredGetPropFunction;
+ }
+
+ virtual void registerSetPropertyFunction(RegisteredSetPropFunction& registeredSetPropFunction) {
+ registeredSetPropFunction_ = registeredSetPropFunction;
+ }
+
+ virtual void registerGetDescriptionFunction(RegisteredGetDescriptionFunction& registeredGetDescriptionFunction) {
+ registeredGetDescriptionFunction_ = registeredGetDescriptionFunction;
+ }
+
+private:
+ std::string name_;
+ RegisteredGetPropFunction registeredGetPropFunction_;
+ RegisteredSetPropFunction registeredSetPropFunction_;
+ RegisteredGetDescriptionFunction registeredGetDescriptionFunction_;
+};
+
+}
+}
+}
+
+#endif /* LINK_HPP_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef PROTOCOL_H_
+#define PROTOCOL_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <string>
+#include <set>
+#include <memory>
+#include <stdint.h>
+#include "Device.hpp"
+
+// ============================================================================
+// Forward declaration
+// ============================================================================
+namespace Intel {
+ namespace CCFL {
+ namespace API {
+ class Model;
+ }
+ }
+}
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace Protocols {
+
+class Protocol
+{
+public:
+ typedef std::shared_ptr<Protocol> SharedPtr;
+ typedef std::weak_ptr<Protocol> WeakPtr;
+ typedef uint32_t Handle;
+
+ static const Handle INVALID_HANDLE = (Handle)0;
+public:
+ virtual ~Protocol() {};
+
+public:
+ virtual void setModel(const std::shared_ptr<Intel::CCFL::API::Model>& model) = 0;
+ virtual const Handle getHandle() = 0;
+ virtual void setHandle(const Handle handle) = 0;
+ virtual const std::string& getName() = 0;
+ virtual void forceDeviceDiscovery() = 0;
+};
+
+}
+}
+}
+
+#endif /* PROTOCOL_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef SERVICE_H_
+#define SERVICE_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <string>
+#include <memory>
+#include <set>
+#include "Characteristic.hpp"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace API {
+
+class Service {
+ // ============================================================
+ // Type Definition(s)
+ // ============================================================
+ public:
+ typedef std::shared_ptr<Service> SharedPtr;
+ typedef std::weak_ptr<Service> WeakPtr;
+
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~Service() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+
+ virtual const std::string& getName() const = 0;
+ virtual const std::set<Characteristic::SharedPtr>& getCharacteristics() const = 0;
+};
+
+}
+}
+}
+
+
+#endif /* SERVICE_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+/*
+ * SimpleLogger.cpp
+ *
+ * Created on: Mar 27, 2014
+ * Author: dkhudson
+ */
+#include "SimpleLogger.h"
+
+#ifdef __ANDROID__
+ #include <android/log.h>
+#endif
+
+namespace Intel {
+namespace CCFL {
+
+void LOG(const char * format, ...) {
+#ifdef __ANDROID__
+ va_list args;
+ va_start (args, format);
+ __android_log_vprint(ANDROID_LOG_INFO, "CCF-Lite-ANDROID", format, args);
+ va_end (args);
+#elif defined __linux__
+ printf("INFO: CCF-Lite-LINUX: ");
+ va_list args;
+ va_start (args, format);
+ vprintf(format, args);
+ va_end (args);
+ printf("\n");
+#endif
+}
+
+void logDebug(const char * tag, const char * format, ...) {
+#ifdef __ANDROID__
+ va_list args;
+ va_start (args, format);
+ __android_log_vprint(ANDROID_LOG_DEBUG, tag, format, args);
+ va_end (args);
+#elif defined __linux__
+ printf("DEBUG: %s: ", tag);
+ va_list args;
+ va_start (args, format);
+ vprintf(format, args);
+ va_end (args);
+ printf("\n");
+#endif
+}
+void logInfo(const char * tag, const char * format, ...) {
+#ifdef __ANDROID__
+ va_list args;
+ va_start (args, format);
+ __android_log_vprint(ANDROID_LOG_INFO, tag, format, args);
+ va_end (args);
+#elif defined __linux__
+ printf("INFO: %s: ", tag);
+ va_list args;
+ va_start (args, format);
+ vprintf(format, args);
+ va_end (args);
+ printf("\n");
+#endif
+}
+
+void logWarn(const char * tag, const char * format, ...) {
+#ifdef __ANDROID__
+ va_list args;
+ va_start (args, format);
+ __android_log_vprint(ANDROID_LOG_WARN, tag, format, args);
+ va_end (args);
+#elif defined __linux__
+ printf("WARN: %s: ", tag);
+ va_list args;
+ va_start (args, format);
+ vprintf(format, args);
+ va_end (args);
+ printf("\n");
+#endif
+}
+
+void logError(const char * tag, const char * format, ...) {
+#ifdef __ANDROID__
+ va_list args;
+ va_start (args, format);
+ __android_log_vprint(ANDROID_LOG_ERROR, tag, format, args);
+ va_end (args);
+#elif defined __linux__
+ printf("ERROR: %s: ", tag);
+ va_list args;
+ va_start (args, format);
+ vprintf(format, args);
+ va_end (args);
+ printf("\n");
+#endif
+}
+
+void logFatal(const char * tag, const char * format, ...) {
+#ifdef __ANDROID__
+ va_list args;
+ va_start (args, format);
+ __android_log_vprint(ANDROID_LOG_FATAL, tag, format, args);
+ va_end (args);
+#elif defined __linux__
+ printf("FATAL: %s: ", tag);
+ va_list args;
+ va_start (args, format);
+ vprintf(format, args);
+ va_end (args);
+ printf("\n");
+#endif
+}
+
+}
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef LOGGER_H_
+#define LOGGER_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+namespace Intel {
+namespace CCFL {
+
+void logDebug(const char * tag, const char * format, ...);
+void logInfo(const char * tag, const char * format, ...);
+void logWarn(const char * tag, const char * format, ...);
+void logError(const char * tag, const char * format, ...);
+void logFatal(const char * tag, const char * format, ...);
+
+
+//#ifndef NDEBUG
+//#if 0
+// #ifdef __linux__
+// #include <stdio.h>
+// #define LOG(...) printf(__VA_ARGS__); printf("\n");
+// #elif __ANDROID__
+// #include <android/log.h>
+// #define LOG(...) _android_log_print(ANDROID_LOG_INFO, "LOG_TAG", __VA_ARGS__);
+// #elif _WIN64
+// #define LOG(...)
+// #elif _WIN32
+// #define LOG(...)
+// #elif __APPLE__
+// #define LOG(...)
+// #else
+// #endif
+//#else
+// #define LOG(...)
+//#endif
+
+}
+}
+
+#endif /* LOGGER_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef UUIDLESS_HPP_
+#define UUIDLESS_HPP_
+
+// ============================================================================
+// Includes
+// ============================================================================
+
+#include <cstring>
+#include "Core.h"
+
+ // ============================================================================
+ // Namespace
+ // ============================================================================
+ namespace Intel {
+ namespace CCFL {
+
+ class UUIDLess
+ {
+ public:
+ bool operator()(const UUID_t &uuid1, const UUID_t &uuid2) const
+ {
+ return memcmp(&uuid1, &uuid2, sizeof(uuid1))<0;
+ }
+ };
+
+}
+}
+
+
+#endif /* UUIDLESS_HPP_ */
--- /dev/null
+# override with `make BUILD=release`
+# default to debug build
+BUILD := debug
+
+CC := g++
+
+PROG := core
+
+SRC_DIR := ./src
+TEST_DIR := ./test
+TEMP_DIR := ./include/core
+
+CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -pedantic -fpic
+CC_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fpic
+CC_FLAGS := $(CC_FLAGS.$(BUILD))
+
+INC := -I$(SRC_DIR)
+INC += -I./include/core
+INC += -I$(TEST_DIR)
+INC += -I../include/controller
+
+LIBS :=
+#LIBS := -lpthread
+#LIBS += -lboost_thread-mt
+#LIBS += -lboost_thread
+
+# using make's computed variables to select object and bin folders
+# depending on the build type
+OBJ_DIR.debug := ./obj/debug
+OBJ_DIR.release := ./obj/release
+OBJ_DIR := $(OBJ_DIR.$(BUILD))
+
+BIN_DIR.debug := ./bin/debug
+BIN_DIR.release := ./bin/release
+BIN_DIR := $(BIN_DIR.$(BUILD))
+
+CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp)
+CPP_FILES += $(wildcard $(TEST_DIR)/*.cpp)
+CPP_FILES += $(wildcard $(TEMP_DIR)/*.cpp)
+OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o)))
+H_FILES := $(wildcard ./include/core/*.hpp)
+H_FILES += $(wildcard ./include/core/*.h)
+H_FILES += $(wildcard $(TEST_DIR)/*.h)
+LD_FLAGS := -L/usr/lib
+
+
+all: $(PROG)
+
+$(PROG): $(OBJ_FILES)
+ $(CC) -o $@ $^ $(LD_FLAGS) $(LIBS)
+ mv ./$(PROG) ./$(BIN_DIR)
+
+
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h $(H_FILES)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(TEMP_DIR)/%.cpp $(H_FILES)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+.PHONY: clean
+clean :
+ rm -rf ./obj/debug/*
+ rm -rf ./obj/release/*
+ rm -rf ./bin/debug/*
+ rm -rf ./bin/release/*
+
+
+.PHONY: print_vars
+
+print_vars:
+ @echo ""
+ @echo 'BUILD = '$(value BUILD)
+ @echo 'INC = '$(value INC)
+ @echo 'CPP_FILES = '$(value CPP_FILES)
+ @echo 'LIBS = '$(value LIBS)
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include "ModelImpl.h"
+//#include "DeviceImpl.h"
+#include "SimpleLogger.h"
+#include <stdlib.h>
+#include <time.h>
+#include <cstdlib>
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace API {
+
+static const char TAG[] = "ModelImpl";
+
+// ============================================================================
+// GetDevicesResult Implementation Class
+// ============================================================================
+class GetDeviceSuccess : public GetDevicesResult {
+public:
+ virtual ~GetDeviceSuccess() {}
+
+// ============================================================
+// Public Method(s)
+// ============================================================
+public:
+ virtual QueryResultType getResult() const {
+ return SUCCESS;
+ }
+
+ virtual const std::list<Device::SharedPtr>& getDeviceList() const {
+ return deviceList_;
+ }
+
+public:
+ std::list<Device::SharedPtr> deviceList_;
+};
+
+// ============================================================================
+// DeviceEvent Implementation Class
+// ============================================================================
+class DeviceEventSuccess : public DeviceEvent {
+// ============================================================
+// Constructor & Destructor
+// ============================================================
+public:
+ DeviceEventSuccess() {
+ deviceObserverHandle_ = INVALID_DEVICE_OBSERVER_HANDLE;
+ }
+ virtual ~DeviceEventSuccess() {}
+
+// ============================================================
+// Public Method(s)
+// ============================================================
+public:
+ virtual QueryResultType getResult() const {
+ return SUCCESS;
+ }
+
+ virtual DeviceObserverHandle getObserverHandle() const {
+ return deviceObserverHandle_;
+ }
+
+ virtual const std::list<DeviceEventInfo>& getDeviceIdList() const {
+ return deviceInfoList_;
+ }
+
+public:
+ DeviceObserverHandle deviceObserverHandle_;
+ std::list<DeviceEventInfo> deviceInfoList_;
+};
+
+// ============================================================================
+// Model Factory
+// ============================================================================
+Model::SharedPtr Model::createModel() {
+ logDebug(TAG, "Entering Model::createModel");
+ return ModelImpl::createModel();
+}
+
+ModelImpl::SharedPtr ModelImpl::createModel() {
+ // Get singleton of ModelImpl.
+ logDebug(TAG, "Entering ModelImpl::createModel");
+ static SharedPtr instance = std::make_shared<ModelImpl>();
+
+ return instance;
+}
+// ============================================================================
+// Constructors & Destructors
+// ============================================================================
+ModelImpl::ModelImpl() {
+ logDebug(TAG, "Entering ModelImpl::ModelImpl");
+
+ // initialize random seed for use with random protocol handles
+ srand(time(NULL));
+}
+
+ModelImpl::~ModelImpl() {
+ logDebug(TAG, "Entering ModelImpl::~ModelImpl");
+ protocolMap_.clear();
+ deviceList_.clear();
+ deviceObserverMap_.clear();
+}
+
+// ============================================================================
+// Public methods
+// ============================================================================
+
+void ModelImpl::getDevices(GetDevicesFunction& asyncReturnFunc) {
+ logDebug(TAG, "Entering ModelImpl::getDevices");
+
+ mutex_lock_guard lock(deviceListMutex_);
+
+ GetDeviceSuccess result;
+ // Insert from the model device list to the result device list
+ result.deviceList_.insert(result.deviceList_.end(), deviceList_.begin(), deviceList_.end());
+
+ // Invoke the callback
+ asyncReturnFunc(result);
+}
+
+// Add/remove device observer
+void ModelImpl::removeDeviceObserver(DeviceObserverHandle observerHandle) {
+ logDebug(TAG, "Entering ModelImpl::removeDeviceObserver");
+
+ mutex_lock_guard lock(deviceObserverMapMutex_);
+ for (auto iter = deviceObserverMap_.begin(); iter != deviceObserverMap_.end(); ++iter) {
+ if (iter->first == observerHandle) {
+ // Remove protocol
+ deviceObserverMap_.erase(iter);
+ logDebug(TAG, "ModelImpl::removeDeviceObserver, removed observer handle %d", (uint32_t)observerHandle);
+ return;
+ }
+ }
+}
+
+void ModelImpl::setDeviceObserver(DeviceEventFunction& asyncEventFunction) {
+ // TODO: anyway to ensure that asyncEventFunction is valid? nullptr check?
+ logDebug(TAG, "Entering ModelImpl::setDeviceObserver");
+
+ // Create a local scope here so that the mutex will be released at the end of the scope
+ {
+ mutex_lock_guard lock(deviceObserverMapMutex_);
+ // Get a handle that is not already in use
+ DeviceObserverHandle observerHandle;
+ do {
+ observerHandle = generateDeviceObserverHandle();
+ } while (isDeviceObserverHandleInUse(observerHandle));
+
+ // Add observer to the map.
+ // Insert returns a pair with the second a bool set to true if a new element
+ // was inserted or false if an equivalent key already existed.
+ if (deviceObserverMap_.insert(DeviceObserverMap::value_type(observerHandle, asyncEventFunction)).second) {
+ logDebug(TAG, "Entering ModelImpl::setDeviceObserver, observer added");
+ }
+ else {
+ logDebug(TAG, "ModelImpl::setDeviceObserver: Error inserting observer");
+ }
+ }
+
+ // Notify the observers
+ DeviceIdList deviceIdList = getDeviceIdList();
+ notifyDeviceObservers(DeviceEvent::DeviceChange::DEVICE_CURRENT_COLLECTION, deviceIdList);
+}
+
+const Protocols::Protocol::Handle ModelImpl::registerProtocol(const Protocols::Protocol::SharedPtr& protocol) {
+ logDebug(TAG, "Entering ModelImpl::registerProtocol");
+
+ // Validate protocol
+ assert(protocol);
+
+ logDebug(TAG, "ModelImpl::registerProtocol, trying to register protocol %s", protocol->getName().c_str());
+
+ // Iterate through map and ensure that the protocol is not already registered
+ Protocols::Protocol::Handle handle = Protocols::Protocol::INVALID_HANDLE;
+ bool protocolRegistered = false;
+
+ mutex_lock_guard lock(protocolMapMutex_);
+
+ for (auto iter = protocolMap_.begin(); iter != protocolMap_.end(); ++iter) {
+ // TODO: need to handle a protocol that no longer is in scope.
+ // Remove from map and maybe notify apps that devices and/or connections are no longer present
+ Protocols::Protocol::SharedPtr sharedProtocol = iter->second.lock();
+ if (sharedProtocol) {
+ if (sharedProtocol->getName() == protocol->getName()) {
+ logDebug(TAG, "ModelImpl::registerProtocol, protocol %s already registered", protocol->getName().c_str());
+ protocolRegistered = true;
+ break;
+ }
+ }
+ }
+
+ // If the protocol isn't registered, create a new handle and add
+ // the protocol to the map
+ if (!protocolRegistered) {
+
+ // Get a handle that is not already in use
+ do {
+ handle = generateProtocolHandle();
+ } while (isHandleInUse(handle));
+
+ // Add protocol to the map.
+ // Insert returns a pair with the second a bool set to true if a new element
+ // was inserted or false if an equivalent key already existed.
+ Protocols::Protocol::WeakPtr weakProtocol = protocol;
+ if (!protocolMap_.insert(ProtocolMap::value_type(handle, weakProtocol)).second) {
+ logDebug(TAG, "ModelImpl::registerProtocol: Error inserting protocol %s", protocol->getName().c_str());
+ handle = Protocols::Protocol::INVALID_HANDLE;
+ }
+ else {
+ logDebug(TAG, "ModelImpl::registerProtocol: registered protocol = %s", protocol->getName().c_str());
+ protocol->setHandle(handle);
+ }
+ }
+
+ return handle;
+}
+
+bool ModelImpl::unregisterProtocol(const Protocols::Protocol::Handle protocolHandle) {
+ logDebug(TAG, "Entering ModelImpl::unregisterProtocol");
+
+ bool handleFound = false;
+
+ mutex_lock_guard lock(protocolMapMutex_);
+
+ for (auto iter = protocolMap_.begin(); iter != protocolMap_.end(); ++iter) {
+ if (iter->first == protocolHandle) {
+ handleFound = true;
+ // Remove protocol
+ protocolMap_.erase(iter);
+ logDebug(TAG, "ModelImpl::unregisterProtocol, unregistering protocol handle %d", (uint32_t)protocolHandle);
+ break;
+ }
+ }
+
+ return handleFound;
+}
+
+Device::SharedPtr ModelImpl::getDevice(const UUID_t& deviceId) {
+ logDebug(TAG, "Entering ModelImpl::getDevice");
+
+ // Get a device from the device list. If the device already exists, return that
+ // device. If not, create a new device with the specified device id, add it to
+ // the device list, and then return the device
+ mutex_lock_guard lock(deviceListMutex_);
+ if (deviceList_.empty())
+ {
+ logDebug(TAG, "ModelImpl::getDevice, device list empty, adding device");
+ return addDeviceToList(deviceId);
+ }
+
+ // Search list for the device based on device id
+ for (auto iter = deviceList_.begin(); iter != deviceList_.end(); ++iter) {
+ Device::SharedPtr device = *iter;
+ if (device->getId() == deviceId) {
+ logDebug(TAG, "ModelImpl::getDevice, device found in list");
+ return device;
+ }
+ }
+
+ // If here, device not found in list, so add and return
+ logDebug(TAG, "ModelImpl::getDevice, device not found in list, adding device");
+ return addDeviceToList(deviceId);
+}
+
+void ModelImpl::signalDeviceChange(const UUID_t& deviceId, DeviceEvent::DeviceChange deviceEvent) {
+
+ uint32_t linkCount;
+ DeviceIdList deviceIdList;
+ bool sendNotification = false;
+
+ // Create a local scope so that the deviceListMutex_ will be released at the end
+ // of the local scope
+ {
+ mutex_lock_guard lock(deviceListMutex_);
+ // Search list for the device based on device id
+ for (auto iter = deviceList_.begin(); iter != deviceList_.end(); ++iter) {
+ Device::SharedPtr device = *iter;
+ if (device->getId() == deviceId) {
+ linkCount = device->getLinkCount();
+ logDebug(TAG, "ModelImpl::signalDeviceChange, device found, number of links = %d", linkCount);
+
+ if (deviceEvent == DeviceEvent::DeviceChange::DEVICE_ADDED) {
+ // If DEVICE_ADDED and only one link, then that indicates that this is the first
+ // time that the device was found by a protocol, so a notification must be sent.
+ // Multiple links in the device indicate that that the device was previously found
+ // by other protocols, so a notification is not required
+ if (linkCount == 1) {
+ deviceIdList.push_back(deviceId);
+ sendNotification = true;
+ }
+ }
+ else if (deviceEvent == DeviceEvent::DeviceChange::DEVICE_REMOVED) {
+ // If DEVICE_REMOVED and no links remain in the device, then the
+ // device needs to be removed from the device list and
+ // a device removal notification must be sent.
+ if (linkCount == 0) {
+ deviceIdList.push_back(deviceId);
+ deviceList_.erase(iter);
+ sendNotification = true;
+ }
+ }
+ break;
+ }
+ }
+ }
+
+ // Since a device was added or removed, notify the device observers
+ if (sendNotification) {
+ notifyDeviceObservers(deviceEvent, deviceIdList);
+ }
+}
+
+// ============================================================================
+// Private methods
+// ============================================================================
+const Protocols::Protocol::Handle ModelImpl::generateProtocolHandle() {
+ // Handle between 1 and (RAND_MAX -1)
+ Protocols::Protocol::Handle handle = (Protocols::Protocol::Handle)(rand() % (RAND_MAX - 1) + 1);
+
+ return handle;
+}
+
+bool ModelImpl::isHandleInUse(Protocols::Protocol::Handle handle) {
+ bool handleFound = false;
+
+ for (auto iter = protocolMap_.begin(); iter != protocolMap_.end(); ++iter) {
+ if (iter->first == handle) {
+ handleFound = true;
+ break;
+ }
+ }
+ return handleFound;
+}
+
+Device::SharedPtr ModelImpl::addDeviceToList(const UUID_t& deviceId) {
+ logDebug(TAG, "Entering ModelImpl::addDeviceToList");
+
+ deviceList_.push_back(std::make_shared<Device>(deviceId));
+ return deviceList_.back();
+}
+
+DeviceObserverHandle ModelImpl::generateDeviceObserverHandle() {
+ // Handle between 1 and (RAND_MAX -1)
+ DeviceObserverHandle handle = (DeviceObserverHandle)(rand() % (RAND_MAX - 1) + 1);
+
+ return handle;
+}
+
+bool ModelImpl::isDeviceObserverHandleInUse(DeviceObserverHandle observerHandle) {
+ bool handleFound = false;
+
+ for (auto iter = deviceObserverMap_.begin(); iter != deviceObserverMap_.end(); ++iter) {
+ if (iter->first == observerHandle) {
+ handleFound = true;
+ break;
+ }
+ }
+ return handleFound;
+}
+
+void ModelImpl::notifyDeviceObservers(DeviceEvent::DeviceChange event, const DeviceIdList& deviceIdList) {
+ logDebug(TAG, "Entering ModelImpl::notifyDeviceObservers");
+
+ // Iterate through the device id list that was passed to the notifier
+ // and create a list of DeviceEvent::DeviceEventInfo objects.
+ // Set the device id and the event in the DeviceEvent::DeviceEventInfo object
+ std::list<DeviceEvent::DeviceEventInfo> deviceEventInfoList;
+ DeviceEvent::DeviceEventInfo info;
+ for (auto iter = deviceIdList.begin(); iter != deviceIdList.end(); ++iter) {
+ info.deviceId = *iter;
+ info.deviceChange = event;
+
+ deviceEventInfoList.push_back(info);
+ }
+
+ mutex_lock_guard lock(deviceObserverMapMutex_);
+
+ // Nothing to do if there are no observers
+ if (deviceObserverMap_.empty()) {
+ return;
+ }
+
+ DeviceObserverHandle observerHandle;
+ DeviceEventFunction eventFunction;
+
+ // For every observer in the observer map:
+ for (auto iter = deviceObserverMap_.begin(); iter != deviceObserverMap_.end(); ++iter) {
+ observerHandle = iter->first;
+ eventFunction = iter->second;
+
+ // 1. Create a DeviceEventSuccess object and set the observer handle
+ DeviceEventSuccess deviceEventSuccess;
+ deviceEventSuccess.deviceObserverHandle_ = observerHandle;
+
+ // 2. Insert the deviceEventInfoList into the DeviceEventSuccess object list
+ deviceEventSuccess.deviceInfoList_.insert(deviceEventSuccess.deviceInfoList_.end(), deviceEventInfoList.begin(), deviceEventInfoList.end());
+
+ // 3. Invoke the observer's callback function
+ eventFunction(deviceEventSuccess);
+ }
+
+}
+
+ModelImpl::DeviceIdList ModelImpl::getDeviceIdList() {
+
+ mutex_lock_guard lock(deviceListMutex_);
+
+ DeviceIdList deviceIdList;
+
+ // Search list for the device based on device id
+ for (auto iter = deviceList_.begin(); iter != deviceList_.end(); ++iter) {
+ Device::SharedPtr device = *iter;
+ deviceIdList.push_back(device->getId());
+ }
+
+ return deviceIdList;
+}
+
+}
+}
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef MODELIMPL_H_
+#define MODELIMPL_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <memory>
+#include <map>
+#include <list>
+#include <stdint.h>
+
+#include "Protocol.hpp"
+#include "UUIDLess.hpp"
+#include "InternalApi.h"
+#include "Core.h"
+
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace API {
+
+class ModelImpl : public Model
+{
+public:
+ typedef std::shared_ptr<ModelImpl> SharedPtr;
+ typedef std::weak_ptr<ModelImpl> WeakPtr;
+
+public:
+ // Factory
+ static SharedPtr createModel();
+
+public:
+ // Constructor & Destructor
+ ModelImpl();
+ virtual ~ModelImpl();
+
+ // Get the device list
+ virtual void getDevices(GetDevicesFunction& asyncReturnFunc);
+
+ // Add/remove device observer
+ virtual void removeDeviceObserver(DeviceObserverHandle observerHandle);
+ virtual void setDeviceObserver(DeviceEventFunction& asyncEventFunction);
+
+ // Register/unregister a protocol
+ virtual const Protocols::Protocol::Handle registerProtocol(const Protocols::Protocol::SharedPtr& protocol);
+ virtual bool unregisterProtocol(const Protocols::Protocol::Handle protocolHandle);
+ virtual Device::SharedPtr getDevice(const UUID_t& deviceId);
+ virtual void signalDeviceChange(const UUID_t& deviceId, DeviceEvent::DeviceChange deviceEvent);
+
+private:
+ typedef std::map<Protocols::Protocol::Handle, Protocols::Protocol::WeakPtr> ProtocolMap;
+ typedef std::list<Device::SharedPtr> DeviceList;
+ typedef std::map<DeviceObserverHandle, DeviceEventFunction> DeviceObserverMap;
+ typedef std::list<UUID_t> DeviceIdList;
+private:
+ const Protocols::Protocol::Handle generateProtocolHandle();
+ bool isHandleInUse(Protocols::Protocol::Handle handle);
+ Device::SharedPtr addDeviceToList(const UUID_t& deviceId);
+
+ DeviceObserverHandle generateDeviceObserverHandle();
+ bool isDeviceObserverHandleInUse(DeviceObserverHandle observerHandle);
+ DeviceIdList getDeviceIdList();
+ void notifyDeviceObservers(DeviceEvent::DeviceChange event, const DeviceIdList& deviceIdList);
+
+private:
+ ProtocolMap protocolMap_;
+ DeviceList deviceList_;
+ DeviceObserverMap deviceObserverMap_;
+
+ mutex protocolMapMutex_;
+ mutex deviceListMutex_;
+ mutex deviceObserverMapMutex_;
+};
+
+}
+}
+}
+#endif /* MODELIMPL_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+//#include <iostream>
+#include <string.h>
+#include <stdint.h>
+
+#ifdef __linux__
+ #include <thread>
+ #include <pthread.h>
+ #include <chrono>
+#endif
+
+
+#include <functional>
+#include "InternalApi.h"
+#include "SimpleLogger.h"
+#include "MockProtocol.h"
+#include "Core.h"
+#include "Description.hpp"
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+#include <boost/uuid/uuid_io.hpp>
+
+const std::string MOCK_DEVICE_ID0 = "7c34ad16-ae8c-415b-94cc-d8053f4f9f8e";
+const std::string MOCK_DEVICE_ID1 = "646344d0-271c-49dd-8b13-3a7bec1237bd";
+const std::string MOCK_DEVICE_ID2 = "74c406ca-1cfb-4106-a82f-6123e3fe3555";
+
+static const char TAG[] = "CCFL-CoreTest.cpp";
+
+UUID_t toUuid(const std::string& uuidStr) {
+ boost::uuids::string_generator gen;
+ return gen(uuidStr);
+}
+
+using namespace std;
+
+void setPropertyAsync(const Intel::CCFL::API::PropertySetResult& result) {
+ Intel::CCFL::logDebug(TAG, "\t********entering main::setPropertyAsync********");
+ if (result.getResult() == Intel::CCFL::API::QueryResultType::SUCCESS) {
+ Intel::CCFL::logDebug(TAG, "\t QueryResultType::SUCCESS");
+ Intel::CCFL::logDebug(TAG, "\t property:");
+ Intel::CCFL::logDebug(TAG, "\t\t name = %s", result.getName().c_str());
+ Intel::CCFL::logDebug(TAG, "\t\t value = %s", result.getValue().c_str());
+ }
+ Intel::CCFL::logDebug(TAG, "\t********leaving main::setPropertyAsync********");
+}
+
+void getPropertyAsync(const Intel::CCFL::API::PropertyGetResult& result) {
+ Intel::CCFL::logDebug(TAG, "\t********entering main::getPropertyAsync********");
+ if (result.getResult() == Intel::CCFL::API::QueryResultType::SUCCESS) {
+ Intel::CCFL::logDebug(TAG, "\t QueryResultType::SUCCESS");
+ Intel::CCFL::logDebug(TAG, "\t property:");
+ Intel::CCFL::logDebug(TAG, "\t\t name = %s", result.getName().c_str());
+ Intel::CCFL::logDebug(TAG, "\t\t value = %s", result.getValue().c_str());
+ }
+ Intel::CCFL::logDebug(TAG, "\t********leaving main::getPropertyAsync********");
+}
+
+void getDescriptionAsync(const Intel::CCFL::API::DescriptionGetResult& result) {
+ Intel::CCFL::logDebug(TAG, "\t********entering main::getDescriptionAsync********");
+
+ if (result.getResult() == Intel::CCFL::API::QueryResultType::SUCCESS) {
+ Intel::CCFL::logDebug(TAG, "\t QueryResultType::SUCCESS");
+ std::set<Intel::CCFL::API::Service::SharedPtr> serviceSet = result.getServices();
+
+ for (auto iter = serviceSet.begin(); iter != serviceSet.end(); ++iter) {
+ Intel::CCFL::API::Service::WeakPtr serviceWeak = *iter;
+ Intel::CCFL::API::Service::SharedPtr service = serviceWeak.lock();
+ if (service) {
+ Intel::CCFL::logDebug(TAG, "\t service = %s", service->getName().c_str());
+
+ std::set<Intel::CCFL::API::Characteristic::SharedPtr> characteristicSet = service->getCharacteristics();
+ for (auto iter = characteristicSet.begin(); iter != characteristicSet.end(); ++iter) {
+ Intel::CCFL::API::Characteristic::WeakPtr characteristicWeak = *iter;
+ Intel::CCFL::API::Characteristic::SharedPtr characteristic = characteristicWeak.lock();
+ if (characteristic) {
+ Intel::CCFL::logDebug(TAG, "\t\t characteristic = %s", characteristic->getName().c_str());
+ Intel::CCFL::logDebug(TAG, "\t\t readable = %d", characteristic->isReadable());
+ Intel::CCFL::logDebug(TAG, "\t\t writable = %d", characteristic->isWritable());
+ Intel::CCFL::logDebug(TAG, "\t\t constant = %d", characteristic->isConstant());
+ }
+ }
+ }
+ }
+ }
+ Intel::CCFL::logDebug(TAG, "\t********leaving main::getDescriptionAsync********");
+}
+
+void getDevicesAsync(const Intel::CCFL::API::GetDevicesResult& result) {
+ Intel::CCFL::logDebug(TAG, "Entering main::getDevicesAsync");
+
+ if (result.getResult() == Intel::CCFL::API::QueryResultType::SUCCESS) {
+ Intel::CCFL::logDebug(TAG, "main::getDevicesAsync, QueryResultType::SUCCESS");
+ std::list<Intel::CCFL::API::Device::SharedPtr> deviceList = result.getDeviceList();
+ // Search list for the device based on device id
+ if (deviceList.size() > 0) {
+ for (auto iter = deviceList.begin(); iter != deviceList.end(); ++iter) {
+ Intel::CCFL::API::Device::WeakPtr deviceWeak = *iter;
+ Intel::CCFL::API::Device::SharedPtr device = deviceWeak.lock();
+ if (device) {
+ Intel::CCFL::logDebug(TAG, "\tDevice:");
+ Intel::CCFL::logDebug(TAG, "\t name = %s", device->getName().c_str());
+ Intel::CCFL::logDebug(TAG, "\t UUID = %s", to_string(device->getId()).c_str());
+
+ // Test characteristic stuff
+ if (device->getName() == "MockDevice0") {
+ if (device->getLinkCount() > 0) {
+ Intel::CCFL::API::Device::LinkList linkList = device->getLinks();
+ Intel::CCFL::API::Link::WeakPtr linkWeak = linkList.front();
+ Intel::CCFL::API::Link::SharedPtr linkShared = linkWeak.lock();
+ if (linkShared) {
+ // Test set/get properties
+ Intel::CCFL::API::DescriptionGetFunction descriptionGetFunction = getDescriptionAsync;
+ linkShared->getDescription(descriptionGetFunction);
+ Intel::CCFL::API::PropertyGetFunction propertyGetFunction = getPropertyAsync;
+ linkShared->getProperty("CHARACTERISTIC_0", propertyGetFunction);
+ linkShared->getProperty("CHARACTERISTIC_1", propertyGetFunction);
+
+ Intel::CCFL::API::PropertySetFunction propertySetFunction = setPropertyAsync;
+ linkShared->setProperty("CHARACTERISTIC_0", "new_CHARACTERISTIC_0_Value", propertySetFunction);
+ linkShared->setProperty("CHARACTERISTIC_1", "new_CHARACTERISTIC_1_Value", propertySetFunction);
+
+ linkShared->getProperty("CHARACTERISTIC_0", propertyGetFunction);
+ linkShared->getProperty("CHARACTERISTIC_1", propertyGetFunction);
+ }
+ }
+ }
+ }
+ }
+ }
+ else {
+ Intel::CCFL::logDebug(TAG, "\t No devices found");
+ }
+ }
+}
+
+#ifdef __ANDROID__
+ int android_jni_entry() {
+#elif defined __linux__
+ int main() {
+#endif
+
+ Intel::CCFL::logDebug(TAG, "Starting CCFL Core Test");
+
+ // Create MockProtocols. Two are created to make sure that multiples are registered and unregistered correctly
+ std::shared_ptr<Intel::CCFL::Protocols::MockProtocol> mockProtocol = std::make_shared<Intel::CCFL::Protocols::MockProtocol>();
+ mockProtocol->setName("MockProtocol");
+
+ // Get a model from the CCFL API so that we can access the API interface
+ Intel::CCFL::API::Model::WeakPtr modelWeak = Intel::CCFL::API::Model::createModel();
+ Intel::CCFL::API::Model::SharedPtr modelShared = modelWeak.lock();
+ if (modelShared) {
+
+ mockProtocol->setModel(modelShared);
+
+ // Register the MockProtocol
+ Intel::CCFL::Protocols::Protocol::Handle handle;
+ handle = modelShared->registerProtocol(mockProtocol);
+ Intel::CCFL::logDebug(TAG, "Protocol %s handle = %d", mockProtocol->getName().c_str(), (uint32_t)handle);
+
+ Intel::CCFL::API::GetDevicesFunction deviceFunc = getDevicesAsync;
+ modelShared->getDevices(deviceFunc);
+
+ mockProtocol->testAddDevice(toUuid(MOCK_DEVICE_ID0), "MockDevice0");
+ modelShared->getDevices(deviceFunc);
+
+ Intel::CCFL::API::DeviceEventFunction deviceEventLambda = [](const Intel::CCFL::API::DeviceEvent& result)->void {
+ Intel::CCFL::logDebug(TAG, "main::deviceEventAsyncLambda");
+ if (result.getResult() == Intel::CCFL::API::QueryResultType::SUCCESS) {
+ Intel::CCFL::API::DeviceObserverHandle handle = result.getObserverHandle();
+ Intel::CCFL::logDebug(TAG, "main::deviceEventAsyncLambda, observer handle = %ld", (uint32_t)handle);
+ std::list<Intel::CCFL::API::DeviceEvent::DeviceEventInfo> infoList = result.getDeviceIdList();
+ for (auto iter = infoList.begin(); iter != infoList.end(); ++iter) {
+ Intel::CCFL::API::DeviceEvent::DeviceEventInfo info = *iter;
+ Intel::CCFL::logDebug(TAG, "\t Device UUID = %s", to_string(info.deviceId).c_str());
+ switch (info.deviceChange) {
+ case Intel::CCFL::API::DeviceEvent::DeviceChange::DEVICE_CURRENT_COLLECTION:
+ Intel::CCFL::logDebug(TAG, "\t Event = DEVICE_CURRENT_COLLECTION");
+ break;
+ case Intel::CCFL::API::DeviceEvent::DeviceChange::DEVICE_ADDED:
+ Intel::CCFL::logDebug(TAG, "\t Event = DEVICE_ADDED");
+ break;
+ case Intel::CCFL::API::DeviceEvent::DeviceChange::DEVICE_REMOVED:
+ Intel::CCFL::logDebug(TAG, "\t Event = DEVICE_REMOVED");
+ break;
+ default:
+ Intel::CCFL::logDebug(TAG, "\t Event = unknown");
+ break;
+ }
+ }
+ }
+ };
+ modelShared->setDeviceObserver(deviceEventLambda);
+
+ mockProtocol->testAddDevice(toUuid(MOCK_DEVICE_ID1), "MockDevice1");
+ modelShared->getDevices(deviceFunc);
+ mockProtocol->testAddDevice(toUuid(MOCK_DEVICE_ID2), "MockDevice2");
+ modelShared->getDevices(deviceFunc);
+ mockProtocol->testRemoveDevice(toUuid(MOCK_DEVICE_ID0));
+ modelShared->getDevices(deviceFunc);
+
+ Intel::CCFL::logDebug(TAG, "Sleep for 5 sec");
+ std::this_thread::sleep_for(std::chrono::seconds(5));
+ modelShared->unregisterProtocol(handle);
+ Intel::CCFL::logDebug(TAG, "Sleep for 5 sec");
+ }
+
+
+ Intel::CCFL::logDebug(TAG, "Exiting CCFL Core Test");
+ return 0;
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include "MockProtocol.h"
+#include "SimpleLogger.h"
+#include "InternalApi.h"
+#include "Link.hpp"
+#include "Description.hpp"
+#include "Service.hpp"
+#include "Characteristic.hpp"
+#include <set>
+
+#include <boost/uuid/uuid.hpp>
+#include <boost/uuid/uuid_generators.hpp>
+#include <boost/uuid/uuid_io.hpp>
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace Protocols {
+
+static const char TAG[] = "MockProtocol";
+
+const std::string MockProtocol::MOCK_DEVICE_ID = "7c34ad16-ae8c-415b-94cc-d8053f4f9f8e";
+static std::string characteristic0Value = "CHARACTERISTIC_0_VALUE";
+
+// ============================================================================
+// PropertyGetResult Implementation Class
+// ============================================================================
+class PropertyGetResultImpl : public API::PropertyGetResult {
+public:
+ PropertyGetResultImpl() {
+ name_ = "";
+ value_ = "";
+ }
+ virtual ~PropertyGetResultImpl() {}
+
+public:
+ virtual API::QueryResultType getResult() const {
+ return API::QueryResultType::SUCCESS;
+ }
+
+ virtual const std::string& getName() const {
+ return name_;
+ }
+
+ virtual const std::string& getValue() const {
+ return value_;
+ }
+
+public:
+ std::string name_;
+ std::string value_;
+};
+
+// ============================================================================
+// PropertySetResult Implementation Class
+// ============================================================================
+class PropertySetResultImpl : public API::PropertySetResult {
+public:
+ PropertySetResultImpl() {
+ name_ = "";
+ value_ = "";
+ }
+ virtual ~PropertySetResultImpl() {}
+
+public:
+ virtual API::QueryResultType getResult() const {
+ return API::QueryResultType::SUCCESS;
+ }
+
+ virtual const std::string& getName() const {
+ return name_;
+ }
+
+ virtual const std::string& getValue() const {
+ return value_;
+ }
+
+public:
+ std::string name_;
+ std::string value_;
+
+};
+
+// ============================================================================
+// Characteristic Implementation Class
+// ============================================================================
+class CharacteristicImpl : public API::Characteristic {
+public:
+ CharacteristicImpl() {
+ name_ = "";
+ isReadable_ = true;
+ isWritable_ = true;
+ isConstant_ = false;
+ }
+ virtual ~CharacteristicImpl() {}
+
+public:
+ virtual const std::string& getName() const {
+ return name_;
+ }
+ virtual bool isReadable() const {
+ return isReadable_;
+ }
+ virtual bool isWritable() const {
+ return isWritable_;
+ }
+ virtual bool isConstant() const {
+ return isConstant_;
+ }
+
+public:
+ std::string name_;
+ bool isReadable_;
+ bool isWritable_;
+ bool isConstant_;
+};
+
+// ============================================================================
+// Service Implementation Class
+// ============================================================================
+class ServiceImpl : public API::Service {
+public:
+ ServiceImpl() {
+ name_ = "";
+ }
+
+ virtual ~ServiceImpl() {}
+
+public:
+
+ virtual const std::string& getName() const {
+ return name_;
+ }
+
+ virtual const std::set<API::Characteristic::SharedPtr>& getCharacteristics() const {
+ return characteristicSet_;
+ }
+public:
+ std::string name_;
+ std::set<API::Characteristic::SharedPtr> characteristicSet_;
+};
+// ============================================================================
+// DescriptionGetResult Implementation Class
+// ============================================================================
+class DescriptionGetResultImpl : public API::DescriptionGetResult {
+public:
+ virtual ~DescriptionGetResultImpl() {}
+
+public:
+ virtual API::QueryResultType getResult() const {
+ return API::QueryResultType::SUCCESS;
+ };
+
+ virtual const std::set<API::Service::SharedPtr>& getServices() const {
+ return serviceSet_;
+ }
+
+public:
+ std::set<API::Service::SharedPtr> serviceSet_;
+};
+
+// ============================================================================
+// RegisteredSetPropFunction
+// ============================================================================
+void setPropertyFunction(const std::string& propertyName, const std::string& propertyValue, const API::PropertySetFunction& asyncReturnFunc) {
+ logDebug(TAG, "Entering MockProtocol::setPropertyFunction");
+
+ PropertySetResultImpl result;
+
+ if (propertyName == "CHARACTERISTIC_0") {
+ // CHARACTERISTIC_0 is read/write, non-constant, so allow it to be set to new value
+ result.name_ = "CHARACTERISTIC_0";
+ characteristic0Value = propertyValue;
+ result.value_ = characteristic0Value;
+ }
+ else if (propertyName == "CHARACTERISTIC_1") {
+ // CHARACTERISTIC_1 is constant, so ignore new value
+ result.name_ = "CHARACTERISTIC_1";
+ result.value_ = "CHARACTERISTIC_1_VALUE";
+ }
+
+ asyncReturnFunc(result);
+}
+// ============================================================================
+// RegisteredGetPropFunction
+// ============================================================================
+void getPropertyFunction(const std::string& propertyName, const API::PropertyGetFunction& asyncReturnFunc) {
+ logDebug(TAG, "Entering MockProtocol::getPropertyFunction");
+
+ PropertyGetResultImpl result;
+
+ if (propertyName == "CHARACTERISTIC_0") {
+ result.name_ = "CHARACTERISTIC_0";
+ result.value_ = characteristic0Value;
+ }
+ else if (propertyName == "CHARACTERISTIC_1") {
+ result.name_ = "CHARACTERISTIC_1";
+ result.value_ = "CHARACTERISTIC_1_VALUE";
+ }
+
+ asyncReturnFunc(result);
+}
+
+// ============================================================================
+// RegisteredGetDescriptionFunction
+// ============================================================================
+void getDescriptionFunction(const API::DescriptionGetFunction& asyncReturnFunc) {
+ logDebug(TAG, "Entering MockProtocol::getDescriptionFunction");
+
+ DescriptionGetResultImpl result;
+
+ std::shared_ptr<ServiceImpl> service = std::make_shared<ServiceImpl>();
+ if (service) {
+ service->name_ = "SERVICE_A";
+ std::shared_ptr<CharacteristicImpl> characteristic0 = std::make_shared<CharacteristicImpl>();
+ if (characteristic0) {
+ characteristic0->name_ = "CHARACTERISTIC_0";
+ service->characteristicSet_.insert(characteristic0);
+ }
+ std::shared_ptr<CharacteristicImpl> characteristic1 = std::make_shared<CharacteristicImpl>();
+ if (characteristic1) {
+ characteristic1->name_ = "CHARACTERISTIC_1";
+ characteristic1->isReadable_ = true;
+ characteristic1->isWritable_ = false;
+ characteristic1->isConstant_ = true;
+
+ service->characteristicSet_.insert(characteristic1);
+ }
+
+ result.serviceSet_.insert(service);
+ }
+
+
+ // Invoke the callback
+ asyncReturnFunc(result);
+}
+
+// ============================================================================
+// Class
+// ============================================================================
+MockProtocol::MockProtocol()
+{
+ logDebug(TAG, "Entering MockProtocol::MockProtocol");
+
+ name_ = "Mock Protocol";
+ handle_ = Protocol::INVALID_HANDLE;
+}
+
+MockProtocol::~MockProtocol()
+{
+ logDebug(TAG, "Entering MockProtocol::~MockProtocol");
+}
+
+void MockProtocol::setModel(const std::shared_ptr<Intel::CCFL::API::Model>& model) {
+ logDebug(TAG, "Entering MockProtocol::setModel");
+ model_ = model;
+}
+
+const Intel::CCFL::Protocols::Protocol::Handle MockProtocol::getHandle() {
+ logDebug(TAG, "Entering MockProtocol::getHandle");
+ return 0;
+}
+
+void MockProtocol::setHandle(const Handle handle) {
+ logDebug(TAG, "Entering MockProtocol::setHandle");
+ handle_ = handle;
+}
+
+const std::string& MockProtocol::getName() {
+// logDebug(TAG, "Entering MockProtocol::getName");
+ return name_;
+}
+
+void MockProtocol::setName(const std::string& name)
+{
+ logDebug(TAG, "Entering MockProtocol::setName, name = %s", name.c_str());
+ name_ = name;
+}
+
+void MockProtocol::forceDeviceDiscovery() {
+ logDebug(TAG, "Entering MockProtocol::forceDeviceDiscovery");
+}
+
+// Test interface
+void MockProtocol::testAddDevice(const UUID_t& deviceId, const std::string deviceName) {
+ logDebug(TAG, "Entering MockProtocol::testAddDevice, device name = %s, device UUID = %s", deviceName.c_str(), to_string(deviceId).c_str());
+
+ std::shared_ptr<API::Model> sharedModel = model_.lock();
+ if (sharedModel) {
+ API::Device::SharedPtr device = sharedModel->getDevice(deviceId);
+ if (device) {
+ device->setName(deviceName);
+ // Add a link to the device
+ API::Link::SharedPtr link = std::make_shared<API::Link>();
+
+ // Register property functions for the link
+ API::Link::RegisteredGetDescriptionFunction regGetDescriptionFunction = getDescriptionFunction;
+ link->registerGetDescriptionFunction(regGetDescriptionFunction);
+ API::Link::RegisteredGetPropFunction regGetPropFunction = getPropertyFunction;
+ link->registerGetPropertyFunction(regGetPropFunction);
+ API::Link::RegisteredSetPropFunction regSetPropFunction = setPropertyFunction;
+ link->registerSetPropertyFunction(regSetPropFunction);
+
+ // Add the link to the device and signal the model that the device changed
+ device->addLink(link);
+ sharedModel->signalDeviceChange(deviceId, API::DeviceEvent::DeviceChange::DEVICE_ADDED);
+ }
+ }
+}
+
+void MockProtocol::testRemoveDevice(const UUID_t& deviceId) {
+ logDebug(TAG, "Entering MockProtocol::testRemoveDevice, device UUID = %s", to_string(deviceId).c_str());
+
+ std::shared_ptr<API::Model> sharedModel = model_.lock();
+ if (sharedModel) {
+ API::Device::SharedPtr device = sharedModel->getDevice(deviceId);
+ if (device) {
+ // Remove the link
+ uint32_t linkCnt = device->getLinkCount();
+ logDebug(TAG, "MockProtocol::testRemoveDevice, link count = %d", linkCnt);
+ if (linkCnt > 0) {
+ API::Device::LinkList linkList = device->getLinks();
+ API::Link::SharedPtr link = linkList.front();
+ if (link) {
+ logDebug(TAG, "MockProtocol::testRemoveDevice, removing link");
+ if (device->removeLink(link)) {
+ logDebug(TAG, "MockProtocol::testRemoveDevice, link removed, signaling device change");
+ sharedModel->signalDeviceChange(deviceId, API::DeviceEvent::DeviceChange::DEVICE_REMOVED);
+ }
+ }
+ }
+ }
+ }
+}
+
+}
+}
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef MOCKPROTOCOL_H_
+#define MOCKPROTOCOL_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <memory>
+#include <string>
+#include <functional>
+#include "Protocol.hpp"
+#include "Core.h"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace Intel {
+namespace CCFL {
+namespace Protocols {
+
+// ============================================================================
+// Class
+// ============================================================================
+class MockProtocol : public Protocol
+{
+public:
+ MockProtocol();
+ virtual ~MockProtocol();
+public:
+ virtual void setModel(const std::shared_ptr<Intel::CCFL::API::Model>& model);
+ virtual const Handle getHandle();
+ virtual void setHandle(const Handle handle);
+ virtual const std::string& getName();
+ virtual void setName(const std::string& name);
+ virtual void forceDeviceDiscovery();
+
+private:
+ std::string name_;
+ Handle handle_;
+ std::weak_ptr<API::Model> model_;
+
+// Test interface
+public:
+ void testAddDevice(const UUID_t& deviceId, const std::string deviceName);
+ void testRemoveDevice(const UUID_t& deviceId);
+private:
+ static const std::string MOCK_DEVICE_ID;
+
+};
+
+
+}
+}
+}
+
+#endif /* MOCKPROTOCOL_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include "LiteConnection.h"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace remoting {
+
+ // ============================================================================
+ // Constructor/Destructor
+ // ============================================================================
+ //---------------------------------------------------------------------------
+ // Constructor
+ //---------------------------------------------------------------------------
+ LiteConnection::LiteConnection(int socket) : socket_(socket)
+ {
+
+ }
+
+ //---------------------------------------------------------------------------
+ // Destructor
+ //---------------------------------------------------------------------------
+ LiteConnection::~LiteConnection()
+ {
+ }
+
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef LITECONNECTION_H_
+#define LITECONNECTION_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace remoting {
+
+ // ==========================================================================
+ // Class
+ // ==========================================================================
+
+ class LiteConnection {
+ public:
+ // TODO: socket parameter is faked with an int for now until I know how the connection info will be conveyed
+ LiteConnection(int socket);
+ virtual ~LiteConnection();
+
+ private:
+ int socket_;
+ };
+
+}
+
+#endif /* LITECONNECTION_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include "LiteRemoting.h"
+
+#include <boost/make_shared.hpp>
+#include <boost/bind.hpp>
+#include <functional>
+#include <stdexcept>
+
+#ifdef DEBUG
+#include <android/log.h>
+#endif
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace remoting {
+
+ // ============================================================================
+ // Macros
+ // ============================================================================
+ // TODO: Need application ID for Remoting
+ const std::string LiteRemoting::APPLICATION_UUID_STRING = "7A1B397B-B576-44C4-943F-000000000001";
+
+// ============================================================================
+// Macros
+// ============================================================================
+#ifdef DEBUG
+ #define LOG_PRINT(X) __android_log_print(ANDROID_LOG_VERBOSE, "LiteRemoting", (X));
+#else
+ #define LOG_PRINT(X)
+#endif
+
+// ============================================================================
+// Constructor/Destructor/getInstance
+// ============================================================================
+ //---------------------------------------------------------------------------
+ // Constructor
+ // Called by getInstance method (Singleton patter)
+ //---------------------------------------------------------------------------
+ LiteRemoting::LiteRemoting(PrivateConstructKey key) {
+
+ apiResultReady_ = false;
+
+// public static final String applicationId = "7A1B397B-B576-44C4-943F-000000000001";
+// public static final UUID applicationUUID = UUID.fromString(applicationId);
+
+ // Begin CCF API interaction
+ pCCFService_ = API::Service::createService();
+ if (pCCFService_)
+ {
+ pCCFService_->registerApplication();
+
+ UUID_t applicationId;
+ StringToUuid(APPLICATION_UUID_STRING.c_str(), &applicationId);
+
+ pCCFContext_ = pCCFService_->createContext(applicationId);
+
+ if (pCCFContext_)
+ {
+ doStartup();
+ }
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ // Destructor
+ //---------------------------------------------------------------------------
+ LiteRemoting::~LiteRemoting() {
+ // Empty containers
+ sessionMap_.clear();
+ targetDeviceProxyMap_.clear();
+
+ // Turn off observer callbacks
+ pCCFContext_->setSessionObserver();
+ pCCFContext_->setUserObserver();
+
+ // CCF APP interaction
+ if (pCCFService_)
+ {
+ pCCFService_->deregisterApplication();
+ }
+ }
+
+ //---------------------------------------------------------------------------
+ // getInstance (Singleton pattern
+ //---------------------------------------------------------------------------
+ // Get singleton instance of LiteRemoting
+ boost::shared_ptr<LiteRemoting> LiteRemoting::getInstance() {
+ LOG_PRINT("LiteRemoting::getInstance()");
+
+ static boost::shared_ptr<LiteRemoting> instance = boost::make_shared<LiteRemoting>(PrivateConstructKey());
+
+ return instance;
+ }
+
+// ============================================================================
+// Methods
+// ============================================================================
+ void LiteRemoting::doStartup() {
+
+ // Get the local session id
+ boost::unique_lock<boost::mutex> lock(mutex_);
+ queryMySessionId();
+ while (!apiResultReady_)
+ {
+ // TODO: maybe do cond_.timed_wait() ???
+ cond_.wait(lock);
+ }
+
+ // Get local session info
+ lock.lock();
+ queryMySessionInfo();
+ while (!apiResultReady_)
+ {
+ // TODO: maybe do cond_.timed_wait() ???
+ cond_.wait(lock);
+ }
+
+ // Now that we have local session info, set the session observer
+ pCCFContext_->setSessionObserver(boost::bind(&LiteRemoting::sessionObserver, this, _1));
+
+ // TODO: set up connection observer
+
+ // TODO: set up device observer
+
+ }
+
+ void LiteRemoting::addSessionToMap(UUID_t sessionId) {
+ // Add session to the sessionMap
+ auto iter = sessionMap_.find(sessionId);
+ if (iter == sessionMap_.end() )
+ {
+ // sessionUUID not found, so add session
+ sessionMap_[sessionId] = boost::make_shared<LiteSessionImpl>(pCCFContext_, sessionId);
+ }
+ }
+
+ boost::shared_ptr<LiteSessionImpl> LiteRemoting::getSessionFromMap(UUID_t sessionId) {
+ boost::shared_ptr<LiteSessionImpl> pSession;
+ try {
+ pSession = sessionMap_.at(sessionId);
+ }
+ catch (const std::out_of_range& oor) {
+ // sessionId not found, so add session
+ sessionMap_[sessionId] = boost::make_shared<LiteSessionImpl>(pCCFContext_, sessionId);
+ }
+
+ return sessionMap_[sessionId];
+ }
+
+ void LiteRemoting::addTargetDeviceToMap(UUID_t targetDeviceId) {
+ // A LiteTargetDeviceProxy with this targetDeviceId was not found, so add
+ // Add target device to the targetDeviceProxyMap_
+ auto iter = targetDeviceProxyMap_.find(targetDeviceId);
+ if (iter == targetDeviceProxyMap_.end() )
+ {
+ // targetDeviceId not found, so add session
+ targetDeviceProxyMap_[targetDeviceId] = boost::make_shared<LiteTargetDeviceProxy>(targetDeviceId);
+ }
+
+ }
+
+ boost::shared_ptr<LiteTargetDeviceProxy> LiteRemoting::getTargetDeviceFromMap(UUID_t targetDeviceId) {
+ boost::shared_ptr<LiteTargetDeviceProxy> pTargetDevice;
+ try {
+ pTargetDevice = targetDeviceProxyMap_.at(targetDeviceId);
+ }
+ catch (const std::out_of_range& oor) {
+ // sessionId not found, so add session
+ targetDeviceProxyMap_[targetDeviceId] = boost::make_shared<LiteTargetDeviceProxy>(targetDeviceId);
+ }
+
+ return targetDeviceProxyMap_[targetDeviceId];
+
+ }
+
+ void LiteRemoting::handleNewTargetDevice(UUID_t targetDeviceId) {
+ addTargetDeviceToMap(targetDeviceId);
+ //session.sendDeviceArrival(device);
+ }
+
+ // TODO: socket parameter is faked with an int for now until I know how the connection info will be conveyed
+ void LiteRemoting::handleNewConnection(UUID_t sessionId, int socket) {
+ // Validate socket
+ if (socket == 0) {
+ return;
+ }
+
+ // Get the specified session and a new connection
+ boost::shared_ptr<LiteSessionImpl> pSession = getSessionFromMap(sessionId);
+ boost::shared_ptr<LiteConnection> pConnection = boost::make_shared<LiteConnection>(socket);
+ // TODO: add device info to connection
+
+ // List<LiteDeviceProxy> deviceProxyList = new ArrayList<LiteDeviceProxy>();
+ // synchronized (deviceProxySet) {
+ // for(LiteDeviceProxy device : deviceProxySet) {
+ // if (device.isLocal()) {
+ // deviceProxyList.add(device);
+ // }
+ // }
+ // }
+ // for(LiteDeviceProxy device : deviceProxyList) {
+ // try {
+ // connection.sendDeviceArrival(device);
+ // } catch (IOException e) {
+ // e.printStackTrace();
+ // }
+ // }
+
+ // Add the new connection to the session
+ pSession->addConnection(pConnection);
+ }
+
+ void LiteRemoting::queryMySessionId() {
+ apiResultReady_ = false;
+
+ pCCFContext_->querySessionId([this](const API::SessionIdResult& sessionIdResult) -> void {
+
+ API::SessionIdResult::ResultType queryResult = sessionIdResult.getResult();
+ boost::lock_guard<boost::mutex> lock(mutex_);
+ switch (queryResult) {
+ case API::SessionIdResult::ResultType::Success:
+ LOG_PRINT("LiteRemoting::queryMySessionId() - queryResult == Success");
+ mySessionId_ = sessionIdResult.getSessionId();
+ apiResultReady_ = true;
+ break;
+ case API::SessionIdResult::ResultType::InternalError:
+ LOG_PRINT("LiteRemoting::queryMySessionId() - queryResult == InternalError");
+ break;
+ case API::SessionIdResult::ResultType::InvalidLocalSession:
+ LOG_PRINT("LiteRemoting::queryMySessionId() - queryResult == InvalidLocalSession");
+ break;
+ default:
+ LOG_PRINT("LiteRemoting::queryMySessionId() - queryResult == unknown");
+ break;
+ }
+ cond_.notify_one();
+ });
+ }
+
+ void LiteRemoting::queryMySessionInfo()
+ {
+ apiResultReady_ = false;
+
+// pCCFContext_->querySession(sessionUUID, std::bind(&LiteRemoting::querySessionObserver, this, _1));
+ pCCFContext_->querySession(mySessionId_, [this](const API::SessionQueryResult& sessionQueryResult) -> void {
+
+ API::QueryResultType queryResult = sessionQueryResult.getResult();
+ boost::lock_guard<boost::mutex> lock(mutex_);
+ switch (queryResult) {
+ case API::QueryResultType::Success:
+ LOG_PRINT("LiteRemoting::queryMySessionInfo() - queryResult == Success");
+ // TODO: verify that CCF application is in the session application set?
+
+ // Add my local session to the sessionMap
+ addSessionToMap(mySessionId_);
+ sessionMap_[mySessionId_]->setPublicAvatarId(sessionQueryResult.getPublicAvatarId());
+ sessionMap_[mySessionId_]->setPrivateAvatarId(sessionQueryResult.getPrivateAvatarId());
+ sessionMap_[mySessionId_]->setPublicAvatarId(sessionQueryResult.getPublicAvatarId());
+ sessionMap_[mySessionId_]->setUserId(sessionQueryResult.getUserId());
+ sessionMap_[mySessionId_]->setIssuer(sessionQueryResult.getIssuer());
+ sessionMap_[mySessionId_]->setName(sessionQueryResult.getName());
+ sessionMap_[mySessionId_]->setStatusText(sessionQueryResult.getStatusText());
+ sessionMap_[mySessionId_]->setSecurityCode(sessionQueryResult.getSecurityCode());
+ sessionMap_[mySessionId_]->setApplicationSet(sessionQueryResult.getApplicationSet());
+
+ // TODO: add more conditions before inviting to join session?
+ if (!sessionMap_[mySessionId_]->isConnected() && !sessionMap_[mySessionId_]->isInvited()) {
+ sessionMap_[mySessionId_]->invite();
+ }
+
+ apiResultReady_ = true;
+ break;
+ case API::QueryResultType::NotFound:
+ LOG_PRINT("LiteRemoting::queryMySessionInfo() - queryResult == NotFound");
+ break;
+ default:
+ LOG_PRINT("LiteRemoting::queryMySessionInfo() - queryResult == unknown");
+ break;
+ }
+ cond_.notify_one();
+ });
+ }
+
+// ============================================================================
+// Observers
+// ============================================================================
+ void LiteRemoting::sessionObserver(const API::SessionEvent& sessionEvent)
+ {
+
+ UUID_t sessionId = sessionEvent.getSessionId();
+
+ // TODO: Need to put in logic for seeing what's changed. Added, dropped, paused?
+// int changeMask = sessionEvent.getWhatChanged();
+
+ // See if we already have the session in the map. If not, create and add
+ addSessionToMap(sessionId);
+ }
+
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef LITEREMOTING_H_
+#define LITEREMOTING_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <boost/shared_ptr.hpp>
+#include <boost/thread.hpp>
+#include <uuid.h>
+#include <map>
+#include <set>
+#include "api.h"
+using namespace Intel::STC;
+
+#include "LiteSessionImpl.h"
+#include "LiteUUIDLess.hpp"
+#include "LiteTargetDevice.hpp"
+#include "LiteTargetDeviceProxy.h"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace remoting {
+
+ // ==========================================================================
+ // Class
+ // ==========================================================================
+ class LiteRemoting {
+ // ============================================================
+ // Constants
+ // ============================================================
+ public:
+ static const std::string APPLICATION_UUID_STRING;
+
+ // ============================================================
+ // Type Definition
+ // ============================================================
+ public:
+ typedef boost::shared_ptr<LiteRemoting> Ptr;
+
+ // ============================================================
+ // Singleton
+ // ============================================================
+ public:
+ static boost::shared_ptr<LiteRemoting> getInstance();
+
+ // ============================================================
+ // Private key for Singleton with shared_ptr
+ // LiteRemoting ctor must be public for make_ptr.
+ // But since we are a singleton, we don't want to allow clients
+ // to call the ctor. Since client can't access
+ // PrivateConstructKey, it can't call the public ctor.
+ // ============================================================
+ private:
+ struct PrivateConstructKey {};
+
+ // ============================================================
+ // Constructor and Destructor
+ // ============================================================
+ public:
+ LiteRemoting(PrivateConstructKey key);
+ virtual ~LiteRemoting();
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+
+
+ // ============================================================
+ // Private copy constructor for Singleton
+ // ============================================================
+ private:
+ LiteRemoting(const LiteRemoting&);
+
+ // ============================================================
+ // Private Attributes
+ // ============================================================
+ private:
+ // CCF API Interface
+ API::Service::SharedPtr pCCFService_;
+ API::Context::SharedPtr pCCFContext_;
+
+ UUID_t mySessionId_;
+ std::map <UUID_t, boost::shared_ptr<LiteSessionImpl>, LiteUUIDLess> sessionMap_;
+ std::map <UUID_t, boost::shared_ptr<LiteTargetDeviceProxy>, LiteUUIDLess> targetDeviceProxyMap_;
+ boost::condition_variable cond_;
+ boost::mutex mutex_;
+ bool apiResultReady_;
+
+ // ============================================================
+ // Private Methods
+ // ============================================================
+ private:
+ void doStartup();
+ void queryMySessionId();
+ void queryMySessionInfo();
+ void addSessionToMap(UUID_t sessionId);
+ boost::shared_ptr<LiteSessionImpl> getSessionFromMap(UUID_t sessionId);
+ void addTargetDeviceToMap(UUID_t targetDeviceId);
+ boost::shared_ptr<LiteTargetDeviceProxy> getTargetDeviceFromMap(UUID_t targetDeviceId);
+ void handleNewConnection(UUID_t sessionId, int socket);
+ void handleNewTargetDevice(UUID_t targetDeviceId);
+
+ // ============================================================
+ // Observers
+ // ============================================================
+ private:
+ void sessionObserver(const API::SessionEvent& sessionEvent);
+
+ };
+}
+#endif /* LITEREMOTING_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef LITESESSION_HPP_
+#define LITESESSION_HPP_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <string>
+#include <uuid.h>
+#include <set>
+#include <boost/shared_ptr.hpp>
+#include "api.h"
+using namespace Intel::STC;
+
+#include "LiteConnection.h"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace remoting {
+
+ class LiteSession
+ {
+
+ public:
+ LiteSession(API::Context::SharedPtr pCCFContext, UUID_t uuid) : pCCFContext_(pCCFContext), sessionId_(uuid) {};
+ virtual ~LiteSession() { connectionSet_.clear(); };
+
+ virtual void invite() = 0;
+ virtual void disconnect() = 0;
+
+ public:
+ bool isInvited() {
+ return isInvited_;
+ }
+
+ bool isConnected() {
+ return isConnected_;
+ }
+
+ void setPublicAvatarId(const UUID_t& avatarId) {
+ publicAvatarId_ = avatarId;
+ }
+
+ void setPrivateAvatarId(const UUID_t& avatarId) {
+ privateAvatarId_ = avatarId;
+ }
+
+ void setUserId(const UUID_t& userId) {
+ userId_ = userId;
+ }
+
+ void setIssuer(const std::string& issuer) {
+ issuer_ = issuer;
+ }
+
+ void setName(const std::string& name) {
+ sessionName_ = name;
+ }
+
+ void setStatusText(const std::string& text) {
+ statusText_ = text;
+ }
+
+ void setSecurityCode(const std::string& code) {
+ securityCode_ = code;
+ }
+
+ void setApplicationSet(const std::set<UUID_t>& applicationSet) {
+ applicationSet_ = applicationSet;
+ }
+
+ const UUID_t& getPublicAvatarId() {
+ return publicAvatarId_;
+ }
+
+ const UUID_t& getPrivateAvatarId() {
+ return privateAvatarId_;
+ }
+
+ const UUID_t& getUserId() {
+ return userId_;
+ }
+
+ const std::string& getIssuer() {
+ return issuer_;
+ }
+
+ const std::string& getName() {
+ return sessionName_;
+ }
+
+ const std::string& getStatusText() {
+ return statusText_;
+ }
+
+ const std::string& getSecurityCode() {
+ return securityCode_;
+ }
+ const std::set<UUID_t>& getApplicationSet() {
+ return applicationSet_;
+ }
+
+ void addConnection(boost::shared_ptr<LiteConnection> connection) {
+ connectionSet_.insert(connection);
+ }
+
+ void removeConnection(boost::shared_ptr<LiteConnection> connection) {
+ connectionSet_.erase(connection);
+ }
+
+ protected:
+ bool onLocalNetwork_;
+ bool onCloudNetwork_;
+ bool isController_;
+ bool isInvited_;
+ bool isConnected_;
+
+ API::Context::SharedPtr pCCFContext_;
+ API::InvitationBuilder::SharedPtr pInvitationBuilder_;
+
+ UUID_t sessionId_;
+ UUID_t publicAvatarId_;
+ UUID_t privateAvatarId_;
+ UUID_t userId_;
+ std::string issuer_;
+ std::string sessionName_;
+ std::string statusText_;
+ std::string securityCode_;
+ std::set <UUID_t> applicationSet_;
+
+ std::set<boost::shared_ptr<LiteConnection>> connectionSet_;
+
+
+ };
+
+}
+
+
+#endif /* LITESESSION_HPP_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <string>
+#include "LiteSessionImpl.h"
+
+#ifdef DEBUG
+#include <android/log.h>
+#endif
+
+namespace remoting {
+
+ LiteSessionImpl::LiteSessionImpl(API::Context::SharedPtr pCCFContext, UUID_t uuid) : LiteSession(pCCFContext, uuid)
+ {
+#ifdef DEBUG
+ __android_log_print(ANDROID_LOG_VERBOSE, tag, "LiteSessionImpl::LiteSessionImpl()");
+#endif
+
+ if (pCCFContext_)
+ {
+ // Set callbacks
+ using namespace std::placeholders;
+
+ pCCFContext_->querySession(sessionId_, std::bind(&LiteSessionImpl::querySessionObserver, this, _1));
+ }
+ }
+
+ LiteSessionImpl::~LiteSessionImpl()
+ {
+ applicationSet_.clear();
+ }
+
+
+ void LiteSessionImpl::invite() {
+ if (!isConnected_ && !isInvited_) {
+ if (pCCFContext_) {
+ pInvitationBuilder_ = pCCFContext_->createInvitationBuilder();
+ isInvited_ = true;
+ }
+ }
+ }
+
+ void LiteSessionImpl::disconnect() {
+ // TODO: implement
+ }
+
+ void LiteSessionImpl::querySessionObserver(const API::SessionQueryResult& sessionQueryResult)
+ {
+
+ }
+}
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef LITESESSIONIMPL_H_
+#define LITESESSIONIMPL_H_
+
+#include "LiteSession.hpp"
+#include "api.h"
+using namespace Intel::STC;
+
+namespace remoting {
+
+ class LiteSessionImpl : public LiteSession
+ {
+ public:
+ LiteSessionImpl(API::Context::SharedPtr pCCFContext, UUID_t uuid);
+ virtual ~LiteSessionImpl();
+
+ virtual void invite();
+ virtual void disconnect();
+
+ private:
+ // Listeners
+ void querySessionObserver(const API::SessionQueryResult& sessionQueryResult);
+ };
+}
+
+
+#endif /* LITESESSIONIMPL_H_ */
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef LITETARGETDEVICE_HPP_
+#define LITETARGETDEVICE_HPP_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <string>
+#include <uuid.h>
+
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace remoting {
+
+ // ==========================================================================
+ // Class
+ // ==========================================================================
+ class LiteTargetDevice
+ {
+ public:
+ LiteTargetDevice(UUID_t uuid) : deviceId_(uuid), name_("Unknown target device"), isLocal_(false) {};
+ virtual ~LiteTargetDevice() {};
+
+ const UUID_t& getDeviceUUID() {
+ return deviceId_;
+ }
+
+ const std::string& getName() {
+ return name_;
+ }
+
+ bool isLocal() {
+ return isLocal_;
+ }
+
+ void setName(const std::string& name) {
+ name_ = name;
+ }
+
+ void setLocal(bool isLocal) {
+ isLocal_ = isLocal;
+ }
+
+ protected:
+ UUID_t deviceId_;
+ std::string name_;
+ bool isLocal_;
+ };
+
+}
+
+#endif /* LITETARGETDEVICE_HPP_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include "LiteTargetDeviceProxy.h"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace remoting {
+
+ // ============================================================================
+ // Constructor/Destructor
+ // ============================================================================
+ //---------------------------------------------------------------------------
+ // Constructor
+ //---------------------------------------------------------------------------
+ LiteTargetDeviceProxy::LiteTargetDeviceProxy(UUID_t uuid) : LiteTargetDevice(uuid)
+ {
+ }
+
+ LiteTargetDeviceProxy::~LiteTargetDeviceProxy()
+ {
+ }
+
+
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef LITETARGETDEVICEPROXY_H_
+#define LITETARGETDEVICEPROXY_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <set>
+
+#include "LiteTargetDevice.hpp"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace remoting {
+
+ // ==========================================================================
+ // Class
+ // ==========================================================================
+
+class LiteTargetDeviceProxy: public LiteTargetDevice
+{
+public:
+ // Methods
+ LiteTargetDeviceProxy(UUID_t uuid);
+ virtual ~LiteTargetDeviceProxy();
+
+
+private:
+};
+
+}
+
+#endif /* LITETARGETDEVICEPROXY_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef LITEUUIDLESS_HPP_
+#define LITEUUIDLESS_HPP_
+
+#include <uuid.h>
+
+namespace remoting {
+
+ class LiteUUIDLess
+ {
+ public:
+ bool operator()(const UUID_t &uuid1, const UUID_t &uuid2) const
+ {
+ return memcmp(&uuid1, &uuid2, sizeof(uuid1))<0;
+ }
+ };
+
+}
+
+
+#endif /* LITEUUIDLESS_HPP_ */
--- /dev/null
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
+ <storageModule moduleId="org.eclipse.cdt.core.settings">
+ <cconfiguration id="cdt.managedbuild.toolchain.gnu.base.1018092337">
+ <storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.toolchain.gnu.base.1018092337" moduleId="org.eclipse.cdt.core.settings" name="Default">
+ <externalSettings/>
+ <extensions>
+ <extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
+ <extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
+ </extensions>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <configuration buildProperties="" id="cdt.managedbuild.toolchain.gnu.base.1018092337" name="Default" parent="org.eclipse.cdt.build.core.emptycfg">
+ <folderInfo id="cdt.managedbuild.toolchain.gnu.base.1018092337.1087568516" name="/" resourcePath="">
+ <toolChain id="cdt.managedbuild.toolchain.gnu.base.1117193088" name="cdt.managedbuild.toolchain.gnu.base" superClass="cdt.managedbuild.toolchain.gnu.base">
+ <targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.target.gnu.platform.base.2034178578" name="Debug Platform" osList="linux,hpux,aix,qnx" superClass="cdt.managedbuild.target.gnu.platform.base"/>
+ <builder id="cdt.managedbuild.target.gnu.builder.base.136308549" managedBuildOn="false" name="Gnu Make Builder.Default" superClass="cdt.managedbuild.target.gnu.builder.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.archiver.base.916466382" name="GCC Archiver" superClass="cdt.managedbuild.tool.gnu.archiver.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.compiler.base.542165745" name="GCC C++ Compiler" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.base">
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.compiler.input.1701422539" superClass="cdt.managedbuild.tool.gnu.cpp.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.compiler.base.71677454" name="GCC C Compiler" superClass="cdt.managedbuild.tool.gnu.c.compiler.base">
+ <inputType id="cdt.managedbuild.tool.gnu.c.compiler.input.600103919" superClass="cdt.managedbuild.tool.gnu.c.compiler.input"/>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.c.linker.base.1867869060" name="GCC C Linker" superClass="cdt.managedbuild.tool.gnu.c.linker.base"/>
+ <tool id="cdt.managedbuild.tool.gnu.cpp.linker.base.1385603412" name="GCC C++ Linker" superClass="cdt.managedbuild.tool.gnu.cpp.linker.base">
+ <inputType id="cdt.managedbuild.tool.gnu.cpp.linker.input.1384762464" superClass="cdt.managedbuild.tool.gnu.cpp.linker.input">
+ <additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
+ <additionalInput kind="additionalinput" paths="$(LIBS)"/>
+ </inputType>
+ </tool>
+ <tool id="cdt.managedbuild.tool.gnu.assembler.base.20930498" name="GCC Assembler" superClass="cdt.managedbuild.tool.gnu.assembler.base">
+ <inputType id="cdt.managedbuild.tool.gnu.assembler.input.522304477" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
+ </tool>
+ </toolChain>
+ </folderInfo>
+ </configuration>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.externalSettings"/>
+ </cconfiguration>
+ </storageModule>
+ <storageModule moduleId="cdtBuildSystem" version="4.0.0">
+ <project id="libcoap-4.1.1.null.789466840" name="libcoap-4.1.1"/>
+ </storageModule>
+ <storageModule moduleId="scannerConfiguration">
+ <autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
+ </storageModule>
+ <storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
+ <storageModule moduleId="org.eclipse.cdt.make.core.buildtargets"/>
+</cproject>
--- /dev/null
+2014-02-04 Olaf Bergmann <bergmann@tzi.org>
+
+ * resource.c (coap_print_link): This function now takes an offset
+ where printing starts. This is used for generating blocks on the
+ fly.
+
+ * net.c (wellknown_response): Added support for Block2 options
+ when generating a response for .well-known/core.
+
+ * block.h (coap_opt_block_num): Fixed handling of zero-length
+ options. COAP_OPT_BLOCK_LAST now returns NULL when the option
+ value's length is zero.
+
+2014-01-07 Olaf Bergmann <bergmann@tzi.org>
+
+ * resource.c (coap_print_link): Output partial resource
+ descriptions. The function now provides a sliding window over the
+ textual representation of the resource. Output starts at the given
+ offset and ends at the buffer's upper bound. The meaning of the
+ return value has changed to allow distinguishing whether or not
+ the resource description has been truncated at the buffer's upper
+ bound.
+ (print_wellknown): Support for the new coap_print_link(). An
+ additional parameter now is used to provide the offset into the
+ resource description. The meaning of the return value has been
+ adjusted accordingly.
+
+2013-12-23 Olaf Bergmann <bergmann@tzi.org>
+
+ * configure.in: merged with LWIP port from chrysn
+ <https://git.gitorious.org/coap-lwip/coap-lwip.git>. This
+ introduces new compiler flags WITH_POSIX and WITH_LWIP to
+ distinguish target platforms.
+
+2013-09-03 Olaf Bergmann <bergmann@tzi.org>
+
+ * option.h (coap_option_setb): increased size of option type
+ argument
+
+ * tests/test_error_response.c (t_init_error_response_tests): new
+ tests for error response generation
+
+ * tests/test_pdu.c (t_encode_pdu5): fixed number for option Accept
+
+ * net.c (coap_new_error_response): fixed option size calculation
+
+2013-07-04 Olaf Bergmann <bergmann@tzi.org>
+
+ * net.c (coap_new_context): register critical Accept option
+
+ * pdu.c: option codes for Accept and Size1 according to coap-18
+
+2013-02-01 Olaf Bergmann <bergmann@tzi.org>
+
+ * coap_time.h (coap_clock_init_impl): fix invalid preprocessor
+ directive. #warning is now only used for gcc only (close sf bug #15)
+
+ * net.c (wellknown_response): applied patch from chrysn to
+ fix bug in generation of .well-known/core representation
+
+2013-01-21 Olaf Bergmann <bergmann@tzi.org>
+
+ * option.h: renamed option field in coap_opt_iterator_t to
+ next_option to detect erroneous use in old code
+
+2013-01-18 Olaf Bergmann <bergmann@tzi.org>
+
+ * configure.in: new option --with-tests to enable unit tests
+
+ * tests/testdriver.c: unit tests for parser functions
+
+ * pdu.c (coap_pdu_parse): new PDU parser for Klaus-encoding
+ according to coap-13
+
+ * net.c (coap_read): call coap_pdu_parse() to check PDU integrity
+
+ * option.c: Klaus-encoding for coap-13, including new option
+ iterator interface
+
+2012-11-20 Olaf Bergmann <bergmann@tzi.org>
+
+ * net.c (next_option_safe): made option parsing more robust in
+ presence of option jumps
+
+ * pdu.h: new option codes from draft-ietf-core-coap-12
+
+ * option.c (coap_opt_setlength): new function to set option length
+
+ * uri.c (make_decoded_option): use coap_opt_setlength() instead of
+ obsolete macro COAP_OPT_SETLENGTH.
+
+2012-11-19 Olaf Bergmann <bergmann@tzi.org>
+
+ * uri.c (make_decoded_option): use coap_opt_encode() instead of writing
+
+2012-11-03 Olaf Bergmann <bergmann@tzi.org>
+
+ * net.c (coap_read): read new option encoding
+
+2012-11-01 Olaf Bergmann <bergmann@tzi.org>
+
+ * option.c (coap_opt_size, coap_opt_value, coap_opt_length):
+ several functions to access fields of options (possibly preceeded
+ by option jump)
+
+2012-10-25 Olaf Bergmann <bergmann@tzi.org>
+
+ * option.c (coap_opt_encode): new function for option encoding
+ with option jumps
+
+2012-03-23 Olaf Bergmann <bergmann@tzi.org>
+
+ * examples/client.c (clear_obs): clear observation relationship after
+ user-specified duration
+
+2012-03-21 Olaf Bergmann <bergmann@tzi.org>
+
+ * resource.c (print_wellknown): filtering by attributes
+
+2012-03-19 Olaf Bergmann <bergmann@tzi.org>
+
+ * pdu.c (coap_add_option): allow more than 15 options.
+
+2012-03-15 Olaf Bergmann <bergmann@tzi.org>
+
+ * examples/client.c (cmdline_uri): split path and query here to
+ make it easier to include these options in subsequent requests for
+ block transfer.
+
+2012-03-14 Olaf Bergmann <bergmann@tzi.org>
+
+ * examples/etsi_iot_01.c: Support for POST, PUT, DELETE on /test
+
+2012-03-13 Olaf Bergmann <bergmann@tzi.org>
+
+ * encode.c (coap_encode_var_bytes): more efficient coding for 0
+
+2012-03-11 Olaf Bergmann <bergmann@tzi.org>
+
+ * examples/etsi_iot_01.c: Test cases for 1st ETSI CoAP Plugtest,
+ March 24/25, 2012 in Paris, France.
+
+2012-03-10 Olaf Bergmann <bergmann@tzi.org>
+
+ * block.c: support for block transfer.
+
+2012-03-07 Olaf Bergmann <bergmann@tzi.org>
+
+ * examples/client.c (usage): new command line options
+ -B to set timeout after which the main loop is left.
+ -e to specify a payload (incompatible with -f)
+ (message_handler): bugfixes
+
+ * resource.h: (coap_method_handler_t): new API for method handlers.
+
+
+Copyright 2012 Olaf Bergmann, TZI
+Copying and distribution of this file, with or without modification, are
+permitted provided the copyright notice and this notice are preserved.
--- /dev/null
+Copyright (c) 2010--2011, Olaf Bergmann
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ o Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ o Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
--- /dev/null
+ GNU GENERAL PUBLIC LICENSE
+ Version 2, June 1991
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ Everyone is permitted to copy and distribute verbatim copies
+ of this license document, but changing it is not allowed.
+
+ Preamble
+
+ The licenses for most software are designed to take away your
+freedom to share and change it. By contrast, the GNU General Public
+License is intended to guarantee your freedom to share and change free
+software--to make sure the software is free for all its users. This
+General Public License applies to most of the Free Software
+Foundation's software and to any other program whose authors commit to
+using it. (Some other Free Software Foundation software is covered by
+the GNU Lesser General Public License instead.) You can apply it to
+your programs, too.
+
+ When we speak of free software, we are referring to freedom, not
+price. Our General Public Licenses are designed to make sure that you
+have the freedom to distribute copies of free software (and charge for
+this service if you wish), that you receive source code or can get it
+if you want it, that you can change the software or use pieces of it
+in new free programs; and that you know you can do these things.
+
+ To protect your rights, we need to make restrictions that forbid
+anyone to deny you these rights or to ask you to surrender the rights.
+These restrictions translate to certain responsibilities for you if you
+distribute copies of the software, or if you modify it.
+
+ For example, if you distribute copies of such a program, whether
+gratis or for a fee, you must give the recipients all the rights that
+you have. You must make sure that they, too, receive or can get the
+source code. And you must show them these terms so they know their
+rights.
+
+ We protect your rights with two steps: (1) copyright the software, and
+(2) offer you this license which gives you legal permission to copy,
+distribute and/or modify the software.
+
+ Also, for each author's protection and ours, we want to make certain
+that everyone understands that there is no warranty for this free
+software. If the software is modified by someone else and passed on, we
+want its recipients to know that what they have is not the original, so
+that any problems introduced by others will not reflect on the original
+authors' reputations.
+
+ Finally, any free program is threatened constantly by software
+patents. We wish to avoid the danger that redistributors of a free
+program will individually obtain patent licenses, in effect making the
+program proprietary. To prevent this, we have made it clear that any
+patent must be licensed for everyone's free use or not licensed at all.
+
+ The precise terms and conditions for copying, distribution and
+modification follow.
+
+ GNU GENERAL PUBLIC LICENSE
+ TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+
+ 0. This License applies to any program or other work which contains
+a notice placed by the copyright holder saying it may be distributed
+under the terms of this General Public License. The "Program", below,
+refers to any such program or work, and a "work based on the Program"
+means either the Program or any derivative work under copyright law:
+that is to say, a work containing the Program or a portion of it,
+either verbatim or with modifications and/or translated into another
+language. (Hereinafter, translation is included without limitation in
+the term "modification".) Each licensee is addressed as "you".
+
+Activities other than copying, distribution and modification are not
+covered by this License; they are outside its scope. The act of
+running the Program is not restricted, and the output from the Program
+is covered only if its contents constitute a work based on the
+Program (independent of having been made by running the Program).
+Whether that is true depends on what the Program does.
+
+ 1. You may copy and distribute verbatim copies of the Program's
+source code as you receive it, in any medium, provided that you
+conspicuously and appropriately publish on each copy an appropriate
+copyright notice and disclaimer of warranty; keep intact all the
+notices that refer to this License and to the absence of any warranty;
+and give any other recipients of the Program a copy of this License
+along with the Program.
+
+You may charge a fee for the physical act of transferring a copy, and
+you may at your option offer warranty protection in exchange for a fee.
+
+ 2. You may modify your copy or copies of the Program or any portion
+of it, thus forming a work based on the Program, and copy and
+distribute such modifications or work under the terms of Section 1
+above, provided that you also meet all of these conditions:
+
+ a) You must cause the modified files to carry prominent notices
+ stating that you changed the files and the date of any change.
+
+ b) You must cause any work that you distribute or publish, that in
+ whole or in part contains or is derived from the Program or any
+ part thereof, to be licensed as a whole at no charge to all third
+ parties under the terms of this License.
+
+ c) If the modified program normally reads commands interactively
+ when run, you must cause it, when started running for such
+ interactive use in the most ordinary way, to print or display an
+ announcement including an appropriate copyright notice and a
+ notice that there is no warranty (or else, saying that you provide
+ a warranty) and that users may redistribute the program under
+ these conditions, and telling the user how to view a copy of this
+ License. (Exception: if the Program itself is interactive but
+ does not normally print such an announcement, your work based on
+ the Program is not required to print an announcement.)
+
+These requirements apply to the modified work as a whole. If
+identifiable sections of that work are not derived from the Program,
+and can be reasonably considered independent and separate works in
+themselves, then this License, and its terms, do not apply to those
+sections when you distribute them as separate works. But when you
+distribute the same sections as part of a whole which is a work based
+on the Program, the distribution of the whole must be on the terms of
+this License, whose permissions for other licensees extend to the
+entire whole, and thus to each and every part regardless of who wrote it.
+
+Thus, it is not the intent of this section to claim rights or contest
+your rights to work written entirely by you; rather, the intent is to
+exercise the right to control the distribution of derivative or
+collective works based on the Program.
+
+In addition, mere aggregation of another work not based on the Program
+with the Program (or with a work based on the Program) on a volume of
+a storage or distribution medium does not bring the other work under
+the scope of this License.
+
+ 3. You may copy and distribute the Program (or a work based on it,
+under Section 2) in object code or executable form under the terms of
+Sections 1 and 2 above provided that you also do one of the following:
+
+ a) Accompany it with the complete corresponding machine-readable
+ source code, which must be distributed under the terms of Sections
+ 1 and 2 above on a medium customarily used for software interchange; or,
+
+ b) Accompany it with a written offer, valid for at least three
+ years, to give any third party, for a charge no more than your
+ cost of physically performing source distribution, a complete
+ machine-readable copy of the corresponding source code, to be
+ distributed under the terms of Sections 1 and 2 above on a medium
+ customarily used for software interchange; or,
+
+ c) Accompany it with the information you received as to the offer
+ to distribute corresponding source code. (This alternative is
+ allowed only for noncommercial distribution and only if you
+ received the program in object code or executable form with such
+ an offer, in accord with Subsection b above.)
+
+The source code for a work means the preferred form of the work for
+making modifications to it. For an executable work, complete source
+code means all the source code for all modules it contains, plus any
+associated interface definition files, plus the scripts used to
+control compilation and installation of the executable. However, as a
+special exception, the source code distributed need not include
+anything that is normally distributed (in either source or binary
+form) with the major components (compiler, kernel, and so on) of the
+operating system on which the executable runs, unless that component
+itself accompanies the executable.
+
+If distribution of executable or object code is made by offering
+access to copy from a designated place, then offering equivalent
+access to copy the source code from the same place counts as
+distribution of the source code, even though third parties are not
+compelled to copy the source along with the object code.
+
+ 4. You may not copy, modify, sublicense, or distribute the Program
+except as expressly provided under this License. Any attempt
+otherwise to copy, modify, sublicense or distribute the Program is
+void, and will automatically terminate your rights under this License.
+However, parties who have received copies, or rights, from you under
+this License will not have their licenses terminated so long as such
+parties remain in full compliance.
+
+ 5. You are not required to accept this License, since you have not
+signed it. However, nothing else grants you permission to modify or
+distribute the Program or its derivative works. These actions are
+prohibited by law if you do not accept this License. Therefore, by
+modifying or distributing the Program (or any work based on the
+Program), you indicate your acceptance of this License to do so, and
+all its terms and conditions for copying, distributing or modifying
+the Program or works based on it.
+
+ 6. Each time you redistribute the Program (or any work based on the
+Program), the recipient automatically receives a license from the
+original licensor to copy, distribute or modify the Program subject to
+these terms and conditions. You may not impose any further
+restrictions on the recipients' exercise of the rights granted herein.
+You are not responsible for enforcing compliance by third parties to
+this License.
+
+ 7. If, as a consequence of a court judgment or allegation of patent
+infringement or for any other reason (not limited to patent issues),
+conditions are imposed on you (whether by court order, agreement or
+otherwise) that contradict the conditions of this License, they do not
+excuse you from the conditions of this License. If you cannot
+distribute so as to satisfy simultaneously your obligations under this
+License and any other pertinent obligations, then as a consequence you
+may not distribute the Program at all. For example, if a patent
+license would not permit royalty-free redistribution of the Program by
+all those who receive copies directly or indirectly through you, then
+the only way you could satisfy both it and this License would be to
+refrain entirely from distribution of the Program.
+
+If any portion of this section is held invalid or unenforceable under
+any particular circumstance, the balance of the section is intended to
+apply and the section as a whole is intended to apply in other
+circumstances.
+
+It is not the purpose of this section to induce you to infringe any
+patents or other property right claims or to contest validity of any
+such claims; this section has the sole purpose of protecting the
+integrity of the free software distribution system, which is
+implemented by public license practices. Many people have made
+generous contributions to the wide range of software distributed
+through that system in reliance on consistent application of that
+system; it is up to the author/donor to decide if he or she is willing
+to distribute software through any other system and a licensee cannot
+impose that choice.
+
+This section is intended to make thoroughly clear what is believed to
+be a consequence of the rest of this License.
+
+ 8. If the distribution and/or use of the Program is restricted in
+certain countries either by patents or by copyrighted interfaces, the
+original copyright holder who places the Program under this License
+may add an explicit geographical distribution limitation excluding
+those countries, so that distribution is permitted only in or among
+countries not thus excluded. In such case, this License incorporates
+the limitation as if written in the body of this License.
+
+ 9. The Free Software Foundation may publish revised and/or new versions
+of the General Public License from time to time. Such new versions will
+be similar in spirit to the present version, but may differ in detail to
+address new problems or concerns.
+
+Each version is given a distinguishing version number. If the Program
+specifies a version number of this License which applies to it and "any
+later version", you have the option of following the terms and conditions
+either of that version or of any later version published by the Free
+Software Foundation. If the Program does not specify a version number of
+this License, you may choose any version ever published by the Free Software
+Foundation.
+
+ 10. If you wish to incorporate parts of the Program into other free
+programs whose distribution conditions are different, write to the author
+to ask for permission. For software which is copyrighted by the Free
+Software Foundation, write to the Free Software Foundation; we sometimes
+make exceptions for this. Our decision will be guided by the two goals
+of preserving the free status of all derivatives of our free software and
+of promoting the sharing and reuse of software generally.
+
+ NO WARRANTY
+
+ 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
+REPAIR OR CORRECTION.
+
+ 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
+POSSIBILITY OF SUCH DAMAGES.
+
+ END OF TERMS AND CONDITIONS
--- /dev/null
+#other options are android, arduino
+PLATFORM=linux
+
+ROOT_DIR = ..
+OCSOCK_DIR = $(ROOT_DIR)/ocsocket
+LOGGER_DIR = $(ROOT_DIR)/logger
+RANDOM_DIR = $(ROOT_DIR)/ocrandom
+CJSON_DIR = $(ROOT_DIR)/../../../ccf-utilities/tb/cJSON
+INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include -I$(RANDOM_DIR)/include -I$(CJSON_DIR)
+
+ifeq ($(PLATFORM),android)
+ CCPLUS=arm-linux-androideabi-g++
+ CC=arm-linux-androideabi-gcc
+ AR=arm-linux-androideabi-ar
+ RANLIB=arm-linux-androideabi-ranlib
+ CFLAGS_ANDROID = -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
+ LDFLAGS_ANDROID = -march=armv7-a -Wl,--fix-cortex-a8 -llog
+else ifeq ($(PLATFORM),linux)
+ CCPLUS=g++
+ CC=gcc
+ AR=ar
+ RANLIB=ranlib
+else
+ $(error Wrong value for PLATFORM !!)
+endif
+
+CFLAGS += -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions \
+ -Wextra -Wno-variadic-macros -pedantic -std=gnu99 -DWITH_POSIX -DTB_LOG
+
+SUBDIRS:= examples doc
+
+SOURCES:= pdu.c net.c debug.c encode.c uri.c coap_list.c resource.c hashkey.c \
+ str.c option.c async.c subscribe.c block.c ocsocket.c logger.c \
+ ocrandom.c cJSON.c
+
+OBJECTS:= $(patsubst %.c, %.o, $(SOURCES))
+
+VPATH = $(OCSOCK_DIR)/src:$(LOGGER_DIR)/src:$(RANDOM_DIR)/src:$(CJSON_DIR)
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $(CFLAGS_ANDROID) $(INC_DIRS) $< -o $@
+
+all: libcoap.a
+ $(MAKE) -C examples all
+
+libcoap.a: $(OBJECTS)
+ $(AR) rcs $@ $^
+ $(RANLIB) $@
+
+install: all
+ $(MAKE) -C examples install
+
+doc:
+ $(MAKE) -C doc
+
+.PHONY: clean
+
+clean: $(SUBDIRS)
+ rm -f *.o libcoap.a
+ for dir in $(SUBDIRS); do \
+ $(MAKE) -C $$dir clean ; \
+ done
+
+
--- /dev/null
+# Makefile for libcoap
+#
+# Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
+#
+# This file is part of the CoAP library libcoap. Please see
+# README for terms of use.
+
+# the library's version
+VERSION:=@PACKAGE_VERSION@
+
+# tools
+@SET_MAKE@
+RANLIB=@RANLIB@
+SHELL = /bin/sh
+MKDIR = mkdir
+ETAGS = @ETAGS@
+
+abs_builddir = @abs_builddir@
+top_builddir = @top_builddir@
+package = @PACKAGE_TARNAME@-@PACKAGE_VERSION@
+
+# files and flags
+SOURCES:= pdu.c net.c debug.c encode.c uri.c coap_list.c resource.c hashkey.c \
+ str.c option.c async.c subscribe.c block.c
+OBJECTS:= $(patsubst %.c, %.o, $(SOURCES))
+HEADERS:=coap.h config.h debug.h pdu.h net.h encode.h uri.h coap_list.h mem.h \
+ str.h option.h bits.h uthash.h utlist.h resource.h hashkey.h async.h \
+ subscribe.h block.h address.h prng.h coap_time.h t_list.h
+CFLAGS:=-Wall -Wextra -std=c99 -pedantic @CFLAGS@
+CPPFLAGS:=@CPPFLAGS@
+DISTDIR=$(top_builddir)/$(package)
+SUBDIRS:=examples doc tests
+FILES:=ChangeLog README LICENSE.BSD LICENSE.GPL Makefile.in configure configure.in config.h.in $(SOURCES) $(HEADERS)
+LIB:=libcoap.a
+LDSOFLAGS=-shared
+LDFLAGS:=@LIBS@
+ARFLAGS:=cru
+examples:=examples
+doc:=doc
+@BUILD_SO@
+
+ifdef BUILD_SO
+ MACHINE?=$(shell $(CC) -dumpmachine)
+ ifeq ($(findstring Darwin, $(MACHINE)), Darwin)
+ LDSOFLAGS=-dynamiclib
+ LIBSO=libcoap.dylib
+ endif
+ ifeq ($(findstring Windows, $(MACHINE)), Windows)
+ LIBSO=libcoap.dll
+ endif
+ # more platforms go here
+ ifndef LIBSO
+ LIBSO=libcoap.so
+ endif
+ ifndef PICFLAG
+ CFLAGS+=-fPIC
+ else
+ CFLAGS+=$(PICFLAG)
+ endif
+endif
+
+.PHONY: all dirs clean distclean .gitignore doc TAGS
+
+.SUFFIXES:
+.SUFFIXES: .c .o
+
+all: $(LIB) $(LIBSO) dirs
+
+check:
+ echo DISTDIR: $(DISTDIR)
+ echo top_builddir: $(top_builddir)
+ $(MAKE) -C examples check
+
+dirs: $(SUBDIRS)
+ for dir in $^; do \
+ $(MAKE) -C $$dir ; \
+ done
+
+$(LIB): $(OBJECTS)
+ $(AR) $(ARFLAGS) $@ $^
+ $(RANLIB) $@
+
+$(LIBSO): $(OBJECTS)
+ $(LD) $(LDSOFLAGS) $(LDFLAGS) -o $@ $^
+
+clean:
+ @rm -f $(PROGRAM) main.o $(LIB) $(LIBSO) $(OBJECTS)
+ for dir in $(SUBDIRS); do \
+ $(MAKE) -C $$dir clean ; \
+ done
+
+doc:
+ $(MAKE) -C doc
+
+distclean: clean
+ @rm -rf $(DISTDIR)
+ @rm -f *~ $(DISTDIR).tar.gz
+
+dist: $(FILES) $(SUBDIRS)
+ test -d $(DISTDIR) || mkdir $(DISTDIR)
+ cp $(FILES) $(DISTDIR)
+ for dir in $(SUBDIRS); do \
+ $(MAKE) -C $$dir dist; \
+ done
+ tar czf $(package).tar.gz $(DISTDIR)
+
+TAGS:
+ $(ETAGS) -o $@.new $(SOURCES)
+ $(ETAGS) -a -o $@.new $(HEADERS)
+ mv $@.new $@
+
+.gitignore:
+ echo "core\n*~\n*.[oa]\n*.gz\n*.cap\n$(PROGRAM)\n$(DISTDIR)\n.gitignore" >$@
--- /dev/null
+libcoap: A C implementation of IETF Core Application protocol
+
+Copyright (C) 2010--2013 by Olaf Bergmann <bergmann@tzi.org>
+
+ABOUT LIBCOAP
+
+libcoap is a C implementation of a lightweight application-protocol
+for devices that are constrained their resources such as computing
+power, RF range, memory, bandwith, or network packet sizes. This
+protocol, CoAP, is developed in the IETF working group "Constrained
+RESTful Environments (core)", see <http://6lowapp.net>.
+
+PACKAGE CONTENTS
+
+This directory contains a protocol parser and basic networking
+functions for platform with support for malloc() and BSD-style
+sockets. The examples directory contains a client and a server to
+demonstrate the use of this library.
+
+LICENSE INFORMATION
+
+This library is published as open-source software without any warranty
+of any kind. Use is permitted under the terms of the GNU General
+Public License (GPL), Version 2 or higher, OR the revised BSD
+license. Please refer to LICENSE.GPL oder LICENSE.BSD for further
+details.
+
+BUILD STEPS FOR INTEL OC STACK
+
+Use below command to build libcoap:
+make all PLATFORM=linux
+make all PLATFORM=android
+
--- /dev/null
+/* address.h -- representation of network addresses
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+/**
+ * @file address.h
+ * @brief representation of network addresses
+ */
+
+#ifndef _COAP_ADDRESS_H_
+#define _COAP_ADDRESS_H_
+
+#include "config.h"
+
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#else
+#ifndef assert
+#warning "assertions are disabled"
+# define assert(x)
+#endif
+#endif
+
+#include <string.h>
+#include <stdint.h>
+
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+
+#ifdef HAVE_NETINET_IN_H
+#include <sys/socket.h>
+#endif
+
+#ifdef WITH_LWIP
+#include <lwip/ip_addr.h>
+
+typedef struct coap_address_t {
+ uint16_t port;
+ ip_addr_t addr;
+} coap_address_t;
+
+/* FIXME oversimplification: just assuming it's an ipv4 address instead of
+ * looking up the appropraite lwip function */
+
+#define _coap_address_equals_impl(A, B) ((A)->addr.addr == (B)->addr.addr && A->port == B->port)
+
+/* FIXME sure there is something in lwip */
+
+#define _coap_is_mcast_impl(Address) 0
+
+#endif /* WITH_LWIP */
+#ifdef WITH_CONTIKI
+#include "uip.h"
+
+typedef struct coap_address_t {
+ unsigned char size;
+ uip_ipaddr_t addr;
+ unsigned short port;
+} coap_address_t;
+
+#define _coap_address_equals_impl(A,B) \
+ ((A)->size == (B)->size \
+ && (A)->port == (B)->port \
+ && uip_ipaddr_cmp(&((A)->addr),&((B)->addr)))
+
+#define _coap_is_mcast_impl(Address) uip_is_addr_mcast(&((Address)->addr))
+#endif /* WITH_CONTIKI */
+#ifdef WITH_POSIX
+
+#pragma pack(push, 1)
+/** multi-purpose address abstraction */
+typedef struct coap_address_t {
+ socklen_t size; /**< size of addr */
+ union {
+ struct sockaddr sa;
+ struct sockaddr_storage st;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ } addr;
+} coap_address_t;
+#pragma pack(pop)
+
+static inline int
+_coap_address_equals_impl(const coap_address_t *a,
+ const coap_address_t *b) {
+ if (a->size != b->size || a->addr.sa.sa_family != b->addr.sa.sa_family)
+ return 0;
+
+ /* need to compare only relevant parts of sockaddr_in6 */
+ switch (a->addr.sa.sa_family) {
+ case AF_INET:
+ return
+ a->addr.sin.sin_port == b->addr.sin.sin_port &&
+ memcmp(&a->addr.sin.sin_addr, &b->addr.sin.sin_addr,
+ sizeof(struct in_addr)) == 0;
+ case AF_INET6:
+ return a->addr.sin6.sin6_port == b->addr.sin6.sin6_port &&
+ memcmp(&a->addr.sin6.sin6_addr, &b->addr.sin6.sin6_addr,
+ sizeof(struct in6_addr)) == 0;
+ default: /* fall through and signal error */
+ ;
+ }
+ return 0;
+}
+
+static inline int
+_coap_is_mcast_impl(const coap_address_t *a) {
+ if (!a)
+ return 0;
+
+ switch (a->addr.sa.sa_family) {
+ case AF_INET:
+ return IN_MULTICAST(a->addr.sin.sin_addr.s_addr);
+case AF_INET6:
+ return IN6_IS_ADDR_MULTICAST(&a->addr.sin6.sin6_addr);
+ default: /* fall through and signal error */
+ ;
+ }
+ return 0;
+}
+#endif /* WITH_POSIX */
+
+/**
+ * Resets the given coap_address_t object @p addr to its default
+ * values. In particular, the member size must be initialized to the
+ * available size for storing addresses.
+ *
+ * @param addr The coap_address_t object to initialize.
+ */
+static inline void
+coap_address_init(coap_address_t *addr) {
+ assert(addr);
+ memset(addr, 0, sizeof(coap_address_t));
+#ifndef WITH_LWIP
+ /* lwip has constandt address sizes and doesn't need the .size part */
+ addr->size = sizeof(addr->addr);
+#endif
+}
+
+/**
+ * Compares given address objects @p a and @p b. This function returns
+ * @c 1 if addresses are equal, @c 0 otherwise. The parameters @p a
+ * and @p b must not be @c NULL;
+ */
+static inline int
+coap_address_equals(const coap_address_t *a, const coap_address_t *b) {
+ assert(a); assert(b);
+ return _coap_address_equals_impl(a, b);
+}
+
+/**
+ * Checks if given address @p a denotes a multicast address. This
+ * function returns @c 1 if @p a is multicast, @c 0 otherwise.
+ */
+static inline int
+coap_is_mcast(const coap_address_t *a) {
+ return a && _coap_is_mcast_impl(a);
+}
+
+#endif /* _COAP_ADDRESS_H_ */
--- /dev/null
+/* async.c -- state management for asynchronous messages
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+/**
+ * @file async.c
+ * @brief state management for asynchronous messages
+ */
+
+#ifndef WITHOUT_ASYNC
+
+#include "config.h"
+
+#include "utlist.h"
+
+#include "mem.h"
+#include "debug.h"
+#include "async.h"
+
+coap_async_state_t *
+coap_register_async(coap_context_t *context, coap_address_t *peer,
+ coap_pdu_t *request, unsigned char flags, void *data) {
+ coap_async_state_t *s;
+ coap_tid_t id;
+
+ coap_transaction_id(peer, request, &id);
+ LL_SEARCH_SCALAR(context->async_state,s,id,id);
+
+ if (s != NULL) {
+ /* We must return NULL here as the caller must know that he is
+ * responsible for releasing @p data. */
+ debug("asynchronous state for transaction %d already registered\n", id);
+ return NULL;
+ }
+
+ /* store information for handling the asynchronous task */
+ s = (coap_async_state_t *)coap_malloc(sizeof(coap_async_state_t) +
+ request->hdr->token_length);
+ if (!s) {
+ coap_log(LOG_CRIT, "coap_register_async: insufficient memory\n");
+ return NULL;
+ }
+
+ memset(s, 0, sizeof(coap_async_state_t) + request->hdr->token_length);
+
+ /* set COAP_ASYNC_CONFIRM according to request's type */
+ s->flags = flags & ~COAP_ASYNC_CONFIRM;
+ if (request->hdr->type == COAP_MESSAGE_CON)
+ s->flags |= COAP_ASYNC_CONFIRM;
+
+ s->appdata = data;
+
+ memcpy(&s->peer, peer, sizeof(coap_address_t));
+
+ if (request->hdr->token_length) {
+ s->tokenlen = request->hdr->token_length;
+ memcpy(s->token, request->hdr->token, request->hdr->token_length);
+ }
+
+ memcpy(&s->id, &id, sizeof(coap_tid_t));
+
+ coap_touch_async(s);
+
+ LL_PREPEND(context->async_state, s);
+
+ return s;
+}
+
+coap_async_state_t *
+coap_find_async(coap_context_t *context, coap_tid_t id) {
+ coap_async_state_t *tmp;
+ LL_SEARCH_SCALAR(context->async_state,tmp,id,id);
+ return tmp;
+}
+
+int
+coap_remove_async(coap_context_t *context, coap_tid_t id,
+ coap_async_state_t **s) {
+ coap_async_state_t *tmp = coap_find_async(context, id);
+
+ if (tmp)
+ LL_DELETE(context->async_state,tmp);
+
+ *s = tmp;
+ return tmp != NULL;
+}
+
+void
+coap_free_async(coap_async_state_t *s) {
+ if (s && (s->flags & COAP_ASYNC_RELEASE_DATA) != 0)
+ coap_free(s->appdata);
+ coap_free(s);
+}
+
+#else
+void does_not_exist(); /* make some compilers happy */
+#endif /* WITHOUT_ASYNC */
--- /dev/null
+/* async.h -- state management for asynchronous messages
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+/**
+ * @file async.h
+ * @brief state management for asynchronous messages
+ */
+
+
+#ifndef _COAP_ASYNC_H_
+#define _COAP_ASYNC_H_
+
+#include "config.h"
+#include "net.h"
+
+#ifndef WITHOUT_ASYNC
+
+/**
+ * @defgroup coap_async Asynchronous Messaging
+ * @{
+ * Structure for managing asynchronous state of CoAP resources. A
+ * coap_resource_t object holds a list of coap_async_state_t objects
+ * that can be used to generate a separate response in case a result
+ * of an operation cannot be delivered in time, or the resource has
+ * been explicitly subscribed to with the option @c observe.
+ */
+typedef struct coap_async_state_t {
+ unsigned char flags; /**< holds the flags to control behaviour */
+
+ /**
+ * Holds the internal time when the object was registered with a
+ * resource. This field will be updated whenever
+ * coap_register_async() is called for a specific resource.
+ */
+ coap_tick_t created;
+
+ /**
+ * This field can be used to register opaque application data with
+ * the asynchronous state object. */
+ void *appdata;
+
+ unsigned short message_id; /**< id of last message seen */
+ coap_tid_t id; /**< transaction id */
+
+ struct coap_async_state_t *next; /**< internally used for linking */
+
+ coap_address_t peer; /**< the peer to notify */
+ size_t tokenlen; /**< length of the token */
+#pragma GCC diagnostic ignored "-pedantic"
+ unsigned char token[]; /**< the token to use in a response */
+#pragma GCC diagnostic warning "-pedantic"
+} coap_async_state_t;
+
+/* Definitions for Async Status Flags These flags can be used to
+ * control the behaviour of asynchronous response generation. */
+#define COAP_ASYNC_CONFIRM 0x01 /**< send confirmable response */
+#define COAP_ASYNC_SEPARATE 0x02 /**< send separate response */
+#define COAP_ASYNC_OBSERVED 0x04 /**< the resource is being observed */
+
+/** release application data on destruction */
+#define COAP_ASYNC_RELEASE_DATA 0x08
+
+/**
+ * Allocates a new coap_async_state_t object and fills its fields
+ * according to the given @p request. The @p flags are used to control
+ * generation of empty ACK responses to stop retransmissions and to
+ * release registered @p data when the resource is deleted by
+ * coap_free_async(). This function returns a pointer to the registered
+ * coap_async_t object or @c NULL on error. Note that this function will
+ * return @c NULL in case that an object with the same identifier is
+ * already registered.
+ *
+ * @param context The context to use.
+ * @param peer The remote peer that is to be asynchronously notified.
+ * @param request The request that is handled asynchronously.
+ * @param flags Flags to control state management.
+ * @param data Opaque application data to register. Note that the
+ * storage occupied by @p data is released on destruction
+ * only if flag COAP_ASYNC_RELEASE_DATA is set.
+ *
+ * @return A pointer to the registered coap_async_state_t object or
+ * @c NULL in case of an error.
+ */
+coap_async_state_t *
+coap_register_async(coap_context_t *context, coap_address_t *peer,
+ coap_pdu_t *request, unsigned char flags, void *data);
+
+/**
+ * Removes the state object identified by @p id from @p context. The
+ * removed object is returned in @p s, if found. Otherwise, @p s is
+ * undefined. This function returns @c 1 if the object was removed, @c
+ * 0 otherwise. Note that the storage allocated for the stored object
+ * is not released by this functions. You will have to call
+ * coap_free_async() to do so.
+ *
+ * @param context The context where the async object is registered.
+ * @param id The identifier of the asynchronous transaction.
+ * @param s Will be set to the object identified by @p id
+ * after removal.
+ *
+ * @return @c 1 if object was removed and @p s updated, or @c 0 if no
+ * object was found with the given id. @p s is valid only if the
+ * return value is @c 1.
+ */
+int coap_remove_async(coap_context_t *context, coap_tid_t id,
+ coap_async_state_t **s);
+
+/**
+ * Releases the memory that was allocated by coap_async_state_init()
+ * for the object @p s. The registered application data will be
+ * released automatically if COAP_ASYNC_RELEASE_DATA is set.
+ *
+ * @param s The object to delete.
+ */
+void
+coap_free_async(coap_async_state_t *state);
+
+/**
+ * Retrieves the object identified by @p id from the list of asynchronous
+ * transactions that are registered with @p context. This function returns
+ * a pointer to that object or @c NULL if not found.
+ *
+ * @param context The context where the asynchronous objects are
+ * registered with.
+ * @param id The id of the object to retrieve.
+ *
+ * @return A pointer to the object identified by @p id or @c NULL if
+ * not found.
+ */
+coap_async_state_t *coap_find_async(coap_context_t *context, coap_tid_t id);
+
+/**
+ * Updates the time stamp of @p s.
+ *
+ * @param s The state object to update.
+ */
+static inline void
+coap_touch_async(coap_async_state_t *s) { coap_ticks(&s->created); }
+
+/** @} */
+
+#endif /* WITHOUT_ASYNC */
+
+#endif /* _COAP_ASYNC_H_ */
--- /dev/null
+/*
+ * bits.h -- bit vector manipulation
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+/**
+ * @file bits.h
+ * @brief bit vector manipulation
+ */
+
+#ifndef _BITS_H_
+#define _BITS_H_
+
+#include <sys/types.h>
+#include <stdint.h>
+
+/**
+ * Sets the bit @p bit in bit-vector @p vec. This function returns @c
+ * 1 if bit was set or @c -1 on error (i.e. when the given bit does
+ * not fit in the vector).
+ *
+ * @param vec The bit-vector to change.
+ * @param size The size of @p vec in bytes.
+ * @param bit The bit to set in @p vec.
+ *
+ * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise.
+ */
+inline static int
+bits_setb(uint8_t *vec, size_t size, uint8_t bit) {
+ if (size <= (bit >> 3))
+ return -1;
+
+ *(vec + (bit >> 3)) |= (uint8_t)(1 << (bit & 0x07));
+ return 1;
+}
+
+/**
+ * Clears the bit @p bit from bit-vector @p vec. This function returns
+ * @c 1 if bit was cleared or @c -1 on error (i.e. when the given bit
+ * does not fit in the vector).
+ *
+ * @param vec The bit-vector to change.
+ * @param size The size of @p vec in bytes.
+ * @param bit The bit to clear from @p vec.
+ *
+ * @return @c -1 if @p bit does not fit into @p vec, @c 1 otherwise.
+ */
+inline static int
+bits_clrb(uint8_t *vec, size_t size, uint8_t bit) {
+ if (size <= (bit >> 3))
+ return -1;
+
+ *(vec + (bit >> 3)) &= (uint8_t)(~(1 << (bit & 0x07)));
+ return 1;
+}
+
+/**
+ * Gets the status of bit @p bit from bit-vector @p vec. This function returns
+ * @c 1 if the bit is set, @c 0 otherwise (even in case of an error)..
+ *
+ * @param vec The bit-vector to read from..
+ * @param size The size of @p vec in bytes.
+ * @param bit The bit to get from @p vec.
+ *
+ * @return @c 1 if the bit is set, @c 0 otherwise.
+ */
+inline static int
+bits_getb(const uint8_t *vec, size_t size, uint8_t bit) {
+ if (size <= (bit >> 3))
+ return -1;
+
+ return (*(vec + (bit >> 3)) & (1 << (bit & 0x07))) != 0;
+}
+
+#endif /* _BITS_H_ */
--- /dev/null
+/* block.c -- block transfer
+ *
+ * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "config.h"
+
+#if defined(HAVE_ASSERT_H) && !defined(assert)
+# include <assert.h>
+#endif
+
+#include "debug.h"
+#include "block.h"
+
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+#ifndef WITHOUT_BLOCK
+unsigned int
+coap_opt_block_num(const coap_opt_t *block_opt) {
+ unsigned int num = 0;
+ unsigned short len;
+
+ len = coap_opt_length(block_opt);
+
+ if (len == 0) {
+ return 0;
+ }
+
+ if (len > 1) {
+ num = coap_decode_var_bytes(COAP_OPT_VALUE(block_opt),
+ COAP_OPT_LENGTH(block_opt) - 1);
+ }
+
+ return (num << 4) | ((*COAP_OPT_BLOCK_LAST(block_opt) & 0xF0) >> 4);
+}
+
+int
+coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block) {
+ coap_opt_iterator_t opt_iter;
+ coap_opt_t *option;
+
+ assert(block);
+ memset(block, 0, sizeof(coap_block_t));
+
+ if (pdu && (option = coap_check_option(pdu, type, &opt_iter))) {
+ block->szx = COAP_OPT_BLOCK_SZX(option);
+ if (COAP_OPT_BLOCK_MORE(option))
+ block->m = 1;
+ block->num = coap_opt_block_num(option);
+ return 1;
+ }
+
+ return 0;
+}
+
+int
+coap_write_block_opt(coap_block_t *block, unsigned short type,
+ coap_pdu_t *pdu, size_t data_length) {
+ size_t start, want, avail;
+ unsigned char buf[3];
+
+ assert(pdu);
+
+ /* Block2 */
+ if (type != COAP_OPTION_BLOCK2) {
+ warn("coap_write_block_opt: skipped unknown option\n");
+ return -1;
+ }
+
+ start = block->num << (block->szx + 4);
+ if (data_length <= start) {
+ debug("illegal block requested\n");
+ return -2;
+ }
+
+ avail = pdu->max_size - pdu->length - 4;
+ want = 1 << (block->szx + 4);
+
+ /* check if entire block fits in message */
+ if (want <= avail) {
+ block->m = want < data_length - start;
+ } else {
+ /* Sender has requested a block that is larger than the remaining
+ * space in pdu. This is ok if the remaining data fits into the pdu
+ * anyway. The block size needs to be adjusted only if there is more
+ * data left that cannot be delivered in this message. */
+
+ if (data_length - start <= avail) {
+
+ /* it's the final block and everything fits in the message */
+ block->m = 0;
+ } else {
+ unsigned char szx;
+
+ /* we need to decrease the block size */
+ if (avail < 16) { /* bad luck, this is the smallest block size */
+ debug("not enough space, even the smallest block does not fit");
+ return -3;
+ }
+ debug("decrease block size for %d to %d\n", avail, coap_fls(avail) - 5);
+ szx = block->szx;
+ block->szx = coap_fls(avail) - 5;
+ block->m = 1;
+ block->num <<= szx - block->szx;
+ }
+ }
+
+ /* to re-encode the block option */
+ coap_add_option(pdu, type, coap_encode_var_bytes(buf, ((block->num << 4) |
+ (block->m << 3) |
+ block->szx)),
+ buf);
+
+ return 1;
+}
+
+int
+coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data,
+ unsigned int block_num, unsigned char block_szx) {
+ size_t start;
+ start = block_num << (block_szx + 4);
+
+ if (len <= start)
+ return 0;
+
+ return coap_add_data(pdu,
+ min(len - start, (unsigned int)(1 << (block_szx + 4))),
+ data + start);
+}
+#endif /* WITHOUT_BLOCK */
--- /dev/null
+/* block.h -- block transfer
+ *
+ * Copyright (C) 2010--2012,2014 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef _COAP_BLOCK_H_
+#define _COAP_BLOCK_H_
+
+#include "option.h"
+#include "encode.h"
+#include "pdu.h"
+
+/**
+ * @defgroup block Block Transfer
+ * @{
+ */
+
+#ifndef COAP_MAX_BLOCK_SZX
+/**
+ * The largest value for the SZX component in a Block option. Note
+ * that 1 << (COAP_MAX_BLOCK_SZX + 4) should not exceed
+ * COAP_MAX_PDU_SIZE.
+ */
+#define COAP_MAX_BLOCK_SZX 4
+#endif /* COAP_MAX_BLOCK_SZX */
+
+#if (COAP_MAX_PDU_SIZE - 6) < (1 << (COAP_MAX_BLOCK_SZX + 4))
+#error "COAP_MAX_BLOCK_SZX too large"
+#endif
+
+/**
+ * Structure of Block options.
+ */
+typedef struct {
+ unsigned int num:20; /**< block number */
+ unsigned int m:1; /**< 1 if more blocks follow, 0 otherwise */
+ unsigned int szx:3; /**< block size */
+} coap_block_t;
+
+/**
+ * Returns the value of the least significant byte of a Block option @p opt.
+ * For zero-length options (i.e. num == m == szx == 0), COAP_OPT_BLOCK_LAST
+ * returns @c NULL.
+ */
+#define COAP_OPT_BLOCK_LAST(opt) \
+ (COAP_OPT_LENGTH(opt) ? (COAP_OPT_VALUE(opt) + (COAP_OPT_LENGTH(opt)-1)) : 0)
+
+/** Returns the value of the More-bit of a Block option @p opt. */
+#define COAP_OPT_BLOCK_MORE(opt) \
+ (COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x08) : 0)
+
+/** Returns the value of the SZX-field of a Block option @p opt. */
+#define COAP_OPT_BLOCK_SZX(opt) \
+ (COAP_OPT_LENGTH(opt) ? (*COAP_OPT_BLOCK_LAST(opt) & 0x07) : 0)
+
+/**
+ * Returns the value of field @c num in the given block option @p
+ * block_opt.
+ */
+unsigned int coap_opt_block_num(const coap_opt_t *block_opt);
+
+/**
+ * Checks if more than @p num blocks are required to deliver @p data_len
+ * bytes of data for a block size of 1 << (@p szx + 4).
+ */
+static inline int
+coap_more_blocks(size_t data_len, unsigned int num, unsigned short szx) {
+ return ((num+1) << (szx + 4)) < data_len;
+}
+
+/** Sets the More-bit in @p block_opt */
+static inline void
+coap_opt_block_set_m(coap_opt_t *block_opt, int m) {
+ if (m)
+ *(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) |= 0x08;
+ else
+ *(COAP_OPT_VALUE(block_opt) + (COAP_OPT_LENGTH(block_opt) - 1)) &= ~0x08;
+}
+
+/**
+ * Initializes @p block from @p pdu. @p type must be either COAP_OPTION_BLOCK1
+ * or COAP_OPTION_BLOCK2. When option @p type was found in @p pdu, @p block
+ * is initialized with values from this option and the function returns the
+ * value @c 1. Otherwise, @c 0 is returned.
+ *
+ * @param pdu The pdu to search for option @p type.
+ * @param type The option to search for (must be COAP_OPTION_BLOCK1 or
+ * COAP_OPTION_BLOCK2)
+ * @param block The block structure to initilize.
+ * @return @c 1 on success, @c 0 otherwise.
+ */
+int coap_get_block(coap_pdu_t *pdu, unsigned short type, coap_block_t *block);
+
+/**
+ * Writes a block option of type @p type to message @p pdu. If the
+ * requested block size is too large to fit in @p pdu, it is reduced
+ * accordingly. An exception is made for the final block when less
+ * space is required. The actual length of the resource is specified
+ * in @p data_length.
+ *
+ * This function may change *block to reflect the values written to
+ * @p pdu. As the function takes into consideration the remaining space
+ * @p pdu, no more options should be added after coap_write_block_opt()
+ * has returned.
+ *
+ * @param block The block structure to use. On return, this object
+ * is updated according to the values that have been
+ * written to @p pdu.
+ * @param type COAP_OPTION_BLOCK1 or COAP_OPTION_BLOCK2
+ * @param pdu The message where the block option should be
+ * written.
+ * @param data_length The length of the actual data that will be added
+ * the @p pdu by calling coap_add_block().
+ * @return @c 1 on success, or a negative value on error.
+ */
+int coap_write_block_opt(coap_block_t *block, unsigned short type,
+ coap_pdu_t *pdu, size_t data_length);
+
+/**
+ * Adds the @p block_num block of size 1 << (@p block_szx + 4) from
+ * source @p data to @p pdu.
+ *
+ * @param pdu The message to add the block
+ * @param len The length of @p data.
+ * @param data The source data to fill the block with
+ * @param block_num The actual block number
+ * @param block_szx Encoded size of block @p block_number
+ * @return @c 1 on success, @c 0 otherwise.
+ */
+int coap_add_block(coap_pdu_t *pdu, unsigned int len, const unsigned char *data,
+ unsigned int block_num, unsigned char block_szx);
+/**@}*/
+
+#endif /* _COAP_BLOCK_H_ */
--- /dev/null
+/* coap.h -- main header file for CoAP stack
+ *
+ * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef _COAP_H_
+#define _COAP_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "config.h"
+#include "debug.h"
+#include "mem.h"
+#include "coap_list.h"
+#include "pdu.h"
+#include "option.h"
+#include "net.h"
+#include "encode.h"
+#include "str.h"
+#include "uri.h"
+#include "async.h"
+#include "resource.h"
+#include "subscribe.h"
+#include "block.h"
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _COAP_H_ */
--- /dev/null
+/* coap_list.c -- CoAP list structures
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+
+#include "debug.h"
+#include "mem.h"
+#include "coap_list.h"
+
+int
+coap_insert(coap_list_t **queue, coap_list_t *node,
+ int (*order)(void *, void *node) ) {
+ coap_list_t *p, *q;
+ if ( !queue || !node )
+ return 0;
+
+ /* set queue head if empty */
+ if ( !*queue ) {
+ *queue = node;
+ return 1;
+ }
+
+ /* replace queue head if new node has to be added before the existing queue head */
+ q = *queue;
+ if ( order( node->data, q->data ) < 0) {
+ node->next = q;
+ *queue = node;
+ return 1;
+ }
+
+ /* search for right place to insert */
+ do {
+ p = q;
+ q = q->next;
+ } while ( q && order( node->data, q->data ) >= 0);
+
+ /* insert new item */
+ node->next = q;
+ p->next = node;
+ return 1;
+}
+
+int
+coap_delete(coap_list_t *node) {
+ if ( !node )
+ return 0;
+
+ if ( node->delete_func )
+ node->delete_func( node->data );
+ coap_free( node->data );
+ coap_free( node );
+
+ return 1;
+}
+
+void
+coap_delete_list(coap_list_t *queue) {
+ if ( !queue )
+ return;
+
+ coap_delete_list( queue->next );
+ coap_delete( queue );
+}
+
+coap_list_t *
+coap_new_listnode(void *data, void (*delete_func)(void *) ) {
+ coap_list_t *node = (coap_list_t*)coap_malloc( sizeof(coap_list_t) );
+ if ( ! node ) {
+#ifndef NDEBUG
+ coap_log(LOG_CRIT, "coap_new_listnode: malloc\n");
+#endif
+ return NULL;
+ }
+
+ memset(node, 0, sizeof(coap_list_t));
+ node->data = data;
+ node->delete_func = delete_func;
+ return node;
+}
+
--- /dev/null
+/* coap_list.h -- CoAP list structures
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef _COAP_LIST_H_
+#define _COAP_LIST_H_
+
+struct coap_linkedlistnode {
+ struct coap_linkedlistnode *next;
+ void *data;
+
+ /**
+ * Callback function that is called from coap_delete to release
+ * additional memory allocated by data Set to NULL if you do not
+ * need this. Note that data is free'd automatically. */
+ void (*delete_func)(void *);
+};
+
+typedef struct coap_linkedlistnode coap_list_t;
+
+/**
+ * Adds node to given queue, ordered by specified order function. Returns 1
+ * when insert was successful, 0 otherwise.
+ */
+int coap_insert(coap_list_t **queue, coap_list_t *node,
+ int (*order)(void *, void *) );
+
+/* destroys specified node */
+int coap_delete(coap_list_t *node);
+
+/* removes all items from given queue and frees the allocated storage */
+void coap_delete_list(coap_list_t *queue);
+
+/**
+ * Creates a new list node and adds the given data object. The memory allocated
+ * by data will be released by coap_delete() with the new node. Returns the
+ * new list node.
+ */
+coap_list_t *coap_new_listnode(void *data, void (*delete_func)(void *) );
+
+#endif /* _COAP_LIST_H_ */
--- /dev/null
+/* coap_time.h -- Clock Handling
+ *
+ * Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+/**
+ * @file coap_time.h
+ * @brief Clock Handling
+ */
+
+#ifndef _COAP_TIME_H_
+#define _COAP_TIME_H_
+
+/*
+** Make sure we can call this stuff from C++.
+*/
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+#include "config.h"
+
+/**
+ * @defgroup clock Clock Handling
+ * Default implementation of internal clock. You should redefine this if
+ * you do not have time() and gettimeofday().
+ * @{
+ */
+
+#ifdef WITH_LWIP
+
+#include <stdint.h>
+#include <lwip/sys.h>
+
+/* lwIP provides ms in sys_now */
+#define COAP_TICKS_PER_SECOND 1000
+
+typedef uint32_t coap_tick_t;
+
+static inline void coap_ticks_impl(coap_tick_t *t)
+{
+ *t = sys_now();
+}
+
+static inline void coap_clock_init_impl(void)
+{
+}
+
+#define coap_clock_init coap_clock_init_impl
+
+#define coap_ticks coap_ticks_impl
+
+#endif
+#ifdef WITH_CONTIKI
+#include "clock.h"
+
+typedef clock_time_t coap_tick_t;
+
+/**
+ * This data type is used to represent the difference between two
+ * clock_tick_t values. This data type must have the same size in
+ * memory as coap_tick_t to allow wrapping.
+ */
+typedef int coap_tick_diff_t;
+
+#define COAP_TICKS_PER_SECOND CLOCK_SECOND
+
+/** Set at startup to initialize the internal clock (time in seconds). */
+extern clock_time_t clock_offset;
+
+static inline void
+contiki_clock_init_impl(void) {
+ clock_init();
+ clock_offset = clock_time();
+}
+
+#define coap_clock_init contiki_clock_init_impl
+
+static inline void
+contiki_ticks_impl(coap_tick_t *t) {
+ *t = clock_time();
+}
+
+#define coap_ticks contiki_ticks_impl
+
+#endif /* WITH_CONTIKI */
+#ifdef WITH_POSIX
+typedef unsigned int coap_tick_t;
+
+/**
+ * This data type is used to represent the difference between two
+ * clock_tick_t values. This data type must have the same size in
+ * memory as coap_tick_t to allow wrapping.
+ */
+typedef int coap_tick_diff_t;
+
+#define COAP_TICKS_PER_SECOND 1024
+
+/** Set at startup to initialize the internal clock (time in seconds). */
+extern time_t clock_offset;
+#endif /* WITH_POSIX */
+
+#ifndef coap_clock_init
+static inline void
+coap_clock_init_impl(void) {
+#ifdef HAVE_TIME_H
+ clock_offset = time(NULL);
+#else
+# ifdef __GNUC__
+ /* Issue a warning when using gcc. Other prepropressors do
+ * not seem to have a similar feature. */
+# warning "cannot initialize clock"
+# endif
+ clock_offset = 0;
+#endif
+}
+#define coap_clock_init coap_clock_init_impl
+#endif /* coap_clock_init */
+
+#ifndef coap_ticks
+static inline void
+coap_ticks_impl(coap_tick_t *t) {
+#ifdef HAVE_SYS_TIME_H
+ struct timeval tv;
+ gettimeofday(&tv, NULL);
+ *t = (tv.tv_sec - clock_offset) * COAP_TICKS_PER_SECOND
+ + (tv.tv_usec * COAP_TICKS_PER_SECOND / 1000000);
+#else
+#error "clock not implemented"
+#endif
+}
+#define coap_ticks coap_ticks_impl
+#endif /* coap_ticks */
+
+/**
+ * Returns @c 1 if and only if @p a is less than @p b where less is
+ * defined on a signed data type.
+ */
+static inline
+int coap_time_lt(coap_tick_t a, coap_tick_t b) {
+ return ((coap_tick_diff_t)(a - b)) < 0;
+}
+
+/**
+ * Returns @c 1 if and only if @p a is less than or equal @p b where
+ * less is defined on a signed data type.
+ */
+static inline
+int coap_time_le(coap_tick_t a, coap_tick_t b) {
+ return a == b || coap_time_lt(a,b);
+}
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* _COAP_TIME_H_ */
--- /dev/null
+/* config.h. Generated from config.h.in by configure. */
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+/* #undef AC_APPLE_UNIVERSAL_BUILD */
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#define HAVE_ARPA_INET_H 1
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#define HAVE_GETADDRINFO 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `coap' library (-lcoap). */
+/* #undef HAVE_LIBCOAP */
+
+/* Define to 1 if you have the <limits.h> header file. */
+#define HAVE_LIMITS_H 1
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#define HAVE_MALLOC 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#define HAVE_NETDB_H 1
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#define HAVE_NETINET_IN_H 1
+
+/* Define to 1 if you have the `select' function. */
+#define HAVE_SELECT 1
+
+/* Define to 1 if you have the `socket' function. */
+#define HAVE_SOCKET 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strnlen' function. */
+#define HAVE_STRNLEN 1
+
+/* Define to 1 if you have the `strrchr' function. */
+#define HAVE_STRRCHR 1
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#define HAVE_SYSLOG_H 1
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#define HAVE_SYS_SOCKET_H 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#define HAVE_SYS_TIME_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <sys/unistd.h> header file. */
+#define HAVE_SYS_UNISTD_H 1
+
+/* Define to 1 if you have the <time.h> header file. */
+#define HAVE_TIME_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT ""
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "libcoap"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "libcoap 4.1.1"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "libcoap"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "4.1.1"
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+/* # undef WORDS_BIGENDIAN */
+# endif
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+/* #undef malloc */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to `int' if <sys/types.h> does not define. */
+/* #undef ssize_t */
--- /dev/null
+/* config.h.in. Generated from configure.in by autoheader. */
+
+/* Define if building universal (internal helper macro) */
+#undef AC_APPLE_UNIVERSAL_BUILD
+
+/* Define to 1 if you have the <arpa/inet.h> header file. */
+#undef HAVE_ARPA_INET_H
+
+/* Define to 1 if you have the <assert.h> header file. */
+#undef HAVE_ASSERT_H
+
+/* Define to 1 if you have the `getaddrinfo' function. */
+#undef HAVE_GETADDRINFO
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#undef HAVE_INTTYPES_H
+
+/* Define to 1 if you have the `coap' library (-lcoap). */
+#undef HAVE_LIBCOAP
+
+/* Define to 1 if you have the <limits.h> header file. */
+#undef HAVE_LIMITS_H
+
+/* Define to 1 if your system has a GNU libc compatible `malloc' function, and
+ to 0 otherwise. */
+#undef HAVE_MALLOC
+
+/* Define to 1 if you have the <memory.h> header file. */
+#undef HAVE_MEMORY_H
+
+/* Define to 1 if you have the `memset' function. */
+#undef HAVE_MEMSET
+
+/* Define to 1 if you have the <netdb.h> header file. */
+#undef HAVE_NETDB_H
+
+/* Define to 1 if you have the <netinet/in.h> header file. */
+#undef HAVE_NETINET_IN_H
+
+/* Define to 1 if you have the `select' function. */
+#undef HAVE_SELECT
+
+/* Define to 1 if you have the `socket' function. */
+#undef HAVE_SOCKET
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#undef HAVE_STDINT_H
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#undef HAVE_STDLIB_H
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#undef HAVE_STRCASECMP
+
+/* Define to 1 if you have the <strings.h> header file. */
+#undef HAVE_STRINGS_H
+
+/* Define to 1 if you have the <string.h> header file. */
+#undef HAVE_STRING_H
+
+/* Define to 1 if you have the `strnlen' function. */
+#undef HAVE_STRNLEN
+
+/* Define to 1 if you have the `strrchr' function. */
+#undef HAVE_STRRCHR
+
+/* Define to 1 if you have the <syslog.h> header file. */
+#undef HAVE_SYSLOG_H
+
+/* Define to 1 if you have the <sys/socket.h> header file. */
+#undef HAVE_SYS_SOCKET_H
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#undef HAVE_SYS_STAT_H
+
+/* Define to 1 if you have the <sys/time.h> header file. */
+#undef HAVE_SYS_TIME_H
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#undef HAVE_SYS_TYPES_H
+
+/* Define to 1 if you have the <sys/unistd.h> header file. */
+#undef HAVE_SYS_UNISTD_H
+
+/* Define to 1 if you have the <time.h> header file. */
+#undef HAVE_TIME_H
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#undef HAVE_UNISTD_H
+
+/* Define to the address where bug reports for this package should be sent. */
+#undef PACKAGE_BUGREPORT
+
+/* Define to the full name of this package. */
+#undef PACKAGE_NAME
+
+/* Define to the full name and version of this package. */
+#undef PACKAGE_STRING
+
+/* Define to the one symbol short name of this package. */
+#undef PACKAGE_TARNAME
+
+/* Define to the home page for this package. */
+#undef PACKAGE_URL
+
+/* Define to the version of this package. */
+#undef PACKAGE_VERSION
+
+/* Define to 1 if you have the ANSI C header files. */
+#undef STDC_HEADERS
+
+/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
+ significant byte first (like Motorola and SPARC, unlike Intel). */
+#if defined AC_APPLE_UNIVERSAL_BUILD
+# if defined __BIG_ENDIAN__
+# define WORDS_BIGENDIAN 1
+# endif
+#else
+# ifndef WORDS_BIGENDIAN
+# undef WORDS_BIGENDIAN
+# endif
+#endif
+
+/* Define to rpl_malloc if the replacement function should be used. */
+#undef malloc
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+#undef size_t
+
+/* Define to `int' if <sys/types.h> does not define. */
+#undef ssize_t
--- /dev/null
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by libcoap configure 4.1.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ ./configure --host=avr CC=avr-gcc C_EXTRA_FLAGS=-mmcu=atmega2560 -DATMEGA2560
+
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = precious
+uname -m = x86_64
+uname -r = 3.8.0-37-generic
+uname -s = Linux
+uname -v = #53~precise1-Ubuntu SMP Wed Feb 19 21:37:54 UTC 2014
+
+/usr/bin/uname -p = unknown
+/bin/uname -X = unknown
+
+/bin/arch = unknown
+/usr/bin/arch -k = unknown
+/usr/convex/getsysinfo = unknown
+/usr/bin/hostinfo = unknown
+/bin/machine = unknown
+/usr/bin/oslevel = unknown
+/bin/universe = unknown
+
+PATH: /tmp/automake/home/sachin/jdk1.7.0_51/bin
+PATH: /usr/lib/lightdm/lightdm
+PATH: /usr/local/sbin
+PATH: /usr/local/bin
+PATH: /usr/sbin
+PATH: /usr/bin
+PATH: /sbin
+PATH: /bin
+PATH: /usr/games
+PATH: /home/sachin/android/adt-bundle-linux-x86_64-20131030/sdk/tools
+PATH: /home/sachin/android/adt-bundle-linux-x86_64-20131030/sdk/platform-tools
+PATH: /var/tmp/android-14/bin
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+configure:2175: checking whether make sets $(MAKE)
+configure:2197: result: yes
+configure:2214: checking for avr-gcc
+configure:2241: result: avr-gcc
+configure:2510: checking for C compiler version
+configure:2519: avr-gcc --version >&5
+avr-gcc (GCC) 4.5.3
+Copyright (C) 2010 Free Software Foundation, Inc.
+This is free software; see the source for copying conditions. There is NO
+warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+configure:2530: $? = 0
+configure:2519: avr-gcc -v >&5
+Using built-in specs.
+COLLECT_GCC=avr-gcc
+COLLECT_LTO_WRAPPER=/usr/lib/gcc/avr/4.5.3/lto-wrapper
+Target: avr
+Configured with: ../src/configure -v --enable-languages=c,c++ --prefix=/usr/lib --infodir=/usr/share/info --mandir=/usr/share/man --bindir=/usr/bin --libexecdir=/usr/lib --libdir=/usr/lib --enable-shared --with-system-zlib --enable-long-long --enable-nls --without-included-gettext --disable-libssp --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=avr
+Thread model: single
+gcc version 4.5.3 (GCC)
+configure:2530: $? = 0
+configure:2519: avr-gcc -V >&5
+avr-gcc: '-V' option must have argument
+configure:2530: $? = 1
+configure:2519: avr-gcc -qversion >&5
+avr-gcc: unrecognized option '-qversion'
+avr-gcc: no input files
+configure:2530: $? = 1
+configure:2550: checking whether the C compiler works
+configure:2572: avr-gcc conftest.c >&5
+configure:2576: $? = 0
+configure:2624: result: yes
+configure:2627: checking for C compiler default output file name
+configure:2629: result: a.out
+configure:2635: checking for suffix of executables
+configure:2642: avr-gcc -o conftest conftest.c >&5
+configure:2646: $? = 0
+configure:2668: result:
+configure:2690: checking whether we are cross compiling
+configure:2698: avr-gcc -o conftest conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:13:11: warning: initialization makes pointer from integer without a cast
+/tmp/ccBLEQG0.o: In function `main':
+conftest.c:(.text+0x16): undefined reference to `fopen'
+/usr/lib/gcc/avr/4.5.3/../../../avr/lib/libc.a(malloc.o): In function `malloc':
+/build/buildd/avr-libc-1.7.1/avr/lib/avr2/../../../libc/stdlib/malloc.c:80: undefined reference to `__heap_end'
+collect2: ld returned 1 exit status
+configure:2702: $? = 1
+configure:2709: ./conftest
+./configure: line 2711: ./conftest: No such file or directory
+configure:2713: $? = 127
+configure:2728: result: yes
+configure:2733: checking for suffix of object files
+configure:2755: avr-gcc -c conftest.c >&5
+configure:2759: $? = 0
+configure:2780: result: o
+configure:2784: checking whether we are using the GNU C compiler
+configure:2803: avr-gcc -c conftest.c >&5
+configure:2803: $? = 0
+configure:2812: result: yes
+configure:2821: checking whether avr-gcc accepts -g
+configure:2841: avr-gcc -c -g conftest.c >&5
+configure:2841: $? = 0
+configure:2882: result: yes
+configure:2899: checking for avr-gcc option to accept ISO C89
+configure:2962: avr-gcc -c -g -O2 conftest.c >&5
+configure:2962: $? = 0
+configure:2975: result: none needed
+configure:2998: checking for avr-ranlib
+configure:3014: found /usr/bin/avr-ranlib
+configure:3025: result: avr-ranlib
+configure:3089: checking for doxygen
+configure:3107: found /usr/bin/doxygen
+configure:3120: result: /usr/bin/doxygen
+configure:3130: checking for etags
+configure:3161: result: /bin/false
+configure:3176: checking how to run the C preprocessor
+configure:3207: avr-gcc -E conftest.c
+configure:3207: $? = 0
+configure:3221: avr-gcc -E conftest.c
+conftest.c:9:28: fatal error: ac_nonexistent.h: No such file or directory
+compilation terminated.
+configure:3221: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| /* end confdefs.h. */
+| #include <ac_nonexistent.h>
+configure:3246: result: avr-gcc -E
+configure:3266: avr-gcc -E conftest.c
+configure:3266: $? = 0
+configure:3280: avr-gcc -E conftest.c
+conftest.c:9:28: fatal error: ac_nonexistent.h: No such file or directory
+compilation terminated.
+configure:3280: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| /* end confdefs.h. */
+| #include <ac_nonexistent.h>
+configure:3309: checking for grep that handles long lines and -e
+configure:3367: result: /bin/grep
+configure:3372: checking for egrep
+configure:3434: result: /bin/grep -E
+configure:3439: checking for ANSI C header files
+configure:3459: avr-gcc -c -g -O2 conftest.c >&5
+configure:3459: $? = 0
+configure:3543: result: yes
+configure:3556: checking for sys/types.h
+configure:3556: avr-gcc -c -g -O2 conftest.c >&5
+conftest.c:44:23: fatal error: sys/types.h: No such file or directory
+compilation terminated.
+configure:3556: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+|
+| #include <sys/types.h>
+configure:3556: result: no
+configure:3556: checking for sys/stat.h
+configure:3556: avr-gcc -c -g -O2 conftest.c >&5
+conftest.c:44:22: fatal error: sys/stat.h: No such file or directory
+compilation terminated.
+configure:3556: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+|
+| #include <sys/stat.h>
+configure:3556: result: no
+configure:3556: checking for stdlib.h
+configure:3556: avr-gcc -c -g -O2 conftest.c >&5
+configure:3556: $? = 0
+configure:3556: result: yes
+configure:3556: checking for string.h
+configure:3556: avr-gcc -c -g -O2 conftest.c >&5
+configure:3556: $? = 0
+configure:3556: result: yes
+configure:3556: checking for memory.h
+configure:3556: avr-gcc -c -g -O2 conftest.c >&5
+conftest.c:46:20: fatal error: memory.h: No such file or directory
+compilation terminated.
+configure:3556: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+|
+| #include <memory.h>
+configure:3556: result: no
+configure:3556: checking for strings.h
+configure:3556: avr-gcc -c -g -O2 conftest.c >&5
+conftest.c:46:21: fatal error: strings.h: No such file or directory
+compilation terminated.
+configure:3556: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+|
+| #include <strings.h>
+configure:3556: result: no
+configure:3556: checking for inttypes.h
+configure:3556: avr-gcc -c -g -O2 conftest.c >&5
+configure:3556: $? = 0
+configure:3556: result: yes
+configure:3556: checking for stdint.h
+configure:3556: avr-gcc -c -g -O2 conftest.c >&5
+configure:3556: $? = 0
+configure:3556: result: yes
+configure:3556: checking for unistd.h
+configure:3556: avr-gcc -c -g -O2 conftest.c >&5
+conftest.c:48:20: fatal error: unistd.h: No such file or directory
+compilation terminated.
+configure:3556: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+|
+| #include <unistd.h>
+configure:3556: result: no
+configure:3568: checking whether byte ordering is bigendian
+configure:3583: avr-gcc -c -g -O2 conftest.c >&5
+conftest.c:15:13: error: expected '=', ',', ';', 'asm' or '__attribute__' before 'a'
+configure:3583: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| /* end confdefs.h. */
+| #ifndef __APPLE_CC__
+| not a universal capable compiler
+| #endif
+| typedef int dummy;
+|
+configure:3628: avr-gcc -c -g -O2 conftest.c >&5
+conftest.c:14:23: fatal error: sys/types.h: No such file or directory
+compilation terminated.
+configure:3628: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| /* end confdefs.h. */
+| #include <sys/types.h>
+| #include <sys/param.h>
+|
+| int
+| main ()
+| {
+| #if ! (defined BYTE_ORDER && defined BIG_ENDIAN && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN && LITTLE_ENDIAN)
+| bogus endian macros
+| #endif
+|
+| ;
+| return 0;
+| }
+configure:3672: avr-gcc -c -g -O2 conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:20:8: error: 'bogus' undeclared (first use in this function)
+conftest.c:20:8: note: each undeclared identifier is reported only once for each function it appears in
+conftest.c:20:14: error: expected ';' before 'endian'
+configure:3672: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| /* end confdefs.h. */
+| #include <limits.h>
+|
+| int
+| main ()
+| {
+| #if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+| bogus endian macros
+| #endif
+|
+| ;
+| return 0;
+| }
+configure:3728: avr-gcc -c -g -O2 conftest.c >&5
+configure:3728: $? = 0
+configure:3774: result: no
+configure:3794: checking for coap_new_pdu in -lcoap
+configure:3819: avr-gcc -o conftest -g -O2 conftest.c -lcoap >&5
+/usr/lib/gcc/avr/4.5.3/../../../avr/bin/ld: cannot find -lcoap
+collect2: ld returned 1 exit status
+configure:3819: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| /* end confdefs.h. */
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char coap_new_pdu ();
+| int
+| main ()
+| {
+| return coap_new_pdu ();
+| ;
+| return 0;
+| }
+configure:3828: result: no
+configure:3840: checking for library containing gethostbyname
+configure:3871: avr-gcc -o conftest -g -O2 conftest.c >&5
+/tmp/cc5dRuvo.o: In function `main':
+/home/sachin/gitrepos/peg_ccfl-core/libcoap-4.1.1/conftest.c:25: undefined reference to `gethostbyname'
+collect2: ld returned 1 exit status
+configure:3871: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| /* end confdefs.h. */
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char gethostbyname ();
+| int
+| main ()
+| {
+| return gethostbyname ();
+| ;
+| return 0;
+| }
+configure:3871: avr-gcc -o conftest -g -O2 conftest.c -lnsl >&5
+/usr/lib/gcc/avr/4.5.3/../../../avr/bin/ld: cannot find -lnsl
+collect2: ld returned 1 exit status
+configure:3871: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| /* end confdefs.h. */
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char gethostbyname ();
+| int
+| main ()
+| {
+| return gethostbyname ();
+| ;
+| return 0;
+| }
+configure:3888: result: no
+configure:3896: checking for library containing socket
+configure:3927: avr-gcc -o conftest -g -O2 conftest.c >&5
+/tmp/cczRzsqr.o: In function `main':
+/home/sachin/gitrepos/peg_ccfl-core/libcoap-4.1.1/conftest.c:25: undefined reference to `socket'
+collect2: ld returned 1 exit status
+configure:3927: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| /* end confdefs.h. */
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char socket ();
+| int
+| main ()
+| {
+| return socket ();
+| ;
+| return 0;
+| }
+configure:3927: avr-gcc -o conftest -g -O2 conftest.c -lsocket >&5
+/usr/lib/gcc/avr/4.5.3/../../../avr/bin/ld: cannot find -lsocket
+collect2: ld returned 1 exit status
+configure:3927: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| /* end confdefs.h. */
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char socket ();
+| int
+| main ()
+| {
+| return socket ();
+| ;
+| return 0;
+| }
+configure:3944: result: no
+configure:4011: checking assert.h usability
+configure:4011: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+configure:4011: $? = 0
+configure:4011: result: yes
+configure:4011: checking assert.h presence
+configure:4011: avr-gcc -E -DWITH_POSIX conftest.c
+configure:4011: $? = 0
+configure:4011: result: yes
+configure:4011: checking for assert.h
+configure:4011: result: yes
+configure:4011: checking arpa/inet.h usability
+configure:4011: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:48:23: fatal error: arpa/inet.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <arpa/inet.h>
+configure:4011: result: no
+configure:4011: checking arpa/inet.h presence
+configure:4011: avr-gcc -E -DWITH_POSIX conftest.c
+conftest.c:15:23: fatal error: arpa/inet.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| /* end confdefs.h. */
+| #include <arpa/inet.h>
+configure:4011: result: no
+configure:4011: checking for arpa/inet.h
+configure:4011: result: no
+configure:4011: checking limits.h usability
+configure:4011: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+configure:4011: $? = 0
+configure:4011: result: yes
+configure:4011: checking limits.h presence
+configure:4011: avr-gcc -E -DWITH_POSIX conftest.c
+configure:4011: $? = 0
+configure:4011: result: yes
+configure:4011: checking for limits.h
+configure:4011: result: yes
+configure:4011: checking netdb.h usability
+configure:4011: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:49:19: fatal error: netdb.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <netdb.h>
+configure:4011: result: no
+configure:4011: checking netdb.h presence
+configure:4011: avr-gcc -E -DWITH_POSIX conftest.c
+conftest.c:16:19: fatal error: netdb.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| /* end confdefs.h. */
+| #include <netdb.h>
+configure:4011: result: no
+configure:4011: checking for netdb.h
+configure:4011: result: no
+configure:4011: checking netinet/in.h usability
+configure:4011: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:49:24: fatal error: netinet/in.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <netinet/in.h>
+configure:4011: result: no
+configure:4011: checking netinet/in.h presence
+configure:4011: avr-gcc -E -DWITH_POSIX conftest.c
+conftest.c:16:24: fatal error: netinet/in.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| /* end confdefs.h. */
+| #include <netinet/in.h>
+configure:4011: result: no
+configure:4011: checking for netinet/in.h
+configure:4011: result: no
+configure:4011: checking for stdlib.h
+configure:4011: result: yes
+configure:4011: checking for string.h
+configure:4011: result: yes
+configure:4011: checking for strings.h
+configure:4011: result: no
+configure:4011: checking sys/socket.h usability
+configure:4011: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:51:24: fatal error: sys/socket.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/socket.h>
+configure:4011: result: no
+configure:4011: checking sys/socket.h presence
+configure:4011: avr-gcc -E -DWITH_POSIX conftest.c
+conftest.c:18:24: fatal error: sys/socket.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <sys/socket.h>
+configure:4011: result: no
+configure:4011: checking for sys/socket.h
+configure:4011: result: no
+configure:4011: checking sys/time.h usability
+configure:4011: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:51:22: fatal error: sys/time.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/time.h>
+configure:4011: result: no
+configure:4011: checking sys/time.h presence
+configure:4011: avr-gcc -E -DWITH_POSIX conftest.c
+conftest.c:18:22: fatal error: sys/time.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <sys/time.h>
+configure:4011: result: no
+configure:4011: checking for sys/time.h
+configure:4011: result: no
+configure:4011: checking time.h usability
+configure:4011: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:51:18: fatal error: time.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <time.h>
+configure:4011: result: no
+configure:4011: checking time.h presence
+configure:4011: avr-gcc -E -DWITH_POSIX conftest.c
+conftest.c:18:18: fatal error: time.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <time.h>
+configure:4011: result: no
+configure:4011: checking for time.h
+configure:4011: result: no
+configure:4011: checking for unistd.h
+configure:4011: result: no
+configure:4011: checking sys/unistd.h usability
+configure:4011: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:51:24: fatal error: sys/unistd.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <sys/unistd.h>
+configure:4011: result: no
+configure:4011: checking sys/unistd.h presence
+configure:4011: avr-gcc -E -DWITH_POSIX conftest.c
+conftest.c:18:24: fatal error: sys/unistd.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <sys/unistd.h>
+configure:4011: result: no
+configure:4011: checking for sys/unistd.h
+configure:4011: result: no
+configure:4011: checking syslog.h usability
+configure:4011: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:51:20: fatal error: syslog.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| #include <syslog.h>
+configure:4011: result: no
+configure:4011: checking syslog.h presence
+configure:4011: avr-gcc -E -DWITH_POSIX conftest.c
+conftest.c:18:20: fatal error: syslog.h: No such file or directory
+compilation terminated.
+configure:4011: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <syslog.h>
+configure:4011: result: no
+configure:4011: checking for syslog.h
+configure:4011: result: no
+configure:4023: checking for size_t
+configure:4023: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+configure:4023: $? = 0
+configure:4023: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:54:21: error: expected expression before ')' token
+configure:4023: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| if (sizeof ((size_t)))
+| return 0;
+| ;
+| return 0;
+| }
+configure:4023: result: yes
+configure:4034: checking for ssize_t
+configure:4034: avr-gcc -c -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c: In function 'main':
+conftest.c:54:13: error: 'ssize_t' undeclared (first use in this function)
+conftest.c:54:13: note: each undeclared identifier is reported only once for each function it appears in
+configure:4034: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| /* end confdefs.h. */
+| #include <stdio.h>
+| #ifdef HAVE_SYS_TYPES_H
+| # include <sys/types.h>
+| #endif
+| #ifdef HAVE_SYS_STAT_H
+| # include <sys/stat.h>
+| #endif
+| #ifdef STDC_HEADERS
+| # include <stdlib.h>
+| # include <stddef.h>
+| #else
+| # ifdef HAVE_STDLIB_H
+| # include <stdlib.h>
+| # endif
+| #endif
+| #ifdef HAVE_STRING_H
+| # if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+| # include <memory.h>
+| # endif
+| # include <string.h>
+| #endif
+| #ifdef HAVE_STRINGS_H
+| # include <strings.h>
+| #endif
+| #ifdef HAVE_INTTYPES_H
+| # include <inttypes.h>
+| #endif
+| #ifdef HAVE_STDINT_H
+| # include <stdint.h>
+| #endif
+| #ifdef HAVE_UNISTD_H
+| # include <unistd.h>
+| #endif
+| int
+| main ()
+| {
+| if (sizeof (ssize_t))
+| return 0;
+| ;
+| return 0;
+| }
+configure:4034: result: no
+configure:4049: checking for stdlib.h
+configure:4049: result: yes
+configure:4059: checking for GNU libc compatible malloc
+configure:4093: result: no
+configure:4117: checking for memset
+configure:4117: avr-gcc -o conftest -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:45:6: warning: conflicting types for built-in function 'memset'
+configure:4117: $? = 0
+configure:4117: result: yes
+configure:4117: checking for select
+configure:4117: avr-gcc -o conftest -g -O2 -DWITH_POSIX conftest.c >&5
+/tmp/ccgkOSk6.o: In function `main':
+/home/sachin/gitrepos/peg_ccfl-core/libcoap-4.1.1/conftest.c:57: undefined reference to `select'
+collect2: ld returned 1 exit status
+configure:4117: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define ssize_t int
+| #define HAVE_STDLIB_H 1
+| #define HAVE_MALLOC 0
+| #define malloc rpl_malloc
+| #define HAVE_MEMSET 1
+| /* end confdefs.h. */
+| /* Define select to an innocuous variant, in case <limits.h> declares select.
+| For example, HP-UX 11i <limits.h> declares gettimeofday. */
+| #define select innocuous_select
+|
+| /* System header to define __stub macros and hopefully few prototypes,
+| which can conflict with char select (); below.
+| Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+| <limits.h> exists even on freestanding compilers. */
+|
+| #ifdef __STDC__
+| # include <limits.h>
+| #else
+| # include <assert.h>
+| #endif
+|
+| #undef select
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char select ();
+| /* The GNU C library defines this for functions which it implements
+| to always fail with ENOSYS. Some functions are actually named
+| something starting with __ and the normal name is an alias. */
+| #if defined __stub_select || defined __stub___select
+| choke me
+| #endif
+|
+| int
+| main ()
+| {
+| return select ();
+| ;
+| return 0;
+| }
+configure:4117: result: no
+configure:4117: checking for socket
+configure:4117: avr-gcc -o conftest -g -O2 -DWITH_POSIX conftest.c >&5
+/tmp/ccZCmbb9.o: In function `main':
+/home/sachin/gitrepos/peg_ccfl-core/libcoap-4.1.1/conftest.c:57: undefined reference to `socket'
+collect2: ld returned 1 exit status
+configure:4117: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define ssize_t int
+| #define HAVE_STDLIB_H 1
+| #define HAVE_MALLOC 0
+| #define malloc rpl_malloc
+| #define HAVE_MEMSET 1
+| /* end confdefs.h. */
+| /* Define socket to an innocuous variant, in case <limits.h> declares socket.
+| For example, HP-UX 11i <limits.h> declares gettimeofday. */
+| #define socket innocuous_socket
+|
+| /* System header to define __stub macros and hopefully few prototypes,
+| which can conflict with char socket (); below.
+| Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+| <limits.h> exists even on freestanding compilers. */
+|
+| #ifdef __STDC__
+| # include <limits.h>
+| #else
+| # include <assert.h>
+| #endif
+|
+| #undef socket
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char socket ();
+| /* The GNU C library defines this for functions which it implements
+| to always fail with ENOSYS. Some functions are actually named
+| something starting with __ and the normal name is an alias. */
+| #if defined __stub_socket || defined __stub___socket
+| choke me
+| #endif
+|
+| int
+| main ()
+| {
+| return socket ();
+| ;
+| return 0;
+| }
+configure:4117: result: no
+configure:4117: checking for strcasecmp
+configure:4117: avr-gcc -o conftest -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:46:6: warning: conflicting types for built-in function 'strcasecmp'
+configure:4117: $? = 0
+configure:4117: result: yes
+configure:4117: checking for strrchr
+configure:4117: avr-gcc -o conftest -g -O2 -DWITH_POSIX conftest.c >&5
+conftest.c:47:6: warning: conflicting types for built-in function 'strrchr'
+configure:4117: $? = 0
+configure:4117: result: yes
+configure:4117: checking for getaddrinfo
+configure:4117: avr-gcc -o conftest -g -O2 -DWITH_POSIX conftest.c >&5
+/tmp/cca8ULN8.o: In function `main':
+/home/sachin/gitrepos/peg_ccfl-core/libcoap-4.1.1/conftest.c:59: undefined reference to `getaddrinfo'
+collect2: ld returned 1 exit status
+configure:4117: $? = 1
+configure: failed program was:
+| /* confdefs.h */
+| #define PACKAGE_NAME "libcoap"
+| #define PACKAGE_TARNAME "libcoap"
+| #define PACKAGE_VERSION "4.1.1"
+| #define PACKAGE_STRING "libcoap 4.1.1"
+| #define PACKAGE_BUGREPORT ""
+| #define PACKAGE_URL ""
+| #define STDC_HEADERS 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define HAVE_INTTYPES_H 1
+| #define HAVE_STDINT_H 1
+| #define HAVE_ASSERT_H 1
+| #define HAVE_LIMITS_H 1
+| #define HAVE_STDLIB_H 1
+| #define HAVE_STRING_H 1
+| #define ssize_t int
+| #define HAVE_STDLIB_H 1
+| #define HAVE_MALLOC 0
+| #define malloc rpl_malloc
+| #define HAVE_MEMSET 1
+| #define HAVE_STRCASECMP 1
+| #define HAVE_STRRCHR 1
+| /* end confdefs.h. */
+| /* Define getaddrinfo to an innocuous variant, in case <limits.h> declares getaddrinfo.
+| For example, HP-UX 11i <limits.h> declares gettimeofday. */
+| #define getaddrinfo innocuous_getaddrinfo
+|
+| /* System header to define __stub macros and hopefully few prototypes,
+| which can conflict with char getaddrinfo (); below.
+| Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+| <limits.h> exists even on freestanding compilers. */
+|
+| #ifdef __STDC__
+| # include <limits.h>
+| #else
+| # include <assert.h>
+| #endif
+|
+| #undef getaddrinfo
+|
+| /* Override any GCC internal prototype to avoid an error.
+| Use char because int might match the return type of a GCC
+| builtin and then its argument prototype would still apply. */
+| #ifdef __cplusplus
+| extern "C"
+| #endif
+| char getaddrinfo ();
+| /* The GNU C library defines this for functions which it implements
+| to always fail with ENOSYS. Some functions are actually named
+| something starting with __ and the normal name is an alias. */
+| #if defined __stub_getaddrinfo || defined __stub___getaddrinfo
+| choke me
+| #endif
+|
+| int
+| main ()
+| {
+| return getaddrinfo ();
+| ;
+| return 0;
+| }
+configure:4117: result: no
+configure:4117: checking for strnlen
+configure:4117: avr-gcc -o conftest -g -O2 -DWITH_POSIX conftest.c >&5
+configure:4117: $? = 0
+configure:4117: result: yes
+configure:4250: creating ./config.status
+
+## ---------------------- ##
+## Running config.status. ##
+## ---------------------- ##
+
+This file was extended by libcoap config.status 4.1.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES =
+ CONFIG_HEADERS =
+ CONFIG_LINKS =
+ CONFIG_COMMANDS =
+ $ ./config.status
+
+on precious
+
+config.status:814: creating Makefile
+config.status:814: creating doc/Makefile
+config.status:814: creating doc/Doxyfile
+config.status:800: error: cannot find input file: `examples/Makefile.in'
+
+## ---------------- ##
+## Cache variables. ##
+## ---------------- ##
+
+ac_cv_c_bigendian=no
+ac_cv_c_compiler_gnu=yes
+ac_cv_env_CC_set=set
+ac_cv_env_CC_value=avr-gcc
+ac_cv_env_CFLAGS_set=
+ac_cv_env_CFLAGS_value=
+ac_cv_env_CPPFLAGS_set=
+ac_cv_env_CPPFLAGS_value=
+ac_cv_env_CPP_set=
+ac_cv_env_CPP_value=
+ac_cv_env_LDFLAGS_set=
+ac_cv_env_LDFLAGS_value=
+ac_cv_env_LIBS_set=
+ac_cv_env_LIBS_value=
+ac_cv_env_build_alias_set=
+ac_cv_env_build_alias_value=
+ac_cv_env_host_alias_set=set
+ac_cv_env_host_alias_value=avr
+ac_cv_env_target_alias_set=
+ac_cv_env_target_alias_value=
+ac_cv_func_getaddrinfo=no
+ac_cv_func_malloc_0_nonnull=no
+ac_cv_func_memset=yes
+ac_cv_func_select=no
+ac_cv_func_socket=no
+ac_cv_func_strcasecmp=yes
+ac_cv_func_strnlen=yes
+ac_cv_func_strrchr=yes
+ac_cv_header_arpa_inet_h=no
+ac_cv_header_assert_h=yes
+ac_cv_header_inttypes_h=yes
+ac_cv_header_limits_h=yes
+ac_cv_header_memory_h=no
+ac_cv_header_netdb_h=no
+ac_cv_header_netinet_in_h=no
+ac_cv_header_stdc=yes
+ac_cv_header_stdint_h=yes
+ac_cv_header_stdlib_h=yes
+ac_cv_header_string_h=yes
+ac_cv_header_strings_h=no
+ac_cv_header_sys_socket_h=no
+ac_cv_header_sys_stat_h=no
+ac_cv_header_sys_time_h=no
+ac_cv_header_sys_types_h=no
+ac_cv_header_sys_unistd_h=no
+ac_cv_header_syslog_h=no
+ac_cv_header_time_h=no
+ac_cv_header_unistd_h=no
+ac_cv_lib_coap_coap_new_pdu=no
+ac_cv_objext=o
+ac_cv_path_DOXYGEN=/usr/bin/doxygen
+ac_cv_path_EGREP='/bin/grep -E'
+ac_cv_path_ETAGS=/bin/false
+ac_cv_path_GREP=/bin/grep
+ac_cv_prog_CC=avr-gcc
+ac_cv_prog_CPP='avr-gcc -E'
+ac_cv_prog_RANLIB=avr-ranlib
+ac_cv_prog_cc_c89=
+ac_cv_prog_cc_g=yes
+ac_cv_prog_make_make_set=yes
+ac_cv_search_gethostbyname=no
+ac_cv_search_socket=no
+ac_cv_type_size_t=yes
+ac_cv_type_ssize_t=no
+
+## ----------------- ##
+## Output variables. ##
+## ----------------- ##
+
+BUILD_SO=''
+CC='avr-gcc'
+CFLAGS='-g -O2'
+CPP='avr-gcc -E'
+CPPFLAGS=' -DWITH_POSIX'
+DEFS='-DHAVE_CONFIG_H'
+DOXYGEN='/usr/bin/doxygen'
+ECHO_C=''
+ECHO_N='-n'
+ECHO_T=''
+EGREP='/bin/grep -E'
+ETAGS='/bin/false'
+EXEEXT=''
+GREP='/bin/grep'
+LDFLAGS=''
+LIBOBJS=' ${LIBOBJDIR}malloc$U.o'
+LIBS=''
+LTLIBOBJS=' ${LIBOBJDIR}malloc$U.lo'
+OBJEXT='o'
+PACKAGE_BUGREPORT=''
+PACKAGE_NAME='libcoap'
+PACKAGE_STRING='libcoap 4.1.1'
+PACKAGE_TARNAME='libcoap'
+PACKAGE_URL=''
+PACKAGE_VERSION='4.1.1'
+PATH_SEPARATOR=':'
+RANLIB='avr-ranlib'
+SET_MAKE=''
+SHELL='/bin/bash'
+TESTS=''
+ac_ct_CC=''
+bindir='${exec_prefix}/bin'
+build_alias=''
+datadir='${datarootdir}'
+datarootdir='${prefix}/share'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+dvidir='${docdir}'
+exec_prefix='${prefix}'
+host_alias='avr'
+htmldir='${docdir}'
+includedir='${prefix}/include'
+infodir='${datarootdir}/info'
+libdir='${exec_prefix}/lib'
+libexecdir='${exec_prefix}/libexec'
+localedir='${datarootdir}/locale'
+localstatedir='${prefix}/var'
+mandir='${datarootdir}/man'
+oldincludedir='/usr/include'
+pdfdir='${docdir}'
+prefix='/usr/local'
+program_transform_name='s,x,x,'
+psdir='${docdir}'
+sbindir='${exec_prefix}/sbin'
+sharedstatedir='${prefix}/com'
+sysconfdir='${prefix}/etc'
+target_alias=''
+
+## ----------- ##
+## confdefs.h. ##
+## ----------- ##
+
+/* confdefs.h */
+#define PACKAGE_NAME "libcoap"
+#define PACKAGE_TARNAME "libcoap"
+#define PACKAGE_VERSION "4.1.1"
+#define PACKAGE_STRING "libcoap 4.1.1"
+#define PACKAGE_BUGREPORT ""
+#define PACKAGE_URL ""
+#define STDC_HEADERS 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_ASSERT_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_STDLIB_H 1
+#define HAVE_STRING_H 1
+#define ssize_t int
+#define HAVE_STDLIB_H 1
+#define HAVE_MALLOC 0
+#define malloc rpl_malloc
+#define HAVE_MEMSET 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRNLEN 1
+
+configure: exit 1
--- /dev/null
+#! /bin/bash
+# Generated by configure.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=${CONFIG_SHELL-/bin/bash}
+export SHELL
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by libcoap $as_me 4.1.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+# Files that config.status was made for.
+config_files=" Makefile doc/Makefile doc/Doxyfile examples/Makefile tests/Makefile"
+config_headers=" config.h"
+
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+ac_cs_config="'--host=avr' 'CC=avr-gcc' 'C_EXTRA_FLAGS=-mmcu=atmega2560 -DATMEGA2560' 'host_alias=avr'"
+ac_cs_version="\
+libcoap config.status 4.1.1
+configured by ./configure, generated by GNU Autoconf 2.69,
+ with options \"$ac_cs_config\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='/home/sachin/gitrepos/peg_ccfl-core/libcoap-4.1.1'
+srcdir='.'
+test -n "$AWK" || AWK=awk
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+if $ac_cs_recheck; then
+ set X /bin/bash './configure' '--host=avr' 'CC=avr-gcc' 'C_EXTRA_FLAGS=-mmcu=atmega2560 -DATMEGA2560' 'host_alias=avr' $ac_configure_extra_args --no-create --no-recursion
+ shift
+ $as_echo "running CONFIG_SHELL=/bin/bash $*" >&6
+ CONFIG_SHELL='/bin/bash'
+ export CONFIG_SHELL
+ exec "$@"
+fi
+
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+ "doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES doc/Doxyfile" ;;
+ "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;;
+ "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+cat >>"$ac_tmp/subs1.awk" <<\_ACAWK &&
+S["LTLIBOBJS"]=" ${LIBOBJDIR}malloc$U.lo"
+S["BUILD_SO"]=""
+S["TESTS"]=""
+S["LIBOBJS"]=" ${LIBOBJDIR}malloc$U.o"
+S["EGREP"]="/bin/grep -E"
+S["GREP"]="/bin/grep"
+S["CPP"]="avr-gcc -E"
+S["ETAGS"]="/bin/false"
+S["DOXYGEN"]="/usr/bin/doxygen"
+S["RANLIB"]="avr-ranlib"
+S["OBJEXT"]="o"
+S["EXEEXT"]=""
+S["ac_ct_CC"]=""
+S["CPPFLAGS"]=" -DWITH_POSIX"
+S["LDFLAGS"]=""
+S["CFLAGS"]="-g -O2"
+S["CC"]="avr-gcc"
+S["SET_MAKE"]=""
+S["target_alias"]=""
+S["host_alias"]="avr"
+S["build_alias"]=""
+S["LIBS"]=""
+S["ECHO_T"]=""
+S["ECHO_N"]="-n"
+S["ECHO_C"]=""
+S["DEFS"]="-DHAVE_CONFIG_H"
+S["mandir"]="${datarootdir}/man"
+S["localedir"]="${datarootdir}/locale"
+S["libdir"]="${exec_prefix}/lib"
+S["psdir"]="${docdir}"
+S["pdfdir"]="${docdir}"
+S["dvidir"]="${docdir}"
+S["htmldir"]="${docdir}"
+S["infodir"]="${datarootdir}/info"
+S["docdir"]="${datarootdir}/doc/${PACKAGE_TARNAME}"
+S["oldincludedir"]="/usr/include"
+S["includedir"]="${prefix}/include"
+S["localstatedir"]="${prefix}/var"
+S["sharedstatedir"]="${prefix}/com"
+S["sysconfdir"]="${prefix}/etc"
+S["datadir"]="${datarootdir}"
+S["datarootdir"]="${prefix}/share"
+S["libexecdir"]="${exec_prefix}/libexec"
+S["sbindir"]="${exec_prefix}/sbin"
+S["bindir"]="${exec_prefix}/bin"
+S["program_transform_name"]="s,x,x,"
+S["prefix"]="/usr/local"
+S["exec_prefix"]="${prefix}"
+S["PACKAGE_URL"]=""
+S["PACKAGE_BUGREPORT"]=""
+S["PACKAGE_STRING"]="libcoap 4.1.1"
+S["PACKAGE_VERSION"]="4.1.1"
+S["PACKAGE_TARNAME"]="libcoap"
+S["PACKAGE_NAME"]="libcoap"
+S["PATH_SEPARATOR"]=":"
+S["SHELL"]="/bin/bash"
+_ACAWK
+cat >>"$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = "\a"
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+D["PACKAGE_NAME"]=" \"libcoap\""
+D["PACKAGE_TARNAME"]=" \"libcoap\""
+D["PACKAGE_VERSION"]=" \"4.1.1\""
+D["PACKAGE_STRING"]=" \"libcoap 4.1.1\""
+D["PACKAGE_BUGREPORT"]=" \"\""
+D["PACKAGE_URL"]=" \"\""
+D["STDC_HEADERS"]=" 1"
+D["HAVE_STDLIB_H"]=" 1"
+D["HAVE_STRING_H"]=" 1"
+D["HAVE_INTTYPES_H"]=" 1"
+D["HAVE_STDINT_H"]=" 1"
+D["HAVE_ASSERT_H"]=" 1"
+D["HAVE_LIMITS_H"]=" 1"
+D["HAVE_STDLIB_H"]=" 1"
+D["HAVE_STRING_H"]=" 1"
+D["ssize_t"]=" int"
+D["HAVE_STDLIB_H"]=" 1"
+D["HAVE_MALLOC"]=" 0"
+D["malloc"]=" rpl_malloc"
+D["HAVE_MEMSET"]=" 1"
+D["HAVE_STRCASECMP"]=" 1"
+D["HAVE_STRRCHR"]=" 1"
+D["HAVE_STRNLEN"]=" 1"
+ for (key in D) D_is_set[key] = 1
+ FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+[_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ][_abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789]*([\t (]|$)/ {
+ line = $ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+ ac_datarootdir_hack='
+ s&@datadir@&${datarootdir}&g
+ s&@docdir@&${datarootdir}/doc/${PACKAGE_TARNAME}&g
+ s&@infodir@&${datarootdir}/info&g
+ s&@localedir@&${datarootdir}/locale&g
+ s&@mandir@&${datarootdir}/man&g
+ s&\${datarootdir}&${prefix}/share&g' ;;
+esac
+ac_sed_extra="/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}
+
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
--- /dev/null
+#! /bin/sh
+# Guess values for system-dependent variables and create Makefiles.
+# Generated by GNU Autoconf 2.69 for libcoap 4.1.1.
+#
+#
+# Copyright (C) 1992-1996, 1998-2012 Free Software Foundation, Inc.
+#
+#
+# This configure script is free software; the Free Software Foundation
+# gives unlimited permission to copy, distribute and modify it.
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+# Use a proper internal environment variable to ensure we don't fall
+ # into an infinite loop, continuously re-executing ourselves.
+ if test x"${_as_can_reexec}" != xno && test "x$CONFIG_SHELL" != x; then
+ _as_can_reexec=no; export _as_can_reexec;
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+as_fn_exit 255
+ fi
+ # We don't want this to propagate to other subprocesses.
+ { _as_can_reexec=; unset _as_can_reexec;}
+if test "x$CONFIG_SHELL" = x; then
+ as_bourne_compatible="if test -n \"\${ZSH_VERSION+set}\" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on \${1+\"\$@\"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '\${1+\"\$@\"}'='\"\$@\"'
+ setopt NO_GLOB_SUBST
+else
+ case \`(set -o) 2>/dev/null\` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+"
+ as_required="as_fn_return () { (exit \$1); }
+as_fn_success () { as_fn_return 0; }
+as_fn_failure () { as_fn_return 1; }
+as_fn_ret_success () { return 0; }
+as_fn_ret_failure () { return 1; }
+
+exitcode=0
+as_fn_success || { exitcode=1; echo as_fn_success failed.; }
+as_fn_failure && { exitcode=1; echo as_fn_failure succeeded.; }
+as_fn_ret_success || { exitcode=1; echo as_fn_ret_success failed.; }
+as_fn_ret_failure && { exitcode=1; echo as_fn_ret_failure succeeded.; }
+if ( set x; as_fn_ret_success y && test x = \"\$1\" ); then :
+
+else
+ exitcode=1; echo positional parameters were not saved.
+fi
+test x\$exitcode = x0 || exit 1
+test -x / || exit 1"
+ as_suggested=" as_lineno_1=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_1a=\$LINENO
+ as_lineno_2=";as_suggested=$as_suggested$LINENO;as_suggested=$as_suggested" as_lineno_2a=\$LINENO
+ eval 'test \"x\$as_lineno_1'\$as_run'\" != \"x\$as_lineno_2'\$as_run'\" &&
+ test \"x\`expr \$as_lineno_1'\$as_run' + 1\`\" = \"x\$as_lineno_2'\$as_run'\"' || exit 1
+test \$(( 1 + 1 )) = 2 || exit 1"
+ if (eval "$as_required") 2>/dev/null; then :
+ as_have_required=yes
+else
+ as_have_required=no
+fi
+ if test x$as_have_required = xyes && (eval "$as_suggested") 2>/dev/null; then :
+
+else
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+as_found=false
+for as_dir in /bin$PATH_SEPARATOR/usr/bin$PATH_SEPARATOR$PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ as_found=:
+ case $as_dir in #(
+ /*)
+ for as_base in sh bash ksh sh5; do
+ # Try only shells that exist, to save several forks.
+ as_shell=$as_dir/$as_base
+ if { test -f "$as_shell" || test -f "$as_shell.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ CONFIG_SHELL=$as_shell as_have_required=yes
+ if { $as_echo "$as_bourne_compatible""$as_suggested" | as_run=a "$as_shell"; } 2>/dev/null; then :
+ break 2
+fi
+fi
+ done;;
+ esac
+ as_found=false
+done
+$as_found || { if { test -f "$SHELL" || test -f "$SHELL.exe"; } &&
+ { $as_echo "$as_bourne_compatible""$as_required" | as_run=a "$SHELL"; } 2>/dev/null; then :
+ CONFIG_SHELL=$SHELL as_have_required=yes
+fi; }
+IFS=$as_save_IFS
+
+
+ if test "x$CONFIG_SHELL" != x; then :
+ export CONFIG_SHELL
+ # We cannot yet assume a decent shell, so we have to provide a
+# neutralization value for shells without unset; and this also
+# works around shells that cannot unset nonexistent variables.
+# Preserve -v and -x to the replacement shell.
+BASH_ENV=/dev/null
+ENV=/dev/null
+(unset BASH_ENV) >/dev/null 2>&1 && unset BASH_ENV ENV
+case $- in # ((((
+ *v*x* | *x*v* ) as_opts=-vx ;;
+ *v* ) as_opts=-v ;;
+ *x* ) as_opts=-x ;;
+ * ) as_opts= ;;
+esac
+exec $CONFIG_SHELL $as_opts "$as_myself" ${1+"$@"}
+# Admittedly, this is quite paranoid, since all the known shells bail
+# out after a failed `exec'.
+$as_echo "$0: could not re-execute with $CONFIG_SHELL" >&2
+exit 255
+fi
+
+ if test x$as_have_required = xno; then :
+ $as_echo "$0: This script requires a shell more modern than all"
+ $as_echo "$0: the shells that I found on your system."
+ if test x${ZSH_VERSION+set} = xset ; then
+ $as_echo "$0: In particular, zsh $ZSH_VERSION has bugs and should"
+ $as_echo "$0: be upgraded to zsh 4.3.4 or later."
+ else
+ $as_echo "$0: Please tell bug-autoconf@gnu.org about your system,
+$0: including any error possibly output before this
+$0: message. Then install a modern shell, or manually run
+$0: the script under such a shell if you do have one."
+ fi
+ exit 1
+fi
+fi
+fi
+SHELL=${CONFIG_SHELL-/bin/sh}
+export SHELL
+# Unset more variables known to interfere with behavior of common tools.
+CLICOLOR_FORCE= GREP_OPTIONS=
+unset CLICOLOR_FORCE GREP_OPTIONS
+
+## --------------------- ##
+## M4sh Shell Functions. ##
+## --------------------- ##
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+
+ as_lineno_1=$LINENO as_lineno_1a=$LINENO
+ as_lineno_2=$LINENO as_lineno_2a=$LINENO
+ eval 'test "x$as_lineno_1'$as_run'" != "x$as_lineno_2'$as_run'" &&
+ test "x`expr $as_lineno_1'$as_run' + 1`" = "x$as_lineno_2'$as_run'"' || {
+ # Blame Lee E. McMahon (1931-1989) for sed's syntax. :-)
+ sed -n '
+ p
+ /[$]LINENO/=
+ ' <$as_myself |
+ sed '
+ s/[$]LINENO.*/&-/
+ t lineno
+ b
+ :lineno
+ N
+ :loop
+ s/[$]LINENO\([^'$as_cr_alnum'_].*\n\)\(.*\)/\2\1\2/
+ t loop
+ s/-\n.*//
+ ' >$as_me.lineno &&
+ chmod +x "$as_me.lineno" ||
+ { $as_echo "$as_me: error: cannot create $as_me.lineno; rerun with a POSIX shell" >&2; as_fn_exit 1; }
+
+ # If we had to re-execute with $CONFIG_SHELL, we're ensured to have
+ # already done that, so ensure we don't try to do so again and fall
+ # in an infinite loop. This has already happened in practice.
+ _as_can_reexec=no; export _as_can_reexec
+ # Don't try to exec as it changes $[0], causing all sort of problems
+ # (the dirname of $[0] is not the place where we might find the
+ # original and so on. Autoconf is especially sensitive to this).
+ . "./$as_me.lineno"
+ # Exit status is that of the last command.
+ exit
+}
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+test -n "$DJDIR" || exec 7<&0 </dev/null
+exec 6>&1
+
+# Name of the host.
+# hostname on some systems (SVR3.2, old GNU/Linux) returns a bogus exit status,
+# so uname gets run too.
+ac_hostname=`(hostname || uname -n) 2>/dev/null | sed 1q`
+
+#
+# Initializations.
+#
+ac_default_prefix=/usr/local
+ac_clean_files=
+ac_config_libobj_dir=.
+LIBOBJS=
+cross_compiling=no
+subdirs=
+MFLAGS=
+MAKEFLAGS=
+
+# Identity of this package.
+PACKAGE_NAME='libcoap'
+PACKAGE_TARNAME='libcoap'
+PACKAGE_VERSION='4.1.1'
+PACKAGE_STRING='libcoap 4.1.1'
+PACKAGE_BUGREPORT=''
+PACKAGE_URL=''
+
+ac_unique_file="coap.h"
+# Factoring default headers for most tests.
+ac_includes_default="\
+#include <stdio.h>
+#ifdef HAVE_SYS_TYPES_H
+# include <sys/types.h>
+#endif
+#ifdef HAVE_SYS_STAT_H
+# include <sys/stat.h>
+#endif
+#ifdef STDC_HEADERS
+# include <stdlib.h>
+# include <stddef.h>
+#else
+# ifdef HAVE_STDLIB_H
+# include <stdlib.h>
+# endif
+#endif
+#ifdef HAVE_STRING_H
+# if !defined STDC_HEADERS && defined HAVE_MEMORY_H
+# include <memory.h>
+# endif
+# include <string.h>
+#endif
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+#ifdef HAVE_INTTYPES_H
+# include <inttypes.h>
+#endif
+#ifdef HAVE_STDINT_H
+# include <stdint.h>
+#endif
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif"
+
+ac_subst_vars='LTLIBOBJS
+BUILD_SO
+TESTS
+LIBOBJS
+EGREP
+GREP
+CPP
+ETAGS
+DOXYGEN
+RANLIB
+OBJEXT
+EXEEXT
+ac_ct_CC
+CPPFLAGS
+LDFLAGS
+CFLAGS
+CC
+SET_MAKE
+target_alias
+host_alias
+build_alias
+LIBS
+ECHO_T
+ECHO_N
+ECHO_C
+DEFS
+mandir
+localedir
+libdir
+psdir
+pdfdir
+dvidir
+htmldir
+infodir
+docdir
+oldincludedir
+includedir
+localstatedir
+sharedstatedir
+sysconfdir
+datadir
+datarootdir
+libexecdir
+sbindir
+bindir
+program_transform_name
+prefix
+exec_prefix
+PACKAGE_URL
+PACKAGE_BUGREPORT
+PACKAGE_STRING
+PACKAGE_VERSION
+PACKAGE_TARNAME
+PACKAGE_NAME
+PATH_SEPARATOR
+SHELL'
+ac_subst_files=''
+ac_user_opts='
+enable_option_checking
+with_contiki
+with_debug
+with_async
+with_block
+with_observe
+with_query_filter
+with_tests
+with_shared
+'
+ ac_precious_vars='build_alias
+host_alias
+target_alias
+CC
+CFLAGS
+LDFLAGS
+LIBS
+CPPFLAGS
+CPP'
+
+
+# Initialize some variables set by options.
+ac_init_help=
+ac_init_version=false
+ac_unrecognized_opts=
+ac_unrecognized_sep=
+# The variables have the same names as the options, with
+# dashes changed to underlines.
+cache_file=/dev/null
+exec_prefix=NONE
+no_create=
+no_recursion=
+prefix=NONE
+program_prefix=NONE
+program_suffix=NONE
+program_transform_name=s,x,x,
+silent=
+site=
+srcdir=
+verbose=
+x_includes=NONE
+x_libraries=NONE
+
+# Installation directory options.
+# These are left unexpanded so users can "make install exec_prefix=/foo"
+# and all the variables that are supposed to be based on exec_prefix
+# by default will actually change.
+# Use braces instead of parens because sh, perl, etc. also accept them.
+# (The list follows the same order as the GNU Coding Standards.)
+bindir='${exec_prefix}/bin'
+sbindir='${exec_prefix}/sbin'
+libexecdir='${exec_prefix}/libexec'
+datarootdir='${prefix}/share'
+datadir='${datarootdir}'
+sysconfdir='${prefix}/etc'
+sharedstatedir='${prefix}/com'
+localstatedir='${prefix}/var'
+includedir='${prefix}/include'
+oldincludedir='/usr/include'
+docdir='${datarootdir}/doc/${PACKAGE_TARNAME}'
+infodir='${datarootdir}/info'
+htmldir='${docdir}'
+dvidir='${docdir}'
+pdfdir='${docdir}'
+psdir='${docdir}'
+libdir='${exec_prefix}/lib'
+localedir='${datarootdir}/locale'
+mandir='${datarootdir}/man'
+
+ac_prev=
+ac_dashdash=
+for ac_option
+do
+ # If the previous option needs an argument, assign it.
+ if test -n "$ac_prev"; then
+ eval $ac_prev=\$ac_option
+ ac_prev=
+ continue
+ fi
+
+ case $ac_option in
+ *=?*) ac_optarg=`expr "X$ac_option" : '[^=]*=\(.*\)'` ;;
+ *=) ac_optarg= ;;
+ *) ac_optarg=yes ;;
+ esac
+
+ # Accept the important Cygnus configure options, so we can diagnose typos.
+
+ case $ac_dashdash$ac_option in
+ --)
+ ac_dashdash=yes ;;
+
+ -bindir | --bindir | --bindi | --bind | --bin | --bi)
+ ac_prev=bindir ;;
+ -bindir=* | --bindir=* | --bindi=* | --bind=* | --bin=* | --bi=*)
+ bindir=$ac_optarg ;;
+
+ -build | --build | --buil | --bui | --bu)
+ ac_prev=build_alias ;;
+ -build=* | --build=* | --buil=* | --bui=* | --bu=*)
+ build_alias=$ac_optarg ;;
+
+ -cache-file | --cache-file | --cache-fil | --cache-fi \
+ | --cache-f | --cache- | --cache | --cach | --cac | --ca | --c)
+ ac_prev=cache_file ;;
+ -cache-file=* | --cache-file=* | --cache-fil=* | --cache-fi=* \
+ | --cache-f=* | --cache-=* | --cache=* | --cach=* | --cac=* | --ca=* | --c=*)
+ cache_file=$ac_optarg ;;
+
+ --config-cache | -C)
+ cache_file=config.cache ;;
+
+ -datadir | --datadir | --datadi | --datad)
+ ac_prev=datadir ;;
+ -datadir=* | --datadir=* | --datadi=* | --datad=*)
+ datadir=$ac_optarg ;;
+
+ -datarootdir | --datarootdir | --datarootdi | --datarootd | --dataroot \
+ | --dataroo | --dataro | --datar)
+ ac_prev=datarootdir ;;
+ -datarootdir=* | --datarootdir=* | --datarootdi=* | --datarootd=* \
+ | --dataroot=* | --dataroo=* | --dataro=* | --datar=*)
+ datarootdir=$ac_optarg ;;
+
+ -disable-* | --disable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*disable-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--disable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=no ;;
+
+ -docdir | --docdir | --docdi | --doc | --do)
+ ac_prev=docdir ;;
+ -docdir=* | --docdir=* | --docdi=* | --doc=* | --do=*)
+ docdir=$ac_optarg ;;
+
+ -dvidir | --dvidir | --dvidi | --dvid | --dvi | --dv)
+ ac_prev=dvidir ;;
+ -dvidir=* | --dvidir=* | --dvidi=* | --dvid=* | --dvi=* | --dv=*)
+ dvidir=$ac_optarg ;;
+
+ -enable-* | --enable-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*enable-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid feature name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"enable_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--enable-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval enable_$ac_useropt=\$ac_optarg ;;
+
+ -exec-prefix | --exec_prefix | --exec-prefix | --exec-prefi \
+ | --exec-pref | --exec-pre | --exec-pr | --exec-p | --exec- \
+ | --exec | --exe | --ex)
+ ac_prev=exec_prefix ;;
+ -exec-prefix=* | --exec_prefix=* | --exec-prefix=* | --exec-prefi=* \
+ | --exec-pref=* | --exec-pre=* | --exec-pr=* | --exec-p=* | --exec-=* \
+ | --exec=* | --exe=* | --ex=*)
+ exec_prefix=$ac_optarg ;;
+
+ -gas | --gas | --ga | --g)
+ # Obsolete; use --with-gas.
+ with_gas=yes ;;
+
+ -help | --help | --hel | --he | -h)
+ ac_init_help=long ;;
+ -help=r* | --help=r* | --hel=r* | --he=r* | -hr*)
+ ac_init_help=recursive ;;
+ -help=s* | --help=s* | --hel=s* | --he=s* | -hs*)
+ ac_init_help=short ;;
+
+ -host | --host | --hos | --ho)
+ ac_prev=host_alias ;;
+ -host=* | --host=* | --hos=* | --ho=*)
+ host_alias=$ac_optarg ;;
+
+ -htmldir | --htmldir | --htmldi | --htmld | --html | --htm | --ht)
+ ac_prev=htmldir ;;
+ -htmldir=* | --htmldir=* | --htmldi=* | --htmld=* | --html=* | --htm=* \
+ | --ht=*)
+ htmldir=$ac_optarg ;;
+
+ -includedir | --includedir | --includedi | --included | --include \
+ | --includ | --inclu | --incl | --inc)
+ ac_prev=includedir ;;
+ -includedir=* | --includedir=* | --includedi=* | --included=* | --include=* \
+ | --includ=* | --inclu=* | --incl=* | --inc=*)
+ includedir=$ac_optarg ;;
+
+ -infodir | --infodir | --infodi | --infod | --info | --inf)
+ ac_prev=infodir ;;
+ -infodir=* | --infodir=* | --infodi=* | --infod=* | --info=* | --inf=*)
+ infodir=$ac_optarg ;;
+
+ -libdir | --libdir | --libdi | --libd)
+ ac_prev=libdir ;;
+ -libdir=* | --libdir=* | --libdi=* | --libd=*)
+ libdir=$ac_optarg ;;
+
+ -libexecdir | --libexecdir | --libexecdi | --libexecd | --libexec \
+ | --libexe | --libex | --libe)
+ ac_prev=libexecdir ;;
+ -libexecdir=* | --libexecdir=* | --libexecdi=* | --libexecd=* | --libexec=* \
+ | --libexe=* | --libex=* | --libe=*)
+ libexecdir=$ac_optarg ;;
+
+ -localedir | --localedir | --localedi | --localed | --locale)
+ ac_prev=localedir ;;
+ -localedir=* | --localedir=* | --localedi=* | --localed=* | --locale=*)
+ localedir=$ac_optarg ;;
+
+ -localstatedir | --localstatedir | --localstatedi | --localstated \
+ | --localstate | --localstat | --localsta | --localst | --locals)
+ ac_prev=localstatedir ;;
+ -localstatedir=* | --localstatedir=* | --localstatedi=* | --localstated=* \
+ | --localstate=* | --localstat=* | --localsta=* | --localst=* | --locals=*)
+ localstatedir=$ac_optarg ;;
+
+ -mandir | --mandir | --mandi | --mand | --man | --ma | --m)
+ ac_prev=mandir ;;
+ -mandir=* | --mandir=* | --mandi=* | --mand=* | --man=* | --ma=* | --m=*)
+ mandir=$ac_optarg ;;
+
+ -nfp | --nfp | --nf)
+ # Obsolete; use --without-fp.
+ with_fp=no ;;
+
+ -no-create | --no-create | --no-creat | --no-crea | --no-cre \
+ | --no-cr | --no-c | -n)
+ no_create=yes ;;
+
+ -no-recursion | --no-recursion | --no-recursio | --no-recursi \
+ | --no-recurs | --no-recur | --no-recu | --no-rec | --no-re | --no-r)
+ no_recursion=yes ;;
+
+ -oldincludedir | --oldincludedir | --oldincludedi | --oldincluded \
+ | --oldinclude | --oldinclud | --oldinclu | --oldincl | --oldinc \
+ | --oldin | --oldi | --old | --ol | --o)
+ ac_prev=oldincludedir ;;
+ -oldincludedir=* | --oldincludedir=* | --oldincludedi=* | --oldincluded=* \
+ | --oldinclude=* | --oldinclud=* | --oldinclu=* | --oldincl=* | --oldinc=* \
+ | --oldin=* | --oldi=* | --old=* | --ol=* | --o=*)
+ oldincludedir=$ac_optarg ;;
+
+ -prefix | --prefix | --prefi | --pref | --pre | --pr | --p)
+ ac_prev=prefix ;;
+ -prefix=* | --prefix=* | --prefi=* | --pref=* | --pre=* | --pr=* | --p=*)
+ prefix=$ac_optarg ;;
+
+ -program-prefix | --program-prefix | --program-prefi | --program-pref \
+ | --program-pre | --program-pr | --program-p)
+ ac_prev=program_prefix ;;
+ -program-prefix=* | --program-prefix=* | --program-prefi=* \
+ | --program-pref=* | --program-pre=* | --program-pr=* | --program-p=*)
+ program_prefix=$ac_optarg ;;
+
+ -program-suffix | --program-suffix | --program-suffi | --program-suff \
+ | --program-suf | --program-su | --program-s)
+ ac_prev=program_suffix ;;
+ -program-suffix=* | --program-suffix=* | --program-suffi=* \
+ | --program-suff=* | --program-suf=* | --program-su=* | --program-s=*)
+ program_suffix=$ac_optarg ;;
+
+ -program-transform-name | --program-transform-name \
+ | --program-transform-nam | --program-transform-na \
+ | --program-transform-n | --program-transform- \
+ | --program-transform | --program-transfor \
+ | --program-transfo | --program-transf \
+ | --program-trans | --program-tran \
+ | --progr-tra | --program-tr | --program-t)
+ ac_prev=program_transform_name ;;
+ -program-transform-name=* | --program-transform-name=* \
+ | --program-transform-nam=* | --program-transform-na=* \
+ | --program-transform-n=* | --program-transform-=* \
+ | --program-transform=* | --program-transfor=* \
+ | --program-transfo=* | --program-transf=* \
+ | --program-trans=* | --program-tran=* \
+ | --progr-tra=* | --program-tr=* | --program-t=*)
+ program_transform_name=$ac_optarg ;;
+
+ -pdfdir | --pdfdir | --pdfdi | --pdfd | --pdf | --pd)
+ ac_prev=pdfdir ;;
+ -pdfdir=* | --pdfdir=* | --pdfdi=* | --pdfd=* | --pdf=* | --pd=*)
+ pdfdir=$ac_optarg ;;
+
+ -psdir | --psdir | --psdi | --psd | --ps)
+ ac_prev=psdir ;;
+ -psdir=* | --psdir=* | --psdi=* | --psd=* | --ps=*)
+ psdir=$ac_optarg ;;
+
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ silent=yes ;;
+
+ -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb)
+ ac_prev=sbindir ;;
+ -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \
+ | --sbi=* | --sb=*)
+ sbindir=$ac_optarg ;;
+
+ -sharedstatedir | --sharedstatedir | --sharedstatedi \
+ | --sharedstated | --sharedstate | --sharedstat | --sharedsta \
+ | --sharedst | --shareds | --shared | --share | --shar \
+ | --sha | --sh)
+ ac_prev=sharedstatedir ;;
+ -sharedstatedir=* | --sharedstatedir=* | --sharedstatedi=* \
+ | --sharedstated=* | --sharedstate=* | --sharedstat=* | --sharedsta=* \
+ | --sharedst=* | --shareds=* | --shared=* | --share=* | --shar=* \
+ | --sha=* | --sh=*)
+ sharedstatedir=$ac_optarg ;;
+
+ -site | --site | --sit)
+ ac_prev=site ;;
+ -site=* | --site=* | --sit=*)
+ site=$ac_optarg ;;
+
+ -srcdir | --srcdir | --srcdi | --srcd | --src | --sr)
+ ac_prev=srcdir ;;
+ -srcdir=* | --srcdir=* | --srcdi=* | --srcd=* | --src=* | --sr=*)
+ srcdir=$ac_optarg ;;
+
+ -sysconfdir | --sysconfdir | --sysconfdi | --sysconfd | --sysconf \
+ | --syscon | --sysco | --sysc | --sys | --sy)
+ ac_prev=sysconfdir ;;
+ -sysconfdir=* | --sysconfdir=* | --sysconfdi=* | --sysconfd=* | --sysconf=* \
+ | --syscon=* | --sysco=* | --sysc=* | --sys=* | --sy=*)
+ sysconfdir=$ac_optarg ;;
+
+ -target | --target | --targe | --targ | --tar | --ta | --t)
+ ac_prev=target_alias ;;
+ -target=* | --target=* | --targe=* | --targ=* | --tar=* | --ta=* | --t=*)
+ target_alias=$ac_optarg ;;
+
+ -v | -verbose | --verbose | --verbos | --verbo | --verb)
+ verbose=yes ;;
+
+ -version | --version | --versio | --versi | --vers | -V)
+ ac_init_version=: ;;
+
+ -with-* | --with-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*with-\([^=]*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--with-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=\$ac_optarg ;;
+
+ -without-* | --without-*)
+ ac_useropt=`expr "x$ac_option" : 'x-*without-\(.*\)'`
+ # Reject names that are not valid shell variable names.
+ expr "x$ac_useropt" : ".*[^-+._$as_cr_alnum]" >/dev/null &&
+ as_fn_error $? "invalid package name: $ac_useropt"
+ ac_useropt_orig=$ac_useropt
+ ac_useropt=`$as_echo "$ac_useropt" | sed 's/[-+.]/_/g'`
+ case $ac_user_opts in
+ *"
+"with_$ac_useropt"
+"*) ;;
+ *) ac_unrecognized_opts="$ac_unrecognized_opts$ac_unrecognized_sep--without-$ac_useropt_orig"
+ ac_unrecognized_sep=', ';;
+ esac
+ eval with_$ac_useropt=no ;;
+
+ --x)
+ # Obsolete; use --with-x.
+ with_x=yes ;;
+
+ -x-includes | --x-includes | --x-include | --x-includ | --x-inclu \
+ | --x-incl | --x-inc | --x-in | --x-i)
+ ac_prev=x_includes ;;
+ -x-includes=* | --x-includes=* | --x-include=* | --x-includ=* | --x-inclu=* \
+ | --x-incl=* | --x-inc=* | --x-in=* | --x-i=*)
+ x_includes=$ac_optarg ;;
+
+ -x-libraries | --x-libraries | --x-librarie | --x-librari \
+ | --x-librar | --x-libra | --x-libr | --x-lib | --x-li | --x-l)
+ ac_prev=x_libraries ;;
+ -x-libraries=* | --x-libraries=* | --x-librarie=* | --x-librari=* \
+ | --x-librar=* | --x-libra=* | --x-libr=* | --x-lib=* | --x-li=* | --x-l=*)
+ x_libraries=$ac_optarg ;;
+
+ -*) as_fn_error $? "unrecognized option: \`$ac_option'
+Try \`$0 --help' for more information"
+ ;;
+
+ *=*)
+ ac_envvar=`expr "x$ac_option" : 'x\([^=]*\)='`
+ # Reject names that are not valid shell variable names.
+ case $ac_envvar in #(
+ '' | [0-9]* | *[!_$as_cr_alnum]* )
+ as_fn_error $? "invalid variable name: \`$ac_envvar'" ;;
+ esac
+ eval $ac_envvar=\$ac_optarg
+ export $ac_envvar ;;
+
+ *)
+ # FIXME: should be removed in autoconf 3.0.
+ $as_echo "$as_me: WARNING: you should use --build, --host, --target" >&2
+ expr "x$ac_option" : ".*[^-._$as_cr_alnum]" >/dev/null &&
+ $as_echo "$as_me: WARNING: invalid host type: $ac_option" >&2
+ : "${build_alias=$ac_option} ${host_alias=$ac_option} ${target_alias=$ac_option}"
+ ;;
+
+ esac
+done
+
+if test -n "$ac_prev"; then
+ ac_option=--`echo $ac_prev | sed 's/_/-/g'`
+ as_fn_error $? "missing argument to $ac_option"
+fi
+
+if test -n "$ac_unrecognized_opts"; then
+ case $enable_option_checking in
+ no) ;;
+ fatal) as_fn_error $? "unrecognized options: $ac_unrecognized_opts" ;;
+ *) $as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2 ;;
+ esac
+fi
+
+# Check all directory arguments for consistency.
+for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \
+ datadir sysconfdir sharedstatedir localstatedir includedir \
+ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \
+ libdir localedir mandir
+do
+ eval ac_val=\$$ac_var
+ # Remove trailing slashes.
+ case $ac_val in
+ */ )
+ ac_val=`expr "X$ac_val" : 'X\(.*[^/]\)' \| "X$ac_val" : 'X\(.*\)'`
+ eval $ac_var=\$ac_val;;
+ esac
+ # Be sure to have absolute directory names.
+ case $ac_val in
+ [\\/$]* | ?:[\\/]* ) continue;;
+ NONE | '' ) case $ac_var in *prefix ) continue;; esac;;
+ esac
+ as_fn_error $? "expected an absolute directory name for --$ac_var: $ac_val"
+done
+
+# There might be people who depend on the old broken behavior: `$host'
+# used to hold the argument of --host etc.
+# FIXME: To remove some day.
+build=$build_alias
+host=$host_alias
+target=$target_alias
+
+# FIXME: To remove some day.
+if test "x$host_alias" != x; then
+ if test "x$build_alias" = x; then
+ cross_compiling=maybe
+ elif test "x$build_alias" != "x$host_alias"; then
+ cross_compiling=yes
+ fi
+fi
+
+ac_tool_prefix=
+test -n "$host_alias" && ac_tool_prefix=$host_alias-
+
+test "$silent" = yes && exec 6>/dev/null
+
+
+ac_pwd=`pwd` && test -n "$ac_pwd" &&
+ac_ls_di=`ls -di .` &&
+ac_pwd_ls_di=`cd "$ac_pwd" && ls -di .` ||
+ as_fn_error $? "working directory cannot be determined"
+test "X$ac_ls_di" = "X$ac_pwd_ls_di" ||
+ as_fn_error $? "pwd does not report name of working directory"
+
+
+# Find the source files, if location was not specified.
+if test -z "$srcdir"; then
+ ac_srcdir_defaulted=yes
+ # Try the directory containing this script, then the parent directory.
+ ac_confdir=`$as_dirname -- "$as_myself" ||
+$as_expr X"$as_myself" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_myself" : 'X\(//\)[^/]' \| \
+ X"$as_myself" : 'X\(//\)$' \| \
+ X"$as_myself" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_myself" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ srcdir=$ac_confdir
+ if test ! -r "$srcdir/$ac_unique_file"; then
+ srcdir=..
+ fi
+else
+ ac_srcdir_defaulted=no
+fi
+if test ! -r "$srcdir/$ac_unique_file"; then
+ test "$ac_srcdir_defaulted" = yes && srcdir="$ac_confdir or .."
+ as_fn_error $? "cannot find sources ($ac_unique_file) in $srcdir"
+fi
+ac_msg="sources are in $srcdir, but \`cd $srcdir' does not work"
+ac_abs_confdir=`(
+ cd "$srcdir" && test -r "./$ac_unique_file" || as_fn_error $? "$ac_msg"
+ pwd)`
+# When building in place, set srcdir=.
+if test "$ac_abs_confdir" = "$ac_pwd"; then
+ srcdir=.
+fi
+# Remove unnecessary trailing slashes from srcdir.
+# Double slashes in file names in object file debugging info
+# mess up M-x gdb in Emacs.
+case $srcdir in
+*/) srcdir=`expr "X$srcdir" : 'X\(.*[^/]\)' \| "X$srcdir" : 'X\(.*\)'`;;
+esac
+for ac_var in $ac_precious_vars; do
+ eval ac_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_env_${ac_var}_value=\$${ac_var}
+ eval ac_cv_env_${ac_var}_set=\${${ac_var}+set}
+ eval ac_cv_env_${ac_var}_value=\$${ac_var}
+done
+
+#
+# Report the --help message.
+#
+if test "$ac_init_help" = "long"; then
+ # Omit some internal or obsolete options to make the list less imposing.
+ # This message is too long to be a string in the A/UX 3.1 sh.
+ cat <<_ACEOF
+\`configure' configures libcoap 4.1.1 to adapt to many kinds of systems.
+
+Usage: $0 [OPTION]... [VAR=VALUE]...
+
+To assign environment variables (e.g., CC, CFLAGS...), specify them as
+VAR=VALUE. See below for descriptions of some of the useful variables.
+
+Defaults for the options are specified in brackets.
+
+Configuration:
+ -h, --help display this help and exit
+ --help=short display options specific to this package
+ --help=recursive display the short help of all the included packages
+ -V, --version display version information and exit
+ -q, --quiet, --silent do not print \`checking ...' messages
+ --cache-file=FILE cache test results in FILE [disabled]
+ -C, --config-cache alias for \`--cache-file=config.cache'
+ -n, --no-create do not create output files
+ --srcdir=DIR find the sources in DIR [configure dir or \`..']
+
+Installation directories:
+ --prefix=PREFIX install architecture-independent files in PREFIX
+ [$ac_default_prefix]
+ --exec-prefix=EPREFIX install architecture-dependent files in EPREFIX
+ [PREFIX]
+
+By default, \`make install' will install all the files in
+\`$ac_default_prefix/bin', \`$ac_default_prefix/lib' etc. You can specify
+an installation prefix other than \`$ac_default_prefix' using \`--prefix',
+for instance \`--prefix=\$HOME'.
+
+For better control, use the options below.
+
+Fine tuning of the installation directories:
+ --bindir=DIR user executables [EPREFIX/bin]
+ --sbindir=DIR system admin executables [EPREFIX/sbin]
+ --libexecdir=DIR program executables [EPREFIX/libexec]
+ --sysconfdir=DIR read-only single-machine data [PREFIX/etc]
+ --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com]
+ --localstatedir=DIR modifiable single-machine data [PREFIX/var]
+ --libdir=DIR object code libraries [EPREFIX/lib]
+ --includedir=DIR C header files [PREFIX/include]
+ --oldincludedir=DIR C header files for non-gcc [/usr/include]
+ --datarootdir=DIR read-only arch.-independent data root [PREFIX/share]
+ --datadir=DIR read-only architecture-independent data [DATAROOTDIR]
+ --infodir=DIR info documentation [DATAROOTDIR/info]
+ --localedir=DIR locale-dependent data [DATAROOTDIR/locale]
+ --mandir=DIR man documentation [DATAROOTDIR/man]
+ --docdir=DIR documentation root [DATAROOTDIR/doc/libcoap]
+ --htmldir=DIR html documentation [DOCDIR]
+ --dvidir=DIR dvi documentation [DOCDIR]
+ --pdfdir=DIR pdf documentation [DOCDIR]
+ --psdir=DIR ps documentation [DOCDIR]
+_ACEOF
+
+ cat <<\_ACEOF
+_ACEOF
+fi
+
+if test -n "$ac_init_help"; then
+ case $ac_init_help in
+ short | recursive ) echo "Configuration of libcoap 4.1.1:";;
+ esac
+ cat <<\_ACEOF
+
+Optional Packages:
+ --with-PACKAGE[=ARG] use PACKAGE [ARG=yes]
+ --without-PACKAGE do not use PACKAGE (same as --with-PACKAGE=no)
+ --with-contiki build libcoap for the Contiki OS
+ --without-debug disable all debug output and assertions
+ --without-async disable handling of asynchronous transactions and
+ observe
+ --without-block disable block transfer
+ --without-observe disable resource observation
+ --without-query-filter disable support for filters on /.well-known/core
+ --with-tests enable unit tests (requires cunit)
+ --with-shared build shared library
+
+Some influential environment variables:
+ CC C compiler command
+ CFLAGS C compiler flags
+ LDFLAGS linker flags, e.g. -L<lib dir> if you have libraries in a
+ nonstandard directory <lib dir>
+ LIBS libraries to pass to the linker, e.g. -l<library>
+ CPPFLAGS (Objective) C/C++ preprocessor flags, e.g. -I<include dir> if
+ you have headers in a nonstandard directory <include dir>
+ CPP C preprocessor
+
+Use these variables to override the choices made by `configure' or to help
+it to find libraries and programs with nonstandard names/locations.
+
+Report bugs to the package provider.
+_ACEOF
+ac_status=$?
+fi
+
+if test "$ac_init_help" = "recursive"; then
+ # If there are subdirs, report their specific --help.
+ for ac_dir in : $ac_subdirs_all; do test "x$ac_dir" = x: && continue
+ test -d "$ac_dir" ||
+ { cd "$srcdir" && ac_pwd=`pwd` && srcdir=. && test -d "$ac_dir"; } ||
+ continue
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+ cd "$ac_dir" || { ac_status=$?; continue; }
+ # Check for guested configure.
+ if test -f "$ac_srcdir/configure.gnu"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure.gnu" --help=recursive
+ elif test -f "$ac_srcdir/configure"; then
+ echo &&
+ $SHELL "$ac_srcdir/configure" --help=recursive
+ else
+ $as_echo "$as_me: WARNING: no configuration information is in $ac_dir" >&2
+ fi || ac_status=$?
+ cd "$ac_pwd" || { ac_status=$?; break; }
+ done
+fi
+
+test -n "$ac_init_help" && exit $ac_status
+if $ac_init_version; then
+ cat <<\_ACEOF
+libcoap configure 4.1.1
+generated by GNU Autoconf 2.69
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This configure script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it.
+_ACEOF
+ exit
+fi
+
+## ------------------------ ##
+## Autoconf initialization. ##
+## ------------------------ ##
+
+# ac_fn_c_try_compile LINENO
+# --------------------------
+# Try to compile conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext
+ if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest.$ac_objext; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_compile
+
+# ac_fn_c_try_run LINENO
+# ----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded. Assumes
+# that executables *can* be run.
+ac_fn_c_try_run ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && { ac_try='./conftest$ac_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: program exited with status $ac_status" >&5
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=$ac_status
+fi
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_run
+
+# ac_fn_c_try_cpp LINENO
+# ----------------------
+# Try to preprocess conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_cpp ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if { { ac_try="$ac_cpp conftest.$ac_ext"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_cpp conftest.$ac_ext") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } > conftest.i && {
+ test -z "$ac_c_preproc_warn_flag$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_cpp
+
+# ac_fn_c_check_header_compile LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists and can be compiled using the include files in
+# INCLUDES, setting the cache variable VAR accordingly.
+ac_fn_c_check_header_compile ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_compile
+
+# ac_fn_c_try_link LINENO
+# -----------------------
+# Try to link conftest.$ac_ext, and return whether this succeeded.
+ac_fn_c_try_link ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ rm -f conftest.$ac_objext conftest$ac_exeext
+ if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ grep -v '^ *+' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ mv -f conftest.er1 conftest.err
+ fi
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; } && {
+ test -z "$ac_c_werror_flag" ||
+ test ! -s conftest.err
+ } && test -s conftest$ac_exeext && {
+ test "$cross_compiling" = yes ||
+ test -x conftest$ac_exeext
+ }; then :
+ ac_retval=0
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+ ac_retval=1
+fi
+ # Delete the IPA/IPO (Inter Procedural Analysis/Optimization) information
+ # created by the PGI compiler (conftest_ipa8_conftest.oo), as it would
+ # interfere with the next link command; also delete a directory that is
+ # left behind by Apple's compiler. We do this before executing the actions.
+ rm -rf conftest.dSYM conftest_ipa8_conftest.oo
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+ as_fn_set_status $ac_retval
+
+} # ac_fn_c_try_link
+
+# ac_fn_c_check_header_mongrel LINENO HEADER VAR INCLUDES
+# -------------------------------------------------------
+# Tests whether HEADER exists, giving a warning if it cannot be compiled using
+# the include files in INCLUDES and setting the cache variable VAR
+# accordingly.
+ac_fn_c_check_header_mongrel ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ if eval \${$3+:} false; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+else
+ # Is the header compilable?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 usability" >&5
+$as_echo_n "checking $2 usability... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+#include <$2>
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_header_compiler=yes
+else
+ ac_header_compiler=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_compiler" >&5
+$as_echo "$ac_header_compiler" >&6; }
+
+# Is the header present?
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking $2 presence" >&5
+$as_echo_n "checking $2 presence... " >&6; }
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <$2>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ ac_header_preproc=yes
+else
+ ac_header_preproc=no
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_header_preproc" >&5
+$as_echo "$ac_header_preproc" >&6; }
+
+# So? What about this header?
+case $ac_header_compiler:$ac_header_preproc:$ac_c_preproc_warn_flag in #((
+ yes:no: )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&5
+$as_echo "$as_me: WARNING: $2: accepted by the compiler, rejected by the preprocessor!" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+ no:yes:* )
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: present but cannot be compiled" >&5
+$as_echo "$as_me: WARNING: $2: present but cannot be compiled" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: check for missing prerequisite headers?" >&5
+$as_echo "$as_me: WARNING: $2: check for missing prerequisite headers?" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: see the Autoconf documentation" >&5
+$as_echo "$as_me: WARNING: $2: see the Autoconf documentation" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&5
+$as_echo "$as_me: WARNING: $2: section \"Present But Cannot Be Compiled\"" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $2: proceeding with the compiler's result" >&5
+$as_echo "$as_me: WARNING: $2: proceeding with the compiler's result" >&2;}
+ ;;
+esac
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=\$ac_header_compiler"
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+fi
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_header_mongrel
+
+# ac_fn_c_check_type LINENO TYPE VAR INCLUDES
+# -------------------------------------------
+# Tests whether TYPE exists after having included INCLUDES, setting cache
+# variable VAR accordingly.
+ac_fn_c_check_type ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ eval "$3=no"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof ($2))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$4
+int
+main ()
+{
+if (sizeof (($2)))
+ return 0;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ eval "$3=yes"
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_type
+
+# ac_fn_c_check_func LINENO FUNC VAR
+# ----------------------------------
+# Tests whether FUNC exists, setting the cache variable VAR accordingly
+ac_fn_c_check_func ()
+{
+ as_lineno=${as_lineno-"$1"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for $2" >&5
+$as_echo_n "checking for $2... " >&6; }
+if eval \${$3+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+/* Define $2 to an innocuous variant, in case <limits.h> declares $2.
+ For example, HP-UX 11i <limits.h> declares gettimeofday. */
+#define $2 innocuous_$2
+
+/* System header to define __stub macros and hopefully few prototypes,
+ which can conflict with char $2 (); below.
+ Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ <limits.h> exists even on freestanding compilers. */
+
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+
+#undef $2
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char $2 ();
+/* The GNU C library defines this for functions which it implements
+ to always fail with ENOSYS. Some functions are actually named
+ something starting with __ and the normal name is an alias. */
+#if defined __stub_$2 || defined __stub___$2
+choke me
+#endif
+
+int
+main ()
+{
+return $2 ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ eval "$3=yes"
+else
+ eval "$3=no"
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+fi
+eval ac_res=\$$3
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_res" >&5
+$as_echo "$ac_res" >&6; }
+ eval $as_lineno_stack; ${as_lineno_stack:+:} unset as_lineno
+
+} # ac_fn_c_check_func
+cat >config.log <<_ACEOF
+This file contains any messages produced by compilers while
+running configure, to aid debugging if configure makes a mistake.
+
+It was created by libcoap $as_me 4.1.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ $ $0 $@
+
+_ACEOF
+exec 5>>config.log
+{
+cat <<_ASUNAME
+## --------- ##
+## Platform. ##
+## --------- ##
+
+hostname = `(hostname || uname -n) 2>/dev/null | sed 1q`
+uname -m = `(uname -m) 2>/dev/null || echo unknown`
+uname -r = `(uname -r) 2>/dev/null || echo unknown`
+uname -s = `(uname -s) 2>/dev/null || echo unknown`
+uname -v = `(uname -v) 2>/dev/null || echo unknown`
+
+/usr/bin/uname -p = `(/usr/bin/uname -p) 2>/dev/null || echo unknown`
+/bin/uname -X = `(/bin/uname -X) 2>/dev/null || echo unknown`
+
+/bin/arch = `(/bin/arch) 2>/dev/null || echo unknown`
+/usr/bin/arch -k = `(/usr/bin/arch -k) 2>/dev/null || echo unknown`
+/usr/convex/getsysinfo = `(/usr/convex/getsysinfo) 2>/dev/null || echo unknown`
+/usr/bin/hostinfo = `(/usr/bin/hostinfo) 2>/dev/null || echo unknown`
+/bin/machine = `(/bin/machine) 2>/dev/null || echo unknown`
+/usr/bin/oslevel = `(/usr/bin/oslevel) 2>/dev/null || echo unknown`
+/bin/universe = `(/bin/universe) 2>/dev/null || echo unknown`
+
+_ASUNAME
+
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ $as_echo "PATH: $as_dir"
+ done
+IFS=$as_save_IFS
+
+} >&5
+
+cat >&5 <<_ACEOF
+
+
+## ----------- ##
+## Core tests. ##
+## ----------- ##
+
+_ACEOF
+
+
+# Keep a trace of the command line.
+# Strip out --no-create and --no-recursion so they do not pile up.
+# Strip out --silent because we don't want to record it for future runs.
+# Also quote any args containing shell meta-characters.
+# Make two passes to allow for proper duplicate-argument suppression.
+ac_configure_args=
+ac_configure_args0=
+ac_configure_args1=
+ac_must_keep_next=false
+for ac_pass in 1 2
+do
+ for ac_arg
+ do
+ case $ac_arg in
+ -no-create | --no-c* | -n | -no-recursion | --no-r*) continue ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil)
+ continue ;;
+ *\'*)
+ ac_arg=`$as_echo "$ac_arg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ case $ac_pass in
+ 1) as_fn_append ac_configure_args0 " '$ac_arg'" ;;
+ 2)
+ as_fn_append ac_configure_args1 " '$ac_arg'"
+ if test $ac_must_keep_next = true; then
+ ac_must_keep_next=false # Got value, back to normal.
+ else
+ case $ac_arg in
+ *=* | --config-cache | -C | -disable-* | --disable-* \
+ | -enable-* | --enable-* | -gas | --g* | -nfp | --nf* \
+ | -q | -quiet | --q* | -silent | --sil* | -v | -verb* \
+ | -with-* | --with-* | -without-* | --without-* | --x)
+ case "$ac_configure_args0 " in
+ "$ac_configure_args1"*" '$ac_arg' "* ) continue ;;
+ esac
+ ;;
+ -* ) ac_must_keep_next=true ;;
+ esac
+ fi
+ as_fn_append ac_configure_args " '$ac_arg'"
+ ;;
+ esac
+ done
+done
+{ ac_configure_args0=; unset ac_configure_args0;}
+{ ac_configure_args1=; unset ac_configure_args1;}
+
+# When interrupted or exit'd, cleanup temporary files, and complete
+# config.log. We remove comments because anyway the quotes in there
+# would cause problems or look ugly.
+# WARNING: Use '\'' to represent an apostrophe within the trap.
+# WARNING: Do not start the trap code with a newline, due to a FreeBSD 4.0 bug.
+trap 'exit_status=$?
+ # Save into config.log some information that might help in debugging.
+ {
+ echo
+
+ $as_echo "## ---------------- ##
+## Cache variables. ##
+## ---------------- ##"
+ echo
+ # The following way of writing the cache mishandles newlines in values,
+(
+ for ac_var in `(set) 2>&1 | sed -n '\''s/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'\''`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+ (set) 2>&1 |
+ case $as_nl`(ac_space='\'' '\''; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ sed -n \
+ "s/'\''/'\''\\\\'\'''\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\''\\2'\''/p"
+ ;; #(
+ *)
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+)
+ echo
+
+ $as_echo "## ----------------- ##
+## Output variables. ##
+## ----------------- ##"
+ echo
+ for ac_var in $ac_subst_vars
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+
+ if test -n "$ac_subst_files"; then
+ $as_echo "## ------------------- ##
+## File substitutions. ##
+## ------------------- ##"
+ echo
+ for ac_var in $ac_subst_files
+ do
+ eval ac_val=\$$ac_var
+ case $ac_val in
+ *\'\''*) ac_val=`$as_echo "$ac_val" | sed "s/'\''/'\''\\\\\\\\'\'''\''/g"`;;
+ esac
+ $as_echo "$ac_var='\''$ac_val'\''"
+ done | sort
+ echo
+ fi
+
+ if test -s confdefs.h; then
+ $as_echo "## ----------- ##
+## confdefs.h. ##
+## ----------- ##"
+ echo
+ cat confdefs.h
+ echo
+ fi
+ test "$ac_signal" != 0 &&
+ $as_echo "$as_me: caught signal $ac_signal"
+ $as_echo "$as_me: exit $exit_status"
+ } >&5
+ rm -f core *.core core.conftest.* &&
+ rm -f -r conftest* confdefs* conf$$* $ac_clean_files &&
+ exit $exit_status
+' 0
+for ac_signal in 1 2 13 15; do
+ trap 'ac_signal='$ac_signal'; as_fn_exit 1' $ac_signal
+done
+ac_signal=0
+
+# confdefs.h avoids OS command line length limits that DEFS can exceed.
+rm -f -r conftest* confdefs.h
+
+$as_echo "/* confdefs.h */" > confdefs.h
+
+# Predefined preprocessor variables.
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_NAME "$PACKAGE_NAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_TARNAME "$PACKAGE_TARNAME"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_VERSION "$PACKAGE_VERSION"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_STRING "$PACKAGE_STRING"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_BUGREPORT "$PACKAGE_BUGREPORT"
+_ACEOF
+
+cat >>confdefs.h <<_ACEOF
+#define PACKAGE_URL "$PACKAGE_URL"
+_ACEOF
+
+
+# Let the site file select an alternate cache file if it wants to.
+# Prefer an explicitly selected file to automatically selected ones.
+ac_site_file1=NONE
+ac_site_file2=NONE
+if test -n "$CONFIG_SITE"; then
+ # We do not want a PATH search for config.site.
+ case $CONFIG_SITE in #((
+ -*) ac_site_file1=./$CONFIG_SITE;;
+ */*) ac_site_file1=$CONFIG_SITE;;
+ *) ac_site_file1=./$CONFIG_SITE;;
+ esac
+elif test "x$prefix" != xNONE; then
+ ac_site_file1=$prefix/share/config.site
+ ac_site_file2=$prefix/etc/config.site
+else
+ ac_site_file1=$ac_default_prefix/share/config.site
+ ac_site_file2=$ac_default_prefix/etc/config.site
+fi
+for ac_site_file in "$ac_site_file1" "$ac_site_file2"
+do
+ test "x$ac_site_file" = xNONE && continue
+ if test /dev/null != "$ac_site_file" && test -r "$ac_site_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading site script $ac_site_file" >&5
+$as_echo "$as_me: loading site script $ac_site_file" >&6;}
+ sed 's/^/| /' "$ac_site_file" >&5
+ . "$ac_site_file" \
+ || { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "failed to load site script $ac_site_file
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+done
+
+if test -r "$cache_file"; then
+ # Some versions of bash will fail to source /dev/null (special files
+ # actually), so we avoid doing that. DJGPP emulates it as a regular file.
+ if test /dev/null != "$cache_file" && test -f "$cache_file"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: loading cache $cache_file" >&5
+$as_echo "$as_me: loading cache $cache_file" >&6;}
+ case $cache_file in
+ [\\/]* | ?:[\\/]* ) . "$cache_file";;
+ *) . "./$cache_file";;
+ esac
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating cache $cache_file" >&5
+$as_echo "$as_me: creating cache $cache_file" >&6;}
+ >$cache_file
+fi
+
+# Check that the precious variables saved in the cache have kept the same
+# value.
+ac_cache_corrupted=false
+for ac_var in $ac_precious_vars; do
+ eval ac_old_set=\$ac_cv_env_${ac_var}_set
+ eval ac_new_set=\$ac_env_${ac_var}_set
+ eval ac_old_val=\$ac_cv_env_${ac_var}_value
+ eval ac_new_val=\$ac_env_${ac_var}_value
+ case $ac_old_set,$ac_new_set in
+ set,)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was set to \`$ac_old_val' in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,set)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' was not set in the previous run" >&5
+$as_echo "$as_me: error: \`$ac_var' was not set in the previous run" >&2;}
+ ac_cache_corrupted=: ;;
+ ,);;
+ *)
+ if test "x$ac_old_val" != "x$ac_new_val"; then
+ # differences in whitespace do not lead to failure.
+ ac_old_val_w=`echo x $ac_old_val`
+ ac_new_val_w=`echo x $ac_new_val`
+ if test "$ac_old_val_w" != "$ac_new_val_w"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: \`$ac_var' has changed since the previous run:" >&5
+$as_echo "$as_me: error: \`$ac_var' has changed since the previous run:" >&2;}
+ ac_cache_corrupted=:
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&5
+$as_echo "$as_me: warning: ignoring whitespace changes in \`$ac_var' since the previous run:" >&2;}
+ eval $ac_var=\$ac_old_val
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: former value: \`$ac_old_val'" >&5
+$as_echo "$as_me: former value: \`$ac_old_val'" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: current value: \`$ac_new_val'" >&5
+$as_echo "$as_me: current value: \`$ac_new_val'" >&2;}
+ fi;;
+ esac
+ # Pass precious variables to config.status.
+ if test "$ac_new_set" = set; then
+ case $ac_new_val in
+ *\'*) ac_arg=$ac_var=`$as_echo "$ac_new_val" | sed "s/'/'\\\\\\\\''/g"` ;;
+ *) ac_arg=$ac_var=$ac_new_val ;;
+ esac
+ case " $ac_configure_args " in
+ *" '$ac_arg' "*) ;; # Avoid dups. Use of quotes ensures accuracy.
+ *) as_fn_append ac_configure_args " '$ac_arg'" ;;
+ esac
+ fi
+done
+if $ac_cache_corrupted; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+ { $as_echo "$as_me:${as_lineno-$LINENO}: error: changes in the environment can compromise the build" >&5
+$as_echo "$as_me: error: changes in the environment can compromise the build" >&2;}
+ as_fn_error $? "run \`make distclean' and/or \`rm $cache_file' and start over" "$LINENO" 5
+fi
+## -------------------- ##
+## Main body of script. ##
+## -------------------- ##
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+
+
+# First check for Contiki build to quit configure before any other test
+
+# Check whether --with-contiki was given.
+if test "${with_contiki+set}" = set; then :
+ withval=$with_contiki; cp -p Makefile.contiki Makefile
+ cp -p config.h.contiki config.h
+ { $as_echo "$as_me:${as_lineno-$LINENO}: Contiki build prepared" >&5
+$as_echo "$as_me: Contiki build prepared" >&6;}
+ exit 0
+fi
+
+
+# Checks for programs.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether ${MAKE-make} sets \$(MAKE)" >&5
+$as_echo_n "checking whether ${MAKE-make} sets \$(MAKE)... " >&6; }
+set x ${MAKE-make}
+ac_make=`$as_echo "$2" | sed 's/+/p/g; s/[^a-zA-Z0-9_]/_/g'`
+if eval \${ac_cv_prog_make_${ac_make}_set+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat >conftest.make <<\_ACEOF
+SHELL = /bin/sh
+all:
+ @echo '@@@%%%=$(MAKE)=@@@%%%'
+_ACEOF
+# GNU make sometimes prints "make[1]: Entering ...", which would confuse us.
+case `${MAKE-make} -f conftest.make 2>/dev/null` in
+ *@@@%%%=?*=@@@%%%*)
+ eval ac_cv_prog_make_${ac_make}_set=yes;;
+ *)
+ eval ac_cv_prog_make_${ac_make}_set=no;;
+esac
+rm -f conftest.make
+fi
+if eval test \$ac_cv_prog_make_${ac_make}_set = yes; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+ SET_MAKE=
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+ SET_MAKE="MAKE=${MAKE-make}"
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}gcc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_CC"; then
+ ac_ct_CC=$CC
+ # Extract the first word of "gcc", so it can be a program name with args.
+set dummy gcc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="gcc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+else
+ CC="$ac_cv_prog_CC"
+fi
+
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}cc", so it can be a program name with args.
+set dummy ${ac_tool_prefix}cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="${ac_tool_prefix}cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ fi
+fi
+if test -z "$CC"; then
+ # Extract the first word of "cc", so it can be a program name with args.
+set dummy cc; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+ ac_prog_rejected=no
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ if test "$as_dir/$ac_word$ac_exec_ext" = "/usr/ucb/cc"; then
+ ac_prog_rejected=yes
+ continue
+ fi
+ ac_cv_prog_CC="cc"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+if test $ac_prog_rejected = yes; then
+ # We found a bogon in the path, so make sure we never use it.
+ set dummy $ac_cv_prog_CC
+ shift
+ if test $# != 0; then
+ # We chose a different compiler from the bogus one.
+ # However, it has the same basename, so the bogon will be chosen
+ # first if we set CC to just the basename; use the full file name.
+ shift
+ ac_cv_prog_CC="$as_dir/$ac_word${1+' '}$@"
+ fi
+fi
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$CC"; then
+ if test -n "$ac_tool_prefix"; then
+ for ac_prog in cl.exe
+ do
+ # Extract the first word of "$ac_tool_prefix$ac_prog", so it can be a program name with args.
+set dummy $ac_tool_prefix$ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$CC"; then
+ ac_cv_prog_CC="$CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_CC="$ac_tool_prefix$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+CC=$ac_cv_prog_CC
+if test -n "$CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $CC" >&5
+$as_echo "$CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$CC" && break
+ done
+fi
+if test -z "$CC"; then
+ ac_ct_CC=$CC
+ for ac_prog in cl.exe
+do
+ # Extract the first word of "$ac_prog", so it can be a program name with args.
+set dummy $ac_prog; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_CC+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_CC"; then
+ ac_cv_prog_ac_ct_CC="$ac_ct_CC" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_CC="$ac_prog"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_CC=$ac_cv_prog_ac_ct_CC
+if test -n "$ac_ct_CC"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_CC" >&5
+$as_echo "$ac_ct_CC" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+ test -n "$ac_ct_CC" && break
+done
+
+ if test "x$ac_ct_CC" = x; then
+ CC=""
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ CC=$ac_ct_CC
+ fi
+fi
+
+fi
+
+
+test -z "$CC" && { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "no acceptable C compiler found in \$PATH
+See \`config.log' for more details" "$LINENO" 5; }
+
+# Provide some information about the compiler.
+$as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler version" >&5
+set X $ac_compile
+ac_compiler=$2
+for ac_option in --version -v -V -qversion; do
+ { { ac_try="$ac_compiler $ac_option >&5"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compiler $ac_option >&5") 2>conftest.err
+ ac_status=$?
+ if test -s conftest.err; then
+ sed '10a\
+... rest of stderr output deleted ...
+ 10q' conftest.err >conftest.er1
+ cat conftest.er1 >&5
+ fi
+ rm -f conftest.er1 conftest.err
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+done
+
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files a.out a.out.dSYM a.exe b.out"
+# Try to create an executable without -o first, disregard a.out.
+# It will help us diagnose broken compilers, and finding out an intuition
+# of exeext.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the C compiler works" >&5
+$as_echo_n "checking whether the C compiler works... " >&6; }
+ac_link_default=`$as_echo "$ac_link" | sed 's/ -o *conftest[^ ]*//'`
+
+# The possible output files:
+ac_files="a.out conftest.exe conftest a.exe a_out.exe b.out conftest.*"
+
+ac_rmfiles=
+for ac_file in $ac_files
+do
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ * ) ac_rmfiles="$ac_rmfiles $ac_file";;
+ esac
+done
+rm -f $ac_rmfiles
+
+if { { ac_try="$ac_link_default"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link_default") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # Autoconf-2.13 could set the ac_cv_exeext variable to `no'.
+# So ignore a value of `no', otherwise this would lead to `EXEEXT = no'
+# in a Makefile. We should not override ac_cv_exeext if it was cached,
+# so that the user can short-circuit this test for compilers unknown to
+# Autoconf.
+for ac_file in $ac_files ''
+do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj )
+ ;;
+ [ab].out )
+ # We found the default executable, but exeext='' is most
+ # certainly right.
+ break;;
+ *.* )
+ if test "${ac_cv_exeext+set}" = set && test "$ac_cv_exeext" != no;
+ then :; else
+ ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ fi
+ # We set ac_cv_exeext here because the later test for it is not
+ # safe: cross compilers may not add the suffix if given an `-o'
+ # argument, so we may need to know it at that point already.
+ # Even if this section looks crufty: it has the advantage of
+ # actually working.
+ break;;
+ * )
+ break;;
+ esac
+done
+test "$ac_cv_exeext" = no && ac_cv_exeext=
+
+else
+ ac_file=''
+fi
+if test -z "$ac_file"; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+$as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "C compiler cannot create executables
+See \`config.log' for more details" "$LINENO" 5; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+$as_echo "yes" >&6; }
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for C compiler default output file name" >&5
+$as_echo_n "checking for C compiler default output file name... " >&6; }
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_file" >&5
+$as_echo "$ac_file" >&6; }
+ac_exeext=$ac_cv_exeext
+
+rm -f -r a.out a.out.dSYM a.exe conftest$ac_cv_exeext b.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of executables" >&5
+$as_echo_n "checking for suffix of executables... " >&6; }
+if { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ # If both `conftest.exe' and `conftest' are `present' (well, observable)
+# catch `conftest.exe'. For instance with Cygwin, `ls conftest' will
+# work properly (i.e., refer to `conftest.exe'), while it won't with
+# `rm'.
+for ac_file in conftest.exe conftest conftest.*; do
+ test -f "$ac_file" || continue
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM | *.o | *.obj ) ;;
+ *.* ) ac_cv_exeext=`expr "$ac_file" : '[^.]*\(\..*\)'`
+ break;;
+ * ) break;;
+ esac
+done
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of executables: cannot compile and link
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest conftest$ac_cv_exeext
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_exeext" >&5
+$as_echo "$ac_cv_exeext" >&6; }
+
+rm -f conftest.$ac_ext
+EXEEXT=$ac_cv_exeext
+ac_exeext=$EXEEXT
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdio.h>
+int
+main ()
+{
+FILE *f = fopen ("conftest.out", "w");
+ return ferror (f) || fclose (f) != 0;
+
+ ;
+ return 0;
+}
+_ACEOF
+ac_clean_files="$ac_clean_files conftest.out"
+# Check that the compiler produces executables we can run. If not, either
+# the compiler is broken, or we cross compile.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are cross compiling" >&5
+$as_echo_n "checking whether we are cross compiling... " >&6; }
+if test "$cross_compiling" != yes; then
+ { { ac_try="$ac_link"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_link") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }
+ if { ac_try='./conftest$ac_cv_exeext'
+ { { case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_try") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; }; then
+ cross_compiling=no
+ else
+ if test "$cross_compiling" = maybe; then
+ cross_compiling=yes
+ else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot run C compiled programs.
+If you meant to cross compile, use \`--host'.
+See \`config.log' for more details" "$LINENO" 5; }
+ fi
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $cross_compiling" >&5
+$as_echo "$cross_compiling" >&6; }
+
+rm -f conftest.$ac_ext conftest$ac_cv_exeext conftest.out
+ac_clean_files=$ac_clean_files_save
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for suffix of object files" >&5
+$as_echo_n "checking for suffix of object files... " >&6; }
+if ${ac_cv_objext+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+rm -f conftest.o conftest.obj
+if { { ac_try="$ac_compile"
+case "(($ac_try" in
+ *\"* | *\`* | *\\*) ac_try_echo=\$ac_try;;
+ *) ac_try_echo=$ac_try;;
+esac
+eval ac_try_echo="\"\$as_me:${as_lineno-$LINENO}: $ac_try_echo\""
+$as_echo "$ac_try_echo"; } >&5
+ (eval "$ac_compile") 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; then :
+ for ac_file in conftest.o conftest.obj conftest.*; do
+ test -f "$ac_file" || continue;
+ case $ac_file in
+ *.$ac_ext | *.xcoff | *.tds | *.d | *.pdb | *.xSYM | *.bb | *.bbg | *.map | *.inf | *.dSYM ) ;;
+ *) ac_cv_objext=`expr "$ac_file" : '.*\.\(.*\)'`
+ break;;
+ esac
+done
+else
+ $as_echo "$as_me: failed program was:" >&5
+sed 's/^/| /' conftest.$ac_ext >&5
+
+{ { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "cannot compute suffix of object files: cannot compile
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+rm -f conftest.$ac_cv_objext conftest.$ac_ext
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_objext" >&5
+$as_echo "$ac_cv_objext" >&6; }
+OBJEXT=$ac_cv_objext
+ac_objext=$OBJEXT
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether we are using the GNU C compiler" >&5
+$as_echo_n "checking whether we are using the GNU C compiler... " >&6; }
+if ${ac_cv_c_compiler_gnu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+#ifndef __GNUC__
+ choke me
+#endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_compiler_gnu=yes
+else
+ ac_compiler_gnu=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ac_cv_c_compiler_gnu=$ac_compiler_gnu
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_compiler_gnu" >&5
+$as_echo "$ac_cv_c_compiler_gnu" >&6; }
+if test $ac_compiler_gnu = yes; then
+ GCC=yes
+else
+ GCC=
+fi
+ac_test_CFLAGS=${CFLAGS+set}
+ac_save_CFLAGS=$CFLAGS
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether $CC accepts -g" >&5
+$as_echo_n "checking whether $CC accepts -g... " >&6; }
+if ${ac_cv_prog_cc_g+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_save_c_werror_flag=$ac_c_werror_flag
+ ac_c_werror_flag=yes
+ ac_cv_prog_cc_g=no
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+else
+ CFLAGS=""
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+else
+ ac_c_werror_flag=$ac_save_c_werror_flag
+ CFLAGS="-g"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_g=yes
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ ac_c_werror_flag=$ac_save_c_werror_flag
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_g" >&5
+$as_echo "$ac_cv_prog_cc_g" >&6; }
+if test "$ac_test_CFLAGS" = set; then
+ CFLAGS=$ac_save_CFLAGS
+elif test $ac_cv_prog_cc_g = yes; then
+ if test "$GCC" = yes; then
+ CFLAGS="-g -O2"
+ else
+ CFLAGS="-g"
+ fi
+else
+ if test "$GCC" = yes; then
+ CFLAGS="-O2"
+ else
+ CFLAGS=
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $CC option to accept ISO C89" >&5
+$as_echo_n "checking for $CC option to accept ISO C89... " >&6; }
+if ${ac_cv_prog_cc_c89+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_prog_cc_c89=no
+ac_save_CC=$CC
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdarg.h>
+#include <stdio.h>
+struct stat;
+/* Most of the following tests are stolen from RCS 5.7's src/conf.sh. */
+struct buf { int x; };
+FILE * (*rcsopen) (struct buf *, struct stat *, int);
+static char *e (p, i)
+ char **p;
+ int i;
+{
+ return p[i];
+}
+static char *f (char * (*g) (char **, int), char **p, ...)
+{
+ char *s;
+ va_list v;
+ va_start (v,p);
+ s = g (p, va_arg (v,int));
+ va_end (v);
+ return s;
+}
+
+/* OSF 4.0 Compaq cc is some sort of almost-ANSI by default. It has
+ function prototypes and stuff, but not '\xHH' hex character constants.
+ These don't provoke an error unfortunately, instead are silently treated
+ as 'x'. The following induces an error, until -std is added to get
+ proper ANSI mode. Curiously '\x00'!='x' always comes out true, for an
+ array size at least. It's necessary to write '\x00'==0 to get something
+ that's true only with -std. */
+int osf4_cc_array ['\x00' == 0 ? 1 : -1];
+
+/* IBM C 6 for AIX is almost-ANSI by default, but it replaces macro parameters
+ inside strings and character constants. */
+#define FOO(x) 'x'
+int xlc6_cc_array[FOO(a) == 'x' ? 1 : -1];
+
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};
+int pairnames (int, char **, FILE *(*)(struct buf *, struct stat *, int), int, int);
+int argc;
+char **argv;
+int
+main ()
+{
+return f (e, argv, 0) != argv[0] || f (e, argv, 1) != argv[1];
+ ;
+ return 0;
+}
+_ACEOF
+for ac_arg in '' -qlanglvl=extc89 -qlanglvl=ansi -std \
+ -Ae "-Aa -D_HPUX_SOURCE" "-Xc -D__EXTENSIONS__"
+do
+ CC="$ac_save_CC $ac_arg"
+ if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_prog_cc_c89=$ac_arg
+fi
+rm -f core conftest.err conftest.$ac_objext
+ test "x$ac_cv_prog_cc_c89" != "xno" && break
+done
+rm -f conftest.$ac_ext
+CC=$ac_save_CC
+
+fi
+# AC_CACHE_VAL
+case "x$ac_cv_prog_cc_c89" in
+ x)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: none needed" >&5
+$as_echo "none needed" >&6; } ;;
+ xno)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: unsupported" >&5
+$as_echo "unsupported" >&6; } ;;
+ *)
+ CC="$CC $ac_cv_prog_cc_c89"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_prog_cc_c89" >&5
+$as_echo "$ac_cv_prog_cc_c89" >&6; } ;;
+esac
+if test "x$ac_cv_prog_cc_c89" != xno; then :
+
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+if test -n "$ac_tool_prefix"; then
+ # Extract the first word of "${ac_tool_prefix}ranlib", so it can be a program name with args.
+set dummy ${ac_tool_prefix}ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$RANLIB"; then
+ ac_cv_prog_RANLIB="$RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_RANLIB="${ac_tool_prefix}ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+RANLIB=$ac_cv_prog_RANLIB
+if test -n "$RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $RANLIB" >&5
+$as_echo "$RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+fi
+if test -z "$ac_cv_prog_RANLIB"; then
+ ac_ct_RANLIB=$RANLIB
+ # Extract the first word of "ranlib", so it can be a program name with args.
+set dummy ranlib; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_prog_ac_ct_RANLIB+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -n "$ac_ct_RANLIB"; then
+ ac_cv_prog_ac_ct_RANLIB="$ac_ct_RANLIB" # Let the user override the test.
+else
+as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_prog_ac_ct_RANLIB="ranlib"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+fi
+fi
+ac_ct_RANLIB=$ac_cv_prog_ac_ct_RANLIB
+if test -n "$ac_ct_RANLIB"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_ct_RANLIB" >&5
+$as_echo "$ac_ct_RANLIB" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+ if test "x$ac_ct_RANLIB" = x; then
+ RANLIB=":"
+ else
+ case $cross_compiling:$ac_tool_warned in
+yes:)
+{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: using cross tools not prefixed with host triplet" >&5
+$as_echo "$as_me: WARNING: using cross tools not prefixed with host triplet" >&2;}
+ac_tool_warned=yes ;;
+esac
+ RANLIB=$ac_ct_RANLIB
+ fi
+else
+ RANLIB="$ac_cv_prog_RANLIB"
+fi
+
+# Extract the first word of "doxygen", so it can be a program name with args.
+set dummy doxygen; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_DOXYGEN+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $DOXYGEN in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_DOXYGEN="$DOXYGEN" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_DOXYGEN="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_DOXYGEN" && ac_cv_path_DOXYGEN=":"
+ ;;
+esac
+fi
+DOXYGEN=$ac_cv_path_DOXYGEN
+if test -n "$DOXYGEN"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $DOXYGEN" >&5
+$as_echo "$DOXYGEN" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+# Extract the first word of "etags", so it can be a program name with args.
+set dummy etags; ac_word=$2
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for $ac_word" >&5
+$as_echo_n "checking for $ac_word... " >&6; }
+if ${ac_cv_path_ETAGS+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ case $ETAGS in
+ [\\/]* | ?:[\\/]*)
+ ac_cv_path_ETAGS="$ETAGS" # Let the user override the test with a path.
+ ;;
+ *)
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ if as_fn_executable_p "$as_dir/$ac_word$ac_exec_ext"; then
+ ac_cv_path_ETAGS="$as_dir/$ac_word$ac_exec_ext"
+ $as_echo "$as_me:${as_lineno-$LINENO}: found $as_dir/$ac_word$ac_exec_ext" >&5
+ break 2
+ fi
+done
+ done
+IFS=$as_save_IFS
+
+ test -z "$ac_cv_path_ETAGS" && ac_cv_path_ETAGS="/bin/false"
+ ;;
+esac
+fi
+ETAGS=$ac_cv_path_ETAGS
+if test -n "$ETAGS"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ETAGS" >&5
+$as_echo "$ETAGS" >&6; }
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
+
+
+
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking how to run the C preprocessor" >&5
+$as_echo_n "checking how to run the C preprocessor... " >&6; }
+# On Suns, sometimes $CPP names a directory.
+if test -n "$CPP" && test -d "$CPP"; then
+ CPP=
+fi
+if test -z "$CPP"; then
+ if ${ac_cv_prog_CPP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ # Double quotes because CPP needs to be expanded
+ for CPP in "$CC -E" "$CC -E -traditional-cpp" "/lib/cpp"
+ do
+ ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+ break
+fi
+
+ done
+ ac_cv_prog_CPP=$CPP
+
+fi
+ CPP=$ac_cv_prog_CPP
+else
+ ac_cv_prog_CPP=$CPP
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $CPP" >&5
+$as_echo "$CPP" >&6; }
+ac_preproc_ok=false
+for ac_c_preproc_warn_flag in '' yes
+do
+ # Use a header file that comes with gcc, so configuring glibc
+ # with a fresh cross-compiler works.
+ # Prefer <limits.h> to <assert.h> if __STDC__ is defined, since
+ # <limits.h> exists even on freestanding compilers.
+ # On the NeXT, cc -E runs the code through the compiler's parser,
+ # not just through cpp. "Syntax error" is here to catch this case.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifdef __STDC__
+# include <limits.h>
+#else
+# include <assert.h>
+#endif
+ Syntax error
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+
+else
+ # Broken: fails on valid input.
+continue
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+ # OK, works on sane cases. Now check whether nonexistent headers
+ # can be detected and how.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ac_nonexistent.h>
+_ACEOF
+if ac_fn_c_try_cpp "$LINENO"; then :
+ # Broken: success on invalid input.
+continue
+else
+ # Passes both tests.
+ac_preproc_ok=:
+break
+fi
+rm -f conftest.err conftest.i conftest.$ac_ext
+
+done
+# Because of `break', _AC_PREPROC_IFELSE's cleaning code was skipped.
+rm -f conftest.i conftest.err conftest.$ac_ext
+if $ac_preproc_ok; then :
+
+else
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error $? "C preprocessor \"$CPP\" fails sanity check
+See \`config.log' for more details" "$LINENO" 5; }
+fi
+
+ac_ext=c
+ac_cpp='$CPP $CPPFLAGS'
+ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5'
+ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5'
+ac_compiler_gnu=$ac_cv_c_compiler_gnu
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
+$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
+if ${ac_cv_path_GREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test -z "$GREP"; then
+ ac_path_GREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in grep ggrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_GREP" || continue
+# Check for GNU ac_path_GREP and select it if it is found.
+ # Check for GNU $ac_path_GREP
+case `"$ac_path_GREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'GREP' >> "conftest.nl"
+ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_GREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_GREP="$ac_path_GREP"
+ ac_path_GREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_GREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_GREP"; then
+ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_GREP=$GREP
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
+$as_echo "$ac_cv_path_GREP" >&6; }
+ GREP="$ac_cv_path_GREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
+$as_echo_n "checking for egrep... " >&6; }
+if ${ac_cv_path_EGREP+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
+ then ac_cv_path_EGREP="$GREP -E"
+ else
+ if test -z "$EGREP"; then
+ ac_path_EGREP_found=false
+ # Loop through the user's path and test for each of PROGNAME-LIST
+ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ for ac_prog in egrep; do
+ for ac_exec_ext in '' $ac_executable_extensions; do
+ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
+ as_fn_executable_p "$ac_path_EGREP" || continue
+# Check for GNU ac_path_EGREP and select it if it is found.
+ # Check for GNU $ac_path_EGREP
+case `"$ac_path_EGREP" --version 2>&1` in
+*GNU*)
+ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
+*)
+ ac_count=0
+ $as_echo_n 0123456789 >"conftest.in"
+ while :
+ do
+ cat "conftest.in" "conftest.in" >"conftest.tmp"
+ mv "conftest.tmp" "conftest.in"
+ cp "conftest.in" "conftest.nl"
+ $as_echo 'EGREP' >> "conftest.nl"
+ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
+ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
+ as_fn_arith $ac_count + 1 && ac_count=$as_val
+ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
+ # Best one so far, save it but keep looking for a better one
+ ac_cv_path_EGREP="$ac_path_EGREP"
+ ac_path_EGREP_max=$ac_count
+ fi
+ # 10*(2^10) chars as input seems more than enough
+ test $ac_count -gt 10 && break
+ done
+ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
+esac
+
+ $ac_path_EGREP_found && break 3
+ done
+ done
+ done
+IFS=$as_save_IFS
+ if test -z "$ac_cv_path_EGREP"; then
+ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
+ fi
+else
+ ac_cv_path_EGREP=$EGREP
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
+$as_echo "$ac_cv_path_EGREP" >&6; }
+ EGREP="$ac_cv_path_EGREP"
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ANSI C header files" >&5
+$as_echo_n "checking for ANSI C header files... " >&6; }
+if ${ac_cv_header_stdc+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <float.h>
+
+int
+main ()
+{
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_header_stdc=yes
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+
+if test $ac_cv_header_stdc = yes; then
+ # SunOS 4.x string.h does not declare mem*, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <string.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "memchr" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # ISC 2.0.2 stdlib.h does not declare free, contrary to ANSI.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <stdlib.h>
+
+_ACEOF
+if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
+ $EGREP "free" >/dev/null 2>&1; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f conftest*
+
+fi
+
+if test $ac_cv_header_stdc = yes; then
+ # /bin/cc in Irix-4.0.5 gets non-ANSI ctype macros unless using -ansi.
+ if test "$cross_compiling" = yes; then :
+ :
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <ctype.h>
+#include <stdlib.h>
+#if ((' ' & 0x0FF) == 0x020)
+# define ISLOWER(c) ('a' <= (c) && (c) <= 'z')
+# define TOUPPER(c) (ISLOWER(c) ? 'A' + ((c) - 'a') : (c))
+#else
+# define ISLOWER(c) \
+ (('a' <= (c) && (c) <= 'i') \
+ || ('j' <= (c) && (c) <= 'r') \
+ || ('s' <= (c) && (c) <= 'z'))
+# define TOUPPER(c) (ISLOWER(c) ? ((c) | 0x40) : (c))
+#endif
+
+#define XOR(e, f) (((e) && !(f)) || (!(e) && (f)))
+int
+main ()
+{
+ int i;
+ for (i = 0; i < 256; i++)
+ if (XOR (islower (i), ISLOWER (i))
+ || toupper (i) != TOUPPER (i))
+ return 2;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+
+else
+ ac_cv_header_stdc=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_header_stdc" >&5
+$as_echo "$ac_cv_header_stdc" >&6; }
+if test $ac_cv_header_stdc = yes; then
+
+$as_echo "#define STDC_HEADERS 1" >>confdefs.h
+
+fi
+
+# On IRIX 5.3, sys/types and inttypes.h are conflicting.
+for ac_header in sys/types.h sys/stat.h stdlib.h string.h memory.h strings.h \
+ inttypes.h stdint.h unistd.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_compile "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default
+"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether byte ordering is bigendian" >&5
+$as_echo_n "checking whether byte ordering is bigendian... " >&6; }
+if ${ac_cv_c_bigendian+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_cv_c_bigendian=unknown
+ # See if we're dealing with a universal compiler.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#ifndef __APPLE_CC__
+ not a universal capable compiler
+ #endif
+ typedef int dummy;
+
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+
+ # Check for potential -arch flags. It is not universal unless
+ # there are at least two -arch flags with different values.
+ ac_arch=
+ ac_prev=
+ for ac_word in $CC $CFLAGS $CPPFLAGS $LDFLAGS; do
+ if test -n "$ac_prev"; then
+ case $ac_word in
+ i?86 | x86_64 | ppc | ppc64)
+ if test -z "$ac_arch" || test "$ac_arch" = "$ac_word"; then
+ ac_arch=$ac_word
+ else
+ ac_cv_c_bigendian=universal
+ break
+ fi
+ ;;
+ esac
+ ac_prev=
+ elif test "x$ac_word" = "x-arch"; then
+ ac_prev=arch
+ fi
+ done
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if sys/param.h defines the BYTE_ORDER macro.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if ! (defined BYTE_ORDER && defined BIG_ENDIAN \
+ && defined LITTLE_ENDIAN && BYTE_ORDER && BIG_ENDIAN \
+ && LITTLE_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <sys/types.h>
+ #include <sys/param.h>
+
+int
+main ()
+{
+#if BYTE_ORDER != BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # See if <limits.h> defines _LITTLE_ENDIAN or _BIG_ENDIAN (e.g., Solaris).
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#if ! (defined _LITTLE_ENDIAN || defined _BIG_ENDIAN)
+ bogus endian macros
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ # It does; now see whether it defined to _BIG_ENDIAN or not.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <limits.h>
+
+int
+main ()
+{
+#ifndef _BIG_ENDIAN
+ not big endian
+ #endif
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_cv_c_bigendian=yes
+else
+ ac_cv_c_bigendian=no
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ fi
+ if test $ac_cv_c_bigendian = unknown; then
+ # Compile a test program.
+ if test "$cross_compiling" = yes; then :
+ # Try to guess by grepping values from an object file.
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+short int ascii_mm[] =
+ { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
+ short int ascii_ii[] =
+ { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
+ int use_ascii (int i) {
+ return ascii_mm[i] + ascii_ii[i];
+ }
+ short int ebcdic_ii[] =
+ { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
+ short int ebcdic_mm[] =
+ { 0xC2C9, 0xC785, 0x95C4, 0x8981, 0x95E2, 0xA8E2, 0 };
+ int use_ebcdic (int i) {
+ return ebcdic_mm[i] + ebcdic_ii[i];
+ }
+ extern int foo;
+
+int
+main ()
+{
+return use_ascii (foo) == use_ebcdic (foo);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ if grep BIGenDianSyS conftest.$ac_objext >/dev/null; then
+ ac_cv_c_bigendian=yes
+ fi
+ if grep LiTTleEnDian conftest.$ac_objext >/dev/null ; then
+ if test "$ac_cv_c_bigendian" = unknown; then
+ ac_cv_c_bigendian=no
+ else
+ # finding both strings is unlikely to happen, but who knows?
+ ac_cv_c_bigendian=unknown
+ fi
+ fi
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+$ac_includes_default
+int
+main ()
+{
+
+ /* Are we little or big endian? From Harbison&Steele. */
+ union
+ {
+ long int l;
+ char c[sizeof (long int)];
+ } u;
+ u.l = 1;
+ return u.c[sizeof (long int) - 1] == 1;
+
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_c_bigendian=no
+else
+ ac_cv_c_bigendian=yes
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+ fi
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_c_bigendian" >&5
+$as_echo "$ac_cv_c_bigendian" >&6; }
+ case $ac_cv_c_bigendian in #(
+ yes)
+ $as_echo "#define WORDS_BIGENDIAN 1" >>confdefs.h
+;; #(
+ no)
+ ;; #(
+ universal)
+
+$as_echo "#define AC_APPLE_UNIVERSAL_BUILD 1" >>confdefs.h
+
+ ;; #(
+ *)
+ as_fn_error $? "unknown endianness
+ presetting ac_cv_c_bigendian=no (or yes) will help" "$LINENO" 5 ;;
+ esac
+
+
+# Checks for libraries.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for coap_new_pdu in -lcoap" >&5
+$as_echo_n "checking for coap_new_pdu in -lcoap... " >&6; }
+if ${ac_cv_lib_coap_coap_new_pdu+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_lib_save_LIBS=$LIBS
+LIBS="-lcoap $LIBS"
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char coap_new_pdu ();
+int
+main ()
+{
+return coap_new_pdu ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_lib_coap_coap_new_pdu=yes
+else
+ ac_cv_lib_coap_coap_new_pdu=no
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+LIBS=$ac_check_lib_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_coap_coap_new_pdu" >&5
+$as_echo "$ac_cv_lib_coap_coap_new_pdu" >&6; }
+if test "x$ac_cv_lib_coap_coap_new_pdu" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_LIBCOAP 1
+_ACEOF
+
+ LIBS="-lcoap $LIBS"
+
+fi
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing gethostbyname" >&5
+$as_echo_n "checking for library containing gethostbyname... " >&6; }
+if ${ac_cv_search_gethostbyname+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gethostbyname ();
+int
+main ()
+{
+return gethostbyname ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' nsl; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_gethostbyname=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_gethostbyname+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_gethostbyname+:} false; then :
+
+else
+ ac_cv_search_gethostbyname=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_gethostbyname" >&5
+$as_echo "$ac_cv_search_gethostbyname" >&6; }
+ac_res=$ac_cv_search_gethostbyname
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for library containing socket" >&5
+$as_echo_n "checking for library containing socket... " >&6; }
+if ${ac_cv_search_socket+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_func_search_save_LIBS=$LIBS
+cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char socket ();
+int
+main ()
+{
+return socket ();
+ ;
+ return 0;
+}
+_ACEOF
+for ac_lib in '' socket; do
+ if test -z "$ac_lib"; then
+ ac_res="none required"
+ else
+ ac_res=-l$ac_lib
+ LIBS="-l$ac_lib $ac_func_search_save_LIBS"
+ fi
+ if ac_fn_c_try_link "$LINENO"; then :
+ ac_cv_search_socket=$ac_res
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext
+ if ${ac_cv_search_socket+:} false; then :
+ break
+fi
+done
+if ${ac_cv_search_socket+:} false; then :
+
+else
+ ac_cv_search_socket=no
+fi
+rm conftest.$ac_ext
+LIBS=$ac_func_search_save_LIBS
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_search_socket" >&5
+$as_echo "$ac_cv_search_socket" >&6; }
+ac_res=$ac_cv_search_socket
+if test "$ac_res" != no; then :
+ test "$ac_res" = "none required" || LIBS="$ac_res $LIBS"
+
+fi
+
+
+# configuration options that may change compile flags
+
+# Check whether --with-debug was given.
+if test "${with_debug+set}" = set; then :
+ withval=$with_debug; CPPFLAGS="${CPPFLAGS} -DNDEBUG"
+fi
+
+
+
+# Check whether --with-async was given.
+if test "${with_async+set}" = set; then :
+ withval=$with_async; CPPFLAGS="${CPPFLAGS} -DWITHOUT_ASYNC"
+fi
+
+
+
+# Check whether --with-block was given.
+if test "${with_block+set}" = set; then :
+ withval=$with_block; CPPFLAGS="${CPPFLAGS} -DWITHOUT_BLOCK"
+fi
+
+
+
+# Check whether --with-observe was given.
+if test "${with_observe+set}" = set; then :
+ withval=$with_observe; CPPFLAGS="${CPPFLAGS} -DWITHOUT_OBSERVE"
+fi
+
+
+
+# Check whether --with-query-filter was given.
+if test "${with_query_filter+set}" = set; then :
+ withval=$with_query_filter; CPPFLAGS="${CPPFLAGS} -DWITHOUT_QUERY_FILTER"
+fi
+
+
+
+# Check whether --with-tests was given.
+if test "${with_tests+set}" = set; then :
+ withval=$with_tests; TESTS="tests"
+fi
+
+
+
+# Check whether --with-shared was given.
+if test "${with_shared+set}" = set; then :
+ withval=$with_shared; BUILD_SO="BUILD_SO=1"
+fi
+
+
+# disambiguate between autoconf generated setups and contiki / lwip setups
+# which use explicit config.h.* files
+CPPFLAGS="${CPPFLAGS} -DWITH_POSIX"
+
+# Checks for header files.
+for ac_header in assert.h arpa/inet.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/socket.h sys/time.h time.h unistd.h sys/unistd.h syslog.h
+do :
+ as_ac_Header=`$as_echo "ac_cv_header_$ac_header" | $as_tr_sh`
+ac_fn_c_check_header_mongrel "$LINENO" "$ac_header" "$as_ac_Header" "$ac_includes_default"
+if eval test \"x\$"$as_ac_Header"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_header" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+
+done
+
+
+# Checks for typedefs, structures, and compiler characteristics.
+ac_fn_c_check_type "$LINENO" "size_t" "ac_cv_type_size_t" "$ac_includes_default"
+if test "x$ac_cv_type_size_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define size_t unsigned int
+_ACEOF
+
+fi
+
+ac_fn_c_check_type "$LINENO" "ssize_t" "ac_cv_type_ssize_t" "$ac_includes_default"
+if test "x$ac_cv_type_ssize_t" = xyes; then :
+
+else
+
+cat >>confdefs.h <<_ACEOF
+#define ssize_t int
+_ACEOF
+
+fi
+
+
+# Checks for library functions.
+for ac_header in stdlib.h
+do :
+ ac_fn_c_check_header_mongrel "$LINENO" "stdlib.h" "ac_cv_header_stdlib_h" "$ac_includes_default"
+if test "x$ac_cv_header_stdlib_h" = xyes; then :
+ cat >>confdefs.h <<_ACEOF
+#define HAVE_STDLIB_H 1
+_ACEOF
+
+fi
+
+done
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GNU libc compatible malloc" >&5
+$as_echo_n "checking for GNU libc compatible malloc... " >&6; }
+if ${ac_cv_func_malloc_0_nonnull+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if test "$cross_compiling" = yes; then :
+ ac_cv_func_malloc_0_nonnull=no
+else
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#if defined STDC_HEADERS || defined HAVE_STDLIB_H
+# include <stdlib.h>
+#else
+char *malloc ();
+#endif
+
+int
+main ()
+{
+return ! malloc (0);
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_run "$LINENO"; then :
+ ac_cv_func_malloc_0_nonnull=yes
+else
+ ac_cv_func_malloc_0_nonnull=no
+fi
+rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
+ conftest.$ac_objext conftest.beam conftest.$ac_ext
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_func_malloc_0_nonnull" >&5
+$as_echo "$ac_cv_func_malloc_0_nonnull" >&6; }
+if test $ac_cv_func_malloc_0_nonnull = yes; then :
+
+$as_echo "#define HAVE_MALLOC 1" >>confdefs.h
+
+else
+ $as_echo "#define HAVE_MALLOC 0" >>confdefs.h
+
+ case " $LIBOBJS " in
+ *" malloc.$ac_objext "* ) ;;
+ *) LIBOBJS="$LIBOBJS malloc.$ac_objext"
+ ;;
+esac
+
+
+$as_echo "#define malloc rpl_malloc" >>confdefs.h
+
+fi
+
+
+for ac_func in memset select socket strcasecmp strrchr getaddrinfo strnlen
+do :
+ as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
+ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
+if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
+ cat >>confdefs.h <<_ACEOF
+#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
+_ACEOF
+
+fi
+done
+
+
+
+
+
+ac_config_headers="$ac_config_headers config.h"
+
+
+ac_config_files="$ac_config_files Makefile doc/Makefile doc/Doxyfile examples/Makefile tests/Makefile"
+
+cat >confcache <<\_ACEOF
+# This file is a shell script that caches the results of configure
+# tests run on this system so they can be shared between configure
+# scripts and configure runs, see configure's option --config-cache.
+# It is not useful on other systems. If it contains results you don't
+# want to keep, you may remove or edit it.
+#
+# config.status only pays attention to the cache file if you give it
+# the --recheck option to rerun configure.
+#
+# `ac_cv_env_foo' variables (set or unset) will be overridden when
+# loading this file, other *unset* `ac_cv_foo' will be assigned the
+# following values.
+
+_ACEOF
+
+# The following way of writing the cache mishandles newlines in values,
+# but we know of no workaround that is simple, portable, and efficient.
+# So, we kill variables containing newlines.
+# Ultrix sh set writes to stderr and can't be redirected directly,
+# and sets the high bit in the cache file unless we assign to the vars.
+(
+ for ac_var in `(set) 2>&1 | sed -n 's/^\([a-zA-Z_][a-zA-Z0-9_]*\)=.*/\1/p'`; do
+ eval ac_val=\$$ac_var
+ case $ac_val in #(
+ *${as_nl}*)
+ case $ac_var in #(
+ *_cv_*) { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: cache variable $ac_var contains a newline" >&5
+$as_echo "$as_me: WARNING: cache variable $ac_var contains a newline" >&2;} ;;
+ esac
+ case $ac_var in #(
+ _ | IFS | as_nl) ;; #(
+ BASH_ARGV | BASH_SOURCE) eval $ac_var= ;; #(
+ *) { eval $ac_var=; unset $ac_var;} ;;
+ esac ;;
+ esac
+ done
+
+ (set) 2>&1 |
+ case $as_nl`(ac_space=' '; set) 2>&1` in #(
+ *${as_nl}ac_space=\ *)
+ # `set' does not quote correctly, so add quotes: double-quote
+ # substitution turns \\\\ into \\, and sed turns \\ into \.
+ sed -n \
+ "s/'/'\\\\''/g;
+ s/^\\([_$as_cr_alnum]*_cv_[_$as_cr_alnum]*\\)=\\(.*\\)/\\1='\\2'/p"
+ ;; #(
+ *)
+ # `set' quotes correctly as required by POSIX, so do not add quotes.
+ sed -n "/^[_$as_cr_alnum]*_cv_[_$as_cr_alnum]*=/p"
+ ;;
+ esac |
+ sort
+) |
+ sed '
+ /^ac_cv_env_/b end
+ t clear
+ :clear
+ s/^\([^=]*\)=\(.*[{}].*\)$/test "${\1+set}" = set || &/
+ t end
+ s/^\([^=]*\)=\(.*\)$/\1=${\1=\2}/
+ :end' >>confcache
+if diff "$cache_file" confcache >/dev/null 2>&1; then :; else
+ if test -w "$cache_file"; then
+ if test "x$cache_file" != "x/dev/null"; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: updating cache $cache_file" >&5
+$as_echo "$as_me: updating cache $cache_file" >&6;}
+ if test ! -f "$cache_file" || test -h "$cache_file"; then
+ cat confcache >"$cache_file"
+ else
+ case $cache_file in #(
+ */* | ?:*)
+ mv -f confcache "$cache_file"$$ &&
+ mv -f "$cache_file"$$ "$cache_file" ;; #(
+ *)
+ mv -f confcache "$cache_file" ;;
+ esac
+ fi
+ fi
+ else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: not updating unwritable cache $cache_file" >&5
+$as_echo "$as_me: not updating unwritable cache $cache_file" >&6;}
+ fi
+fi
+rm -f confcache
+
+test "x$prefix" = xNONE && prefix=$ac_default_prefix
+# Let make expand exec_prefix.
+test "x$exec_prefix" = xNONE && exec_prefix='${prefix}'
+
+DEFS=-DHAVE_CONFIG_H
+
+ac_libobjs=
+ac_ltlibobjs=
+U=
+for ac_i in : $LIBOBJS; do test "x$ac_i" = x: && continue
+ # 1. Remove the extension, and $U if already installed.
+ ac_script='s/\$U\././;s/\.o$//;s/\.obj$//'
+ ac_i=`$as_echo "$ac_i" | sed "$ac_script"`
+ # 2. Prepend LIBOBJDIR. When used with automake>=1.10 LIBOBJDIR
+ # will be set to the directory where LIBOBJS objects are built.
+ as_fn_append ac_libobjs " \${LIBOBJDIR}$ac_i\$U.$ac_objext"
+ as_fn_append ac_ltlibobjs " \${LIBOBJDIR}$ac_i"'$U.lo'
+done
+LIBOBJS=$ac_libobjs
+
+LTLIBOBJS=$ac_ltlibobjs
+
+
+
+
+: "${CONFIG_STATUS=./config.status}"
+ac_write_fail=0
+ac_clean_files_save=$ac_clean_files
+ac_clean_files="$ac_clean_files $CONFIG_STATUS"
+{ $as_echo "$as_me:${as_lineno-$LINENO}: creating $CONFIG_STATUS" >&5
+$as_echo "$as_me: creating $CONFIG_STATUS" >&6;}
+as_write_fail=0
+cat >$CONFIG_STATUS <<_ASEOF || as_write_fail=1
+#! $SHELL
+# Generated by $as_me.
+# Run this file to recreate the current configuration.
+# Compiler output produced by configure, useful for debugging
+# configure, is in config.log if it exists.
+
+debug=false
+ac_cs_recheck=false
+ac_cs_silent=false
+
+SHELL=\${CONFIG_SHELL-$SHELL}
+export SHELL
+_ASEOF
+cat >>$CONFIG_STATUS <<\_ASEOF || as_write_fail=1
+## -------------------- ##
+## M4sh Initialization. ##
+## -------------------- ##
+
+# Be more Bourne compatible
+DUALCASE=1; export DUALCASE # for MKS sh
+if test -n "${ZSH_VERSION+set}" && (emulate sh) >/dev/null 2>&1; then :
+ emulate sh
+ NULLCMD=:
+ # Pre-4.2 versions of Zsh do word splitting on ${1+"$@"}, which
+ # is contrary to our usage. Disable this feature.
+ alias -g '${1+"$@"}'='"$@"'
+ setopt NO_GLOB_SUBST
+else
+ case `(set -o) 2>/dev/null` in #(
+ *posix*) :
+ set -o posix ;; #(
+ *) :
+ ;;
+esac
+fi
+
+
+as_nl='
+'
+export as_nl
+# Printing a long string crashes Solaris 7 /usr/bin/printf.
+as_echo='\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\'
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo
+as_echo=$as_echo$as_echo$as_echo$as_echo$as_echo$as_echo
+# Prefer a ksh shell builtin over an external printf program on Solaris,
+# but without wasting forks for bash or zsh.
+if test -z "$BASH_VERSION$ZSH_VERSION" \
+ && (test "X`print -r -- $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='print -r --'
+ as_echo_n='print -rn --'
+elif (test "X`printf %s $as_echo`" = "X$as_echo") 2>/dev/null; then
+ as_echo='printf %s\n'
+ as_echo_n='printf %s'
+else
+ if test "X`(/usr/ucb/echo -n -n $as_echo) 2>/dev/null`" = "X-n $as_echo"; then
+ as_echo_body='eval /usr/ucb/echo -n "$1$as_nl"'
+ as_echo_n='/usr/ucb/echo -n'
+ else
+ as_echo_body='eval expr "X$1" : "X\\(.*\\)"'
+ as_echo_n_body='eval
+ arg=$1;
+ case $arg in #(
+ *"$as_nl"*)
+ expr "X$arg" : "X\\(.*\\)$as_nl";
+ arg=`expr "X$arg" : ".*$as_nl\\(.*\\)"`;;
+ esac;
+ expr "X$arg" : "X\\(.*\\)" | tr -d "$as_nl"
+ '
+ export as_echo_n_body
+ as_echo_n='sh -c $as_echo_n_body as_echo'
+ fi
+ export as_echo_body
+ as_echo='sh -c $as_echo_body as_echo'
+fi
+
+# The user is always right.
+if test "${PATH_SEPARATOR+set}" != set; then
+ PATH_SEPARATOR=:
+ (PATH='/bin;/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 && {
+ (PATH='/bin:/bin'; FPATH=$PATH; sh -c :) >/dev/null 2>&1 ||
+ PATH_SEPARATOR=';'
+ }
+fi
+
+
+# IFS
+# We need space, tab and new line, in precisely that order. Quoting is
+# there to prevent editors from complaining about space-tab.
+# (If _AS_PATH_WALK were called with IFS unset, it would disable word
+# splitting by setting IFS to empty value.)
+IFS=" "" $as_nl"
+
+# Find who we are. Look in the path if we contain no directory separator.
+as_myself=
+case $0 in #((
+ *[\\/]* ) as_myself=$0 ;;
+ *) as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
+for as_dir in $PATH
+do
+ IFS=$as_save_IFS
+ test -z "$as_dir" && as_dir=.
+ test -r "$as_dir/$0" && as_myself=$as_dir/$0 && break
+ done
+IFS=$as_save_IFS
+
+ ;;
+esac
+# We did not find ourselves, most probably we were run as `sh COMMAND'
+# in which case we are not to be found in the path.
+if test "x$as_myself" = x; then
+ as_myself=$0
+fi
+if test ! -f "$as_myself"; then
+ $as_echo "$as_myself: error: cannot find myself; rerun with an absolute file name" >&2
+ exit 1
+fi
+
+# Unset variables that we do not need and which cause bugs (e.g. in
+# pre-3.0 UWIN ksh). But do not cause bugs in bash 2.01; the "|| exit 1"
+# suppresses any "Segmentation fault" message there. '((' could
+# trigger a bug in pdksh 5.2.14.
+for as_var in BASH_ENV ENV MAIL MAILPATH
+do eval test x\${$as_var+set} = xset \
+ && ( (unset $as_var) || exit 1) >/dev/null 2>&1 && unset $as_var || :
+done
+PS1='$ '
+PS2='> '
+PS4='+ '
+
+# NLS nuisances.
+LC_ALL=C
+export LC_ALL
+LANGUAGE=C
+export LANGUAGE
+
+# CDPATH.
+(unset CDPATH) >/dev/null 2>&1 && unset CDPATH
+
+
+# as_fn_error STATUS ERROR [LINENO LOG_FD]
+# ----------------------------------------
+# Output "`basename $0`: error: ERROR" to stderr. If LINENO and LOG_FD are
+# provided, also output the error to LOG_FD, referencing LINENO. Then exit the
+# script with STATUS, using 1 if that was 0.
+as_fn_error ()
+{
+ as_status=$1; test $as_status -eq 0 && as_status=1
+ if test "$4"; then
+ as_lineno=${as_lineno-"$3"} as_lineno_stack=as_lineno_stack=$as_lineno_stack
+ $as_echo "$as_me:${as_lineno-$LINENO}: error: $2" >&$4
+ fi
+ $as_echo "$as_me: error: $2" >&2
+ as_fn_exit $as_status
+} # as_fn_error
+
+
+# as_fn_set_status STATUS
+# -----------------------
+# Set $? to STATUS, without forking.
+as_fn_set_status ()
+{
+ return $1
+} # as_fn_set_status
+
+# as_fn_exit STATUS
+# -----------------
+# Exit the shell with STATUS, even in a "trap 0" or "set -e" context.
+as_fn_exit ()
+{
+ set +e
+ as_fn_set_status $1
+ exit $1
+} # as_fn_exit
+
+# as_fn_unset VAR
+# ---------------
+# Portably unset VAR.
+as_fn_unset ()
+{
+ { eval $1=; unset $1;}
+}
+as_unset=as_fn_unset
+# as_fn_append VAR VALUE
+# ----------------------
+# Append the text in VALUE to the end of the definition contained in VAR. Take
+# advantage of any shell optimizations that allow amortized linear growth over
+# repeated appends, instead of the typical quadratic growth present in naive
+# implementations.
+if (eval "as_var=1; as_var+=2; test x\$as_var = x12") 2>/dev/null; then :
+ eval 'as_fn_append ()
+ {
+ eval $1+=\$2
+ }'
+else
+ as_fn_append ()
+ {
+ eval $1=\$$1\$2
+ }
+fi # as_fn_append
+
+# as_fn_arith ARG...
+# ------------------
+# Perform arithmetic evaluation on the ARGs, and store the result in the
+# global $as_val. Take advantage of shells that can avoid forks. The arguments
+# must be portable across $(()) and expr.
+if (eval "test \$(( 1 + 1 )) = 2") 2>/dev/null; then :
+ eval 'as_fn_arith ()
+ {
+ as_val=$(( $* ))
+ }'
+else
+ as_fn_arith ()
+ {
+ as_val=`expr "$@" || test $? -eq 1`
+ }
+fi # as_fn_arith
+
+
+if expr a : '\(a\)' >/dev/null 2>&1 &&
+ test "X`expr 00001 : '.*\(...\)'`" = X001; then
+ as_expr=expr
+else
+ as_expr=false
+fi
+
+if (basename -- /) >/dev/null 2>&1 && test "X`basename -- / 2>&1`" = "X/"; then
+ as_basename=basename
+else
+ as_basename=false
+fi
+
+if (as_dir=`dirname -- /` && test "X$as_dir" = X/) >/dev/null 2>&1; then
+ as_dirname=dirname
+else
+ as_dirname=false
+fi
+
+as_me=`$as_basename -- "$0" ||
+$as_expr X/"$0" : '.*/\([^/][^/]*\)/*$' \| \
+ X"$0" : 'X\(//\)$' \| \
+ X"$0" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X/"$0" |
+ sed '/^.*\/\([^/][^/]*\)\/*$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\/\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+
+# Avoid depending upon Character Ranges.
+as_cr_letters='abcdefghijklmnopqrstuvwxyz'
+as_cr_LETTERS='ABCDEFGHIJKLMNOPQRSTUVWXYZ'
+as_cr_Letters=$as_cr_letters$as_cr_LETTERS
+as_cr_digits='0123456789'
+as_cr_alnum=$as_cr_Letters$as_cr_digits
+
+ECHO_C= ECHO_N= ECHO_T=
+case `echo -n x` in #(((((
+-n*)
+ case `echo 'xy\c'` in
+ *c*) ECHO_T=' ';; # ECHO_T is single tab character.
+ xy) ECHO_C='\c';;
+ *) echo `echo ksh88 bug on AIX 6.1` > /dev/null
+ ECHO_T=' ';;
+ esac;;
+*)
+ ECHO_N='-n';;
+esac
+
+rm -f conf$$ conf$$.exe conf$$.file
+if test -d conf$$.dir; then
+ rm -f conf$$.dir/conf$$.file
+else
+ rm -f conf$$.dir
+ mkdir conf$$.dir 2>/dev/null
+fi
+if (echo >conf$$.file) 2>/dev/null; then
+ if ln -s conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s='ln -s'
+ # ... but there are two gotchas:
+ # 1) On MSYS, both `ln -s file dir' and `ln file dir' fail.
+ # 2) DJGPP < 2.04 has no symlinks; `ln -s' creates a wrapper executable.
+ # In both cases, we have to default to `cp -pR'.
+ ln -s conf$$.file conf$$.dir 2>/dev/null && test ! -f conf$$.exe ||
+ as_ln_s='cp -pR'
+ elif ln conf$$.file conf$$ 2>/dev/null; then
+ as_ln_s=ln
+ else
+ as_ln_s='cp -pR'
+ fi
+else
+ as_ln_s='cp -pR'
+fi
+rm -f conf$$ conf$$.exe conf$$.dir/conf$$.file conf$$.file
+rmdir conf$$.dir 2>/dev/null
+
+
+# as_fn_mkdir_p
+# -------------
+# Create "$as_dir" as a directory, including parents if necessary.
+as_fn_mkdir_p ()
+{
+
+ case $as_dir in #(
+ -*) as_dir=./$as_dir;;
+ esac
+ test -d "$as_dir" || eval $as_mkdir_p || {
+ as_dirs=
+ while :; do
+ case $as_dir in #(
+ *\'*) as_qdir=`$as_echo "$as_dir" | sed "s/'/'\\\\\\\\''/g"`;; #'(
+ *) as_qdir=$as_dir;;
+ esac
+ as_dirs="'$as_qdir' $as_dirs"
+ as_dir=`$as_dirname -- "$as_dir" ||
+$as_expr X"$as_dir" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$as_dir" : 'X\(//\)[^/]' \| \
+ X"$as_dir" : 'X\(//\)$' \| \
+ X"$as_dir" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$as_dir" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ test -d "$as_dir" && break
+ done
+ test -z "$as_dirs" || eval "mkdir $as_dirs"
+ } || test -d "$as_dir" || as_fn_error $? "cannot create directory $as_dir"
+
+
+} # as_fn_mkdir_p
+if mkdir -p . 2>/dev/null; then
+ as_mkdir_p='mkdir -p "$as_dir"'
+else
+ test -d ./-p && rmdir ./-p
+ as_mkdir_p=false
+fi
+
+
+# as_fn_executable_p FILE
+# -----------------------
+# Test if FILE is an executable regular file.
+as_fn_executable_p ()
+{
+ test -f "$1" && test -x "$1"
+} # as_fn_executable_p
+as_test_x='test -x'
+as_executable_p=as_fn_executable_p
+
+# Sed expression to map a string onto a valid CPP name.
+as_tr_cpp="eval sed 'y%*$as_cr_letters%P$as_cr_LETTERS%;s%[^_$as_cr_alnum]%_%g'"
+
+# Sed expression to map a string onto a valid variable name.
+as_tr_sh="eval sed 'y%*+%pp%;s%[^_$as_cr_alnum]%_%g'"
+
+
+exec 6>&1
+## ----------------------------------- ##
+## Main body of $CONFIG_STATUS script. ##
+## ----------------------------------- ##
+_ASEOF
+test $as_write_fail = 0 && chmod +x $CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# Save the log message, to keep $0 and so on meaningful, and to
+# report actual input values of CONFIG_FILES etc. instead of their
+# values after options handling.
+ac_log="
+This file was extended by libcoap $as_me 4.1.1, which was
+generated by GNU Autoconf 2.69. Invocation command line was
+
+ CONFIG_FILES = $CONFIG_FILES
+ CONFIG_HEADERS = $CONFIG_HEADERS
+ CONFIG_LINKS = $CONFIG_LINKS
+ CONFIG_COMMANDS = $CONFIG_COMMANDS
+ $ $0 $@
+
+on `(hostname || uname -n) 2>/dev/null | sed 1q`
+"
+
+_ACEOF
+
+case $ac_config_files in *"
+"*) set x $ac_config_files; shift; ac_config_files=$*;;
+esac
+
+case $ac_config_headers in *"
+"*) set x $ac_config_headers; shift; ac_config_headers=$*;;
+esac
+
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+# Files that config.status was made for.
+config_files="$ac_config_files"
+config_headers="$ac_config_headers"
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ac_cs_usage="\
+\`$as_me' instantiates files and other configuration actions
+from templates according to the current configuration. Unless the files
+and actions are specified as TAGs, all are instantiated by default.
+
+Usage: $0 [OPTION]... [TAG]...
+
+ -h, --help print this help, then exit
+ -V, --version print version number and configuration settings, then exit
+ --config print configuration, then exit
+ -q, --quiet, --silent
+ do not print progress messages
+ -d, --debug don't remove temporary files
+ --recheck update $as_me by reconfiguring in the same conditions
+ --file=FILE[:TEMPLATE]
+ instantiate the configuration file FILE
+ --header=FILE[:TEMPLATE]
+ instantiate the configuration header FILE
+
+Configuration files:
+$config_files
+
+Configuration headers:
+$config_headers
+
+Report bugs to the package provider."
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_cs_config="`$as_echo "$ac_configure_args" | sed 's/^ //; s/[\\""\`\$]/\\\\&/g'`"
+ac_cs_version="\\
+libcoap config.status 4.1.1
+configured by $0, generated by GNU Autoconf 2.69,
+ with options \\"\$ac_cs_config\\"
+
+Copyright (C) 2012 Free Software Foundation, Inc.
+This config.status script is free software; the Free Software Foundation
+gives unlimited permission to copy, distribute and modify it."
+
+ac_pwd='$ac_pwd'
+srcdir='$srcdir'
+test -n "\$AWK" || AWK=awk
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# The default lists apply if the user does not specify any file.
+ac_need_defaults=:
+while test $# != 0
+do
+ case $1 in
+ --*=?*)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=`expr "X$1" : 'X[^=]*=\(.*\)'`
+ ac_shift=:
+ ;;
+ --*=)
+ ac_option=`expr "X$1" : 'X\([^=]*\)='`
+ ac_optarg=
+ ac_shift=:
+ ;;
+ *)
+ ac_option=$1
+ ac_optarg=$2
+ ac_shift=shift
+ ;;
+ esac
+
+ case $ac_option in
+ # Handling of the options.
+ -recheck | --recheck | --rechec | --reche | --rech | --rec | --re | --r)
+ ac_cs_recheck=: ;;
+ --version | --versio | --versi | --vers | --ver | --ve | --v | -V )
+ $as_echo "$ac_cs_version"; exit ;;
+ --config | --confi | --conf | --con | --co | --c )
+ $as_echo "$ac_cs_config"; exit ;;
+ --debug | --debu | --deb | --de | --d | -d )
+ debug=: ;;
+ --file | --fil | --fi | --f )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ '') as_fn_error $? "missing file argument" ;;
+ esac
+ as_fn_append CONFIG_FILES " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --header | --heade | --head | --hea )
+ $ac_shift
+ case $ac_optarg in
+ *\'*) ac_optarg=`$as_echo "$ac_optarg" | sed "s/'/'\\\\\\\\''/g"` ;;
+ esac
+ as_fn_append CONFIG_HEADERS " '$ac_optarg'"
+ ac_need_defaults=false;;
+ --he | --h)
+ # Conflict between --help and --header
+ as_fn_error $? "ambiguous option: \`$1'
+Try \`$0 --help' for more information.";;
+ --help | --hel | -h )
+ $as_echo "$ac_cs_usage"; exit ;;
+ -q | -quiet | --quiet | --quie | --qui | --qu | --q \
+ | -silent | --silent | --silen | --sile | --sil | --si | --s)
+ ac_cs_silent=: ;;
+
+ # This is an error.
+ -*) as_fn_error $? "unrecognized option: \`$1'
+Try \`$0 --help' for more information." ;;
+
+ *) as_fn_append ac_config_targets " $1"
+ ac_need_defaults=false ;;
+
+ esac
+ shift
+done
+
+ac_configure_extra_args=
+
+if $ac_cs_silent; then
+ exec 6>/dev/null
+ ac_configure_extra_args="$ac_configure_extra_args --silent"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+if \$ac_cs_recheck; then
+ set X $SHELL '$0' $ac_configure_args \$ac_configure_extra_args --no-create --no-recursion
+ shift
+ \$as_echo "running CONFIG_SHELL=$SHELL \$*" >&6
+ CONFIG_SHELL='$SHELL'
+ export CONFIG_SHELL
+ exec "\$@"
+fi
+
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+exec 5>>config.log
+{
+ echo
+ sed 'h;s/./-/g;s/^.../## /;s/...$/ ##/;p;x;p;x' <<_ASBOX
+## Running $as_me. ##
+_ASBOX
+ $as_echo "$ac_log"
+} >&5
+
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+
+# Handling of arguments.
+for ac_config_target in $ac_config_targets
+do
+ case $ac_config_target in
+ "config.h") CONFIG_HEADERS="$CONFIG_HEADERS config.h" ;;
+ "Makefile") CONFIG_FILES="$CONFIG_FILES Makefile" ;;
+ "doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
+ "doc/Doxyfile") CONFIG_FILES="$CONFIG_FILES doc/Doxyfile" ;;
+ "examples/Makefile") CONFIG_FILES="$CONFIG_FILES examples/Makefile" ;;
+ "tests/Makefile") CONFIG_FILES="$CONFIG_FILES tests/Makefile" ;;
+
+ *) as_fn_error $? "invalid argument: \`$ac_config_target'" "$LINENO" 5;;
+ esac
+done
+
+
+# If the user did not use the arguments to specify the items to instantiate,
+# then the envvar interface is used. Set only those that are not.
+# We use the long form for the default assignment because of an extremely
+# bizarre bug on SunOS 4.1.3.
+if $ac_need_defaults; then
+ test "${CONFIG_FILES+set}" = set || CONFIG_FILES=$config_files
+ test "${CONFIG_HEADERS+set}" = set || CONFIG_HEADERS=$config_headers
+fi
+
+# Have a temporary directory for convenience. Make it in the build tree
+# simply because there is no reason against having it here, and in addition,
+# creating and moving files from /tmp can sometimes cause problems.
+# Hook for its removal unless debugging.
+# Note that there is a small window in which the directory will not be cleaned:
+# after its creation but before its name has been assigned to `$tmp'.
+$debug ||
+{
+ tmp= ac_tmp=
+ trap 'exit_status=$?
+ : "${ac_tmp:=$tmp}"
+ { test ! -d "$ac_tmp" || rm -fr "$ac_tmp"; } && exit $exit_status
+' 0
+ trap 'as_fn_exit 1' 1 2 13 15
+}
+# Create a (secure) tmp directory for tmp files.
+
+{
+ tmp=`(umask 077 && mktemp -d "./confXXXXXX") 2>/dev/null` &&
+ test -d "$tmp"
+} ||
+{
+ tmp=./conf$$-$RANDOM
+ (umask 077 && mkdir "$tmp")
+} || as_fn_error $? "cannot create a temporary directory in ." "$LINENO" 5
+ac_tmp=$tmp
+
+# Set up the scripts for CONFIG_FILES section.
+# No need to generate them if there are no CONFIG_FILES.
+# This happens for instance with `./config.status config.h'.
+if test -n "$CONFIG_FILES"; then
+
+
+ac_cr=`echo X | tr X '\015'`
+# On cygwin, bash can eat \r inside `` if the user requested igncr.
+# But we know of no other shell where ac_cr would be empty at this
+# point, so we can use a bashism as a fallback.
+if test "x$ac_cr" = x; then
+ eval ac_cr=\$\'\\r\'
+fi
+ac_cs_awk_cr=`$AWK 'BEGIN { print "a\rb" }' </dev/null 2>/dev/null`
+if test "$ac_cs_awk_cr" = "a${ac_cr}b"; then
+ ac_cs_awk_cr='\\r'
+else
+ ac_cs_awk_cr=$ac_cr
+fi
+
+echo 'BEGIN {' >"$ac_tmp/subs1.awk" &&
+_ACEOF
+
+
+{
+ echo "cat >conf$$subs.awk <<_ACEOF" &&
+ echo "$ac_subst_vars" | sed 's/.*/&!$&$ac_delim/' &&
+ echo "_ACEOF"
+} >conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ac_delim_num=`echo "$ac_subst_vars" | grep -c '^'`
+ac_delim='%!_!# '
+for ac_last_try in false false false false false :; do
+ . ./conf$$subs.sh ||
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+
+ ac_delim_n=`sed -n "s/.*$ac_delim\$/X/p" conf$$subs.awk | grep -c X`
+ if test $ac_delim_n = $ac_delim_num; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_STATUS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+rm -f conf$$subs.sh
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+cat >>"\$ac_tmp/subs1.awk" <<\\_ACAWK &&
+_ACEOF
+sed -n '
+h
+s/^/S["/; s/!.*/"]=/
+p
+g
+s/^[^!]*!//
+:repl
+t repl
+s/'"$ac_delim"'$//
+t delim
+:nl
+h
+s/\(.\{148\}\)..*/\1/
+t more1
+s/["\\]/\\&/g; s/^/"/; s/$/\\n"\\/
+p
+n
+b repl
+:more1
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t nl
+:delim
+h
+s/\(.\{148\}\)..*/\1/
+t more2
+s/["\\]/\\&/g; s/^/"/; s/$/"/
+p
+b
+:more2
+s/["\\]/\\&/g; s/^/"/; s/$/"\\/
+p
+g
+s/.\{148\}//
+t delim
+' <conf$$subs.awk | sed '
+/^[^""]/{
+ N
+ s/\n//
+}
+' >>$CONFIG_STATUS || ac_write_fail=1
+rm -f conf$$subs.awk
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+_ACAWK
+cat >>"\$ac_tmp/subs1.awk" <<_ACAWK &&
+ for (key in S) S_is_set[key] = 1
+ FS = "\a"
+
+}
+{
+ line = $ 0
+ nfields = split(line, field, "@")
+ substed = 0
+ len = length(field[1])
+ for (i = 2; i < nfields; i++) {
+ key = field[i]
+ keylen = length(key)
+ if (S_is_set[key]) {
+ value = S[key]
+ line = substr(line, 1, len) "" value "" substr(line, len + keylen + 3)
+ len += length(value) + length(field[++i])
+ substed = 1
+ } else
+ len += 1 + keylen
+ }
+
+ print line
+}
+
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+if sed "s/$ac_cr//" < /dev/null > /dev/null 2>&1; then
+ sed "s/$ac_cr\$//; s/$ac_cr/$ac_cs_awk_cr/g"
+else
+ cat
+fi < "$ac_tmp/subs1.awk" > "$ac_tmp/subs.awk" \
+ || as_fn_error $? "could not setup config files machinery" "$LINENO" 5
+_ACEOF
+
+# VPATH may cause trouble with some makes, so we remove sole $(srcdir),
+# ${srcdir} and @srcdir@ entries from VPATH if srcdir is ".", strip leading and
+# trailing colons and then remove the whole line if VPATH becomes empty
+# (actually we leave an empty line to preserve line numbers).
+if test "x$srcdir" = x.; then
+ ac_vpsub='/^[ ]*VPATH[ ]*=[ ]*/{
+h
+s///
+s/^/:/
+s/[ ]*$/:/
+s/:\$(srcdir):/:/g
+s/:\${srcdir}:/:/g
+s/:@srcdir@:/:/g
+s/^:*//
+s/:*$//
+x
+s/\(=[ ]*\).*/\1/
+G
+s/\n//
+s/^[^=]*=[ ]*$//
+}'
+fi
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+fi # test -n "$CONFIG_FILES"
+
+# Set up the scripts for CONFIG_HEADERS section.
+# No need to generate them if there are no CONFIG_HEADERS.
+# This happens for instance with `./config.status Makefile'.
+if test -n "$CONFIG_HEADERS"; then
+cat >"$ac_tmp/defines.awk" <<\_ACAWK ||
+BEGIN {
+_ACEOF
+
+# Transform confdefs.h into an awk script `defines.awk', embedded as
+# here-document in config.status, that substitutes the proper values into
+# config.h.in to produce config.h.
+
+# Create a delimiter string that does not exist in confdefs.h, to ease
+# handling of long lines.
+ac_delim='%!_!# '
+for ac_last_try in false false :; do
+ ac_tt=`sed -n "/$ac_delim/p" confdefs.h`
+ if test -z "$ac_tt"; then
+ break
+ elif $ac_last_try; then
+ as_fn_error $? "could not make $CONFIG_HEADERS" "$LINENO" 5
+ else
+ ac_delim="$ac_delim!$ac_delim _$ac_delim!! "
+ fi
+done
+
+# For the awk script, D is an array of macro values keyed by name,
+# likewise P contains macro parameters if any. Preserve backslash
+# newline sequences.
+
+ac_word_re=[_$as_cr_Letters][_$as_cr_alnum]*
+sed -n '
+s/.\{148\}/&'"$ac_delim"'/g
+t rset
+:rset
+s/^[ ]*#[ ]*define[ ][ ]*/ /
+t def
+d
+:def
+s/\\$//
+t bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3"/p
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2"/p
+d
+:bsnl
+s/["\\]/\\&/g
+s/^ \('"$ac_word_re"'\)\(([^()]*)\)[ ]*\(.*\)/P["\1"]="\2"\
+D["\1"]=" \3\\\\\\n"\\/p
+t cont
+s/^ \('"$ac_word_re"'\)[ ]*\(.*\)/D["\1"]=" \2\\\\\\n"\\/p
+t cont
+d
+:cont
+n
+s/.\{148\}/&'"$ac_delim"'/g
+t clear
+:clear
+s/\\$//
+t bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/"/p
+d
+:bsnlc
+s/["\\]/\\&/g; s/^/"/; s/$/\\\\\\n"\\/p
+b cont
+' <confdefs.h | sed '
+s/'"$ac_delim"'/"\\\
+"/g' >>$CONFIG_STATUS || ac_write_fail=1
+
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ for (key in D) D_is_set[key] = 1
+ FS = "\a"
+}
+/^[\t ]*#[\t ]*(define|undef)[\t ]+$ac_word_re([\t (]|\$)/ {
+ line = \$ 0
+ split(line, arg, " ")
+ if (arg[1] == "#") {
+ defundef = arg[2]
+ mac1 = arg[3]
+ } else {
+ defundef = substr(arg[1], 2)
+ mac1 = arg[2]
+ }
+ split(mac1, mac2, "(") #)
+ macro = mac2[1]
+ prefix = substr(line, 1, index(line, defundef) - 1)
+ if (D_is_set[macro]) {
+ # Preserve the white space surrounding the "#".
+ print prefix "define", macro P[macro] D[macro]
+ next
+ } else {
+ # Replace #undef with comments. This is necessary, for example,
+ # in the case of _POSIX_SOURCE, which is predefined and required
+ # on some systems where configure will not decide to define it.
+ if (defundef == "undef") {
+ print "/*", prefix defundef, macro, "*/"
+ next
+ }
+ }
+}
+{ print }
+_ACAWK
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+ as_fn_error $? "could not setup config headers machinery" "$LINENO" 5
+fi # test -n "$CONFIG_HEADERS"
+
+
+eval set X " :F $CONFIG_FILES :H $CONFIG_HEADERS "
+shift
+for ac_tag
+do
+ case $ac_tag in
+ :[FHLC]) ac_mode=$ac_tag; continue;;
+ esac
+ case $ac_mode$ac_tag in
+ :[FHL]*:*);;
+ :L* | :C*:*) as_fn_error $? "invalid tag \`$ac_tag'" "$LINENO" 5;;
+ :[FH]-) ac_tag=-:-;;
+ :[FH]*) ac_tag=$ac_tag:$ac_tag.in;;
+ esac
+ ac_save_IFS=$IFS
+ IFS=:
+ set x $ac_tag
+ IFS=$ac_save_IFS
+ shift
+ ac_file=$1
+ shift
+
+ case $ac_mode in
+ :L) ac_source=$1;;
+ :[FH])
+ ac_file_inputs=
+ for ac_f
+ do
+ case $ac_f in
+ -) ac_f="$ac_tmp/stdin";;
+ *) # Look for the file first in the build tree, then in the source tree
+ # (if the path is not absolute). The absolute path cannot be DOS-style,
+ # because $ac_f cannot contain `:'.
+ test -f "$ac_f" ||
+ case $ac_f in
+ [\\/$]*) false;;
+ *) test -f "$srcdir/$ac_f" && ac_f="$srcdir/$ac_f";;
+ esac ||
+ as_fn_error 1 "cannot find input file: \`$ac_f'" "$LINENO" 5;;
+ esac
+ case $ac_f in *\'*) ac_f=`$as_echo "$ac_f" | sed "s/'/'\\\\\\\\''/g"`;; esac
+ as_fn_append ac_file_inputs " '$ac_f'"
+ done
+
+ # Let's still pretend it is `configure' which instantiates (i.e., don't
+ # use $as_me), people would be surprised to read:
+ # /* config.h. Generated by config.status. */
+ configure_input='Generated from '`
+ $as_echo "$*" | sed 's|^[^:]*/||;s|:[^:]*/|, |g'
+ `' by configure.'
+ if test x"$ac_file" != x-; then
+ configure_input="$ac_file. $configure_input"
+ { $as_echo "$as_me:${as_lineno-$LINENO}: creating $ac_file" >&5
+$as_echo "$as_me: creating $ac_file" >&6;}
+ fi
+ # Neutralize special characters interpreted by sed in replacement strings.
+ case $configure_input in #(
+ *\&* | *\|* | *\\* )
+ ac_sed_conf_input=`$as_echo "$configure_input" |
+ sed 's/[\\\\&|]/\\\\&/g'`;; #(
+ *) ac_sed_conf_input=$configure_input;;
+ esac
+
+ case $ac_tag in
+ *:-:* | *:-) cat >"$ac_tmp/stdin" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5 ;;
+ esac
+ ;;
+ esac
+
+ ac_dir=`$as_dirname -- "$ac_file" ||
+$as_expr X"$ac_file" : 'X\(.*[^/]\)//*[^/][^/]*/*$' \| \
+ X"$ac_file" : 'X\(//\)[^/]' \| \
+ X"$ac_file" : 'X\(//\)$' \| \
+ X"$ac_file" : 'X\(/\)' \| . 2>/dev/null ||
+$as_echo X"$ac_file" |
+ sed '/^X\(.*[^/]\)\/\/*[^/][^/]*\/*$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)[^/].*/{
+ s//\1/
+ q
+ }
+ /^X\(\/\/\)$/{
+ s//\1/
+ q
+ }
+ /^X\(\/\).*/{
+ s//\1/
+ q
+ }
+ s/.*/./; q'`
+ as_dir="$ac_dir"; as_fn_mkdir_p
+ ac_builddir=.
+
+case "$ac_dir" in
+.) ac_dir_suffix= ac_top_builddir_sub=. ac_top_build_prefix= ;;
+*)
+ ac_dir_suffix=/`$as_echo "$ac_dir" | sed 's|^\.[\\/]||'`
+ # A ".." for each directory in $ac_dir_suffix.
+ ac_top_builddir_sub=`$as_echo "$ac_dir_suffix" | sed 's|/[^\\/]*|/..|g;s|/||'`
+ case $ac_top_builddir_sub in
+ "") ac_top_builddir_sub=. ac_top_build_prefix= ;;
+ *) ac_top_build_prefix=$ac_top_builddir_sub/ ;;
+ esac ;;
+esac
+ac_abs_top_builddir=$ac_pwd
+ac_abs_builddir=$ac_pwd$ac_dir_suffix
+# for backward compatibility:
+ac_top_builddir=$ac_top_build_prefix
+
+case $srcdir in
+ .) # We are building in place.
+ ac_srcdir=.
+ ac_top_srcdir=$ac_top_builddir_sub
+ ac_abs_top_srcdir=$ac_pwd ;;
+ [\\/]* | ?:[\\/]* ) # Absolute name.
+ ac_srcdir=$srcdir$ac_dir_suffix;
+ ac_top_srcdir=$srcdir
+ ac_abs_top_srcdir=$srcdir ;;
+ *) # Relative name.
+ ac_srcdir=$ac_top_build_prefix$srcdir$ac_dir_suffix
+ ac_top_srcdir=$ac_top_build_prefix$srcdir
+ ac_abs_top_srcdir=$ac_pwd/$srcdir ;;
+esac
+ac_abs_srcdir=$ac_abs_top_srcdir$ac_dir_suffix
+
+
+ case $ac_mode in
+ :F)
+ #
+ # CONFIG_FILE
+ #
+
+_ACEOF
+
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+# If the template does not know about datarootdir, expand it.
+# FIXME: This hack should be removed a few years after 2.60.
+ac_datarootdir_hack=; ac_datarootdir_seen=
+ac_sed_dataroot='
+/datarootdir/ {
+ p
+ q
+}
+/@datadir@/p
+/@docdir@/p
+/@infodir@/p
+/@localedir@/p
+/@mandir@/p'
+case `eval "sed -n \"\$ac_sed_dataroot\" $ac_file_inputs"` in
+*datarootdir*) ac_datarootdir_seen=yes;;
+*@datadir@*|*@docdir@*|*@infodir@*|*@localedir@*|*@mandir@*)
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&5
+$as_echo "$as_me: WARNING: $ac_file_inputs seems to ignore the --datarootdir setting" >&2;}
+_ACEOF
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ ac_datarootdir_hack='
+ s&@datadir@&$datadir&g
+ s&@docdir@&$docdir&g
+ s&@infodir@&$infodir&g
+ s&@localedir@&$localedir&g
+ s&@mandir@&$mandir&g
+ s&\\\${datarootdir}&$datarootdir&g' ;;
+esac
+_ACEOF
+
+# Neutralize VPATH when `$srcdir' = `.'.
+# Shell code in configure.ac might set extrasub.
+# FIXME: do we really want to maintain this feature?
+cat >>$CONFIG_STATUS <<_ACEOF || ac_write_fail=1
+ac_sed_extra="$ac_vpsub
+$extrasub
+_ACEOF
+cat >>$CONFIG_STATUS <<\_ACEOF || ac_write_fail=1
+:t
+/@[a-zA-Z_][a-zA-Z_0-9]*@/!b
+s|@configure_input@|$ac_sed_conf_input|;t t
+s&@top_builddir@&$ac_top_builddir_sub&;t t
+s&@top_build_prefix@&$ac_top_build_prefix&;t t
+s&@srcdir@&$ac_srcdir&;t t
+s&@abs_srcdir@&$ac_abs_srcdir&;t t
+s&@top_srcdir@&$ac_top_srcdir&;t t
+s&@abs_top_srcdir@&$ac_abs_top_srcdir&;t t
+s&@builddir@&$ac_builddir&;t t
+s&@abs_builddir@&$ac_abs_builddir&;t t
+s&@abs_top_builddir@&$ac_abs_top_builddir&;t t
+$ac_datarootdir_hack
+"
+eval sed \"\$ac_sed_extra\" "$ac_file_inputs" | $AWK -f "$ac_tmp/subs.awk" \
+ >$ac_tmp/out || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+
+test -z "$ac_datarootdir_hack$ac_datarootdir_seen" &&
+ { ac_out=`sed -n '/\${datarootdir}/p' "$ac_tmp/out"`; test -n "$ac_out"; } &&
+ { ac_out=`sed -n '/^[ ]*datarootdir[ ]*:*=/p' \
+ "$ac_tmp/out"`; test -z "$ac_out"; } &&
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&5
+$as_echo "$as_me: WARNING: $ac_file contains a reference to the variable \`datarootdir'
+which seems to be undefined. Please make sure it is defined" >&2;}
+
+ rm -f "$ac_tmp/stdin"
+ case $ac_file in
+ -) cat "$ac_tmp/out" && rm -f "$ac_tmp/out";;
+ *) rm -f "$ac_file" && mv "$ac_tmp/out" "$ac_file";;
+ esac \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ ;;
+ :H)
+ #
+ # CONFIG_HEADER
+ #
+ if test x"$ac_file" != x-; then
+ {
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs"
+ } >"$ac_tmp/config.h" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ if diff "$ac_file" "$ac_tmp/config.h" >/dev/null 2>&1; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: $ac_file is unchanged" >&5
+$as_echo "$as_me: $ac_file is unchanged" >&6;}
+ else
+ rm -f "$ac_file"
+ mv "$ac_tmp/config.h" "$ac_file" \
+ || as_fn_error $? "could not create $ac_file" "$LINENO" 5
+ fi
+ else
+ $as_echo "/* $configure_input */" \
+ && eval '$AWK -f "$ac_tmp/defines.awk"' "$ac_file_inputs" \
+ || as_fn_error $? "could not create -" "$LINENO" 5
+ fi
+ ;;
+
+
+ esac
+
+done # for ac_tag
+
+
+as_fn_exit 0
+_ACEOF
+ac_clean_files=$ac_clean_files_save
+
+test $ac_write_fail = 0 ||
+ as_fn_error $? "write failure creating $CONFIG_STATUS" "$LINENO" 5
+
+
+# configure is writing to config.log, and then calls config.status.
+# config.status does its own redirection, appending to config.log.
+# Unfortunately, on DOS this fails, as config.log is still kept open
+# by configure, so config.status won't be able to write to it; its
+# output is simply discarded. So we exec the FD to /dev/null,
+# effectively closing config.log, so it can be properly (re)opened and
+# appended to by config.status. When coming back to configure, we
+# need to make the FD available again.
+if test "$no_create" != yes; then
+ ac_cs_success=:
+ ac_config_status_args=
+ test "$silent" = yes &&
+ ac_config_status_args="$ac_config_status_args --quiet"
+ exec 5>/dev/null
+ $SHELL $CONFIG_STATUS $ac_config_status_args || ac_cs_success=false
+ exec 5>>config.log
+ # Use ||, not &&, to avoid exiting from the if with $? = 1, which
+ # would make configure fail if this is the last instruction.
+ $ac_cs_success || as_fn_exit 1
+fi
+if test -n "$ac_unrecognized_opts" && test "$enable_option_checking" != no; then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: unrecognized options: $ac_unrecognized_opts" >&5
+$as_echo "$as_me: WARNING: unrecognized options: $ac_unrecognized_opts" >&2;}
+fi
+
--- /dev/null
+# -*- Autoconf -*-
+# Process this file with autoconf to produce a configure script.
+#
+# Copyright (C) 2010--2014 Olaf Bergmann <bergmann@tzi.org>
+#
+# This file is part of the CoAP library libcoap. Please see
+# README for terms of use.
+
+AC_PREREQ([2.65])
+AC_INIT([libcoap], [4.1.1])
+AC_CONFIG_SRCDIR([coap.h])
+
+# First check for Contiki build to quit configure before any other test
+AC_ARG_WITH(contiki,
+ [AS_HELP_STRING([--with-contiki],[build libcoap for the Contiki OS])],
+ [cp -p Makefile.contiki Makefile
+ cp -p config.h.contiki config.h
+ AC_MSG_NOTICE([Contiki build prepared])
+ exit 0],
+ [])
+
+# Checks for programs.
+AC_PROG_MAKE_SET
+AC_PROG_CC
+AC_PROG_RANLIB
+AC_PATH_PROG(DOXYGEN, doxygen, [:])
+AC_PATH_PROG(ETAGS, etags, [/bin/false])
+
+AC_C_BIGENDIAN
+
+# Checks for libraries.
+AC_CHECK_LIB([coap], [coap_new_pdu])
+
+AC_SEARCH_LIBS([gethostbyname], [nsl])
+AC_SEARCH_LIBS([socket], [socket])
+
+# configuration options that may change compile flags
+AC_ARG_WITH(debug,
+ [AS_HELP_STRING([--without-debug],[disable all debug output and assertions])],
+ [CPPFLAGS="${CPPFLAGS} -DNDEBUG"],
+ [])
+
+AC_ARG_WITH(async,
+ [AS_HELP_STRING([--without-async],[disable handling of asynchronous transactions and observe])],
+ [CPPFLAGS="${CPPFLAGS} -DWITHOUT_ASYNC"],
+ [])
+
+AC_ARG_WITH(block,
+ [AS_HELP_STRING([--without-block],[disable block transfer])],
+ [CPPFLAGS="${CPPFLAGS} -DWITHOUT_BLOCK"],
+ [])
+
+AC_ARG_WITH(observe,
+ [AS_HELP_STRING([--without-observe],[disable resource observation])],
+ [CPPFLAGS="${CPPFLAGS} -DWITHOUT_OBSERVE"],
+ [])
+
+AC_ARG_WITH(query-filter,
+ [AS_HELP_STRING([--without-query-filter],[disable support for filters on /.well-known/core])],
+ [CPPFLAGS="${CPPFLAGS} -DWITHOUT_QUERY_FILTER"],
+ [])
+
+AC_ARG_WITH(tests,
+ [AS_HELP_STRING([--with-tests],[enable unit tests (requires cunit)])],
+ [TESTS="tests"],
+ [])
+
+AC_ARG_WITH(shared,
+ [AS_HELP_STRING([--with-shared],[build shared library])],
+ [BUILD_SO="BUILD_SO=1"],
+ [])
+
+# disambiguate between autoconf generated setups and contiki / lwip setups
+# which use explicit config.h.* files
+CPPFLAGS="${CPPFLAGS} -DWITH_POSIX"
+
+# Checks for header files.
+AC_CHECK_HEADERS([assert.h arpa/inet.h limits.h netdb.h netinet/in.h stdlib.h string.h strings.h sys/socket.h sys/time.h time.h unistd.h sys/unistd.h syslog.h])
+
+# Checks for typedefs, structures, and compiler characteristics.
+AC_TYPE_SIZE_T
+AC_TYPE_SSIZE_T
+
+# Checks for library functions.
+AC_FUNC_MALLOC
+AC_CHECK_FUNCS([memset select socket strcasecmp strrchr getaddrinfo strnlen])
+
+AC_SUBST(TESTS)
+AC_SUBST(BUILD_SO)
+
+AC_CONFIG_HEADERS([config.h])
+
+AC_CONFIG_FILES([Makefile
+ doc/Makefile
+ doc/Doxyfile
+ examples/Makefile
+ tests/Makefile])
+AC_OUTPUT
--- /dev/null
+/* debug.c -- debug utilities
+ *
+ * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "config.h"
+
+#if defined(HAVE_ASSERT_H) && !defined(assert)
+# include <assert.h>
+#endif
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+
+#include "debug.h"
+#include "net.h"
+
+#ifdef WITH_CONTIKI
+# ifndef DEBUG
+# define DEBUG DEBUG_PRINT
+# endif /* DEBUG */
+#include "net/uip-debug.h"
+#endif
+
+static coap_log_t maxlog = LOG_WARNING; /* default maximum log level */
+
+coap_log_t
+coap_get_log_level() {
+ return maxlog;
+}
+
+void
+coap_set_log_level(coap_log_t level) {
+ maxlog = level;
+}
+
+/* this array has the same order as the type log_t */
+static char *loglevels[] = {
+ "EMRG", "ALRT", "CRIT", "ERR", "WARN", "NOTE", "INFO", "DEBG"
+};
+
+#ifdef HAVE_TIME_H
+
+static inline size_t
+print_timestamp(char *s, size_t len, coap_tick_t t) {
+ struct tm *tmp;
+ time_t now = clock_offset + (t / COAP_TICKS_PER_SECOND);
+ tmp = localtime(&now);
+ return strftime(s, len, "%b %d %H:%M:%S", tmp);
+}
+
+#else /* alternative implementation: just print the timestamp */
+
+static inline size_t
+print_timestamp(char *s, size_t len, coap_tick_t t) {
+#ifdef HAVE_SNPRINTF
+ return snprintf(s, len, "%u.%03u",
+ (unsigned int)(clock_offset + (t / COAP_TICKS_PER_SECOND)),
+ (unsigned int)(t % COAP_TICKS_PER_SECOND));
+#else /* HAVE_SNPRINTF */
+ /* @todo do manual conversion of timestamp */
+ return 0;
+#endif /* HAVE_SNPRINTF */
+}
+
+#endif /* HAVE_TIME_H */
+
+#ifndef NDEBUG
+
+#ifndef HAVE_STRNLEN
+/**
+ * A length-safe strlen() fake.
+ *
+ * @param s The string to count characters != 0.
+ * @param maxlen The maximum length of @p s.
+ *
+ * @return The length of @p s.
+ */
+static inline size_t
+strnlen(const char *s, size_t maxlen) {
+ size_t n = 0;
+ while(*s++ && n < maxlen)
+ ++n;
+ return n;
+}
+#endif /* HAVE_STRNLEN */
+
+unsigned int
+print_readable( const unsigned char *data, unsigned int len,
+ unsigned char *result, unsigned int buflen, int encode_always ) {
+ const unsigned char hex[] = "0123456789ABCDEF";
+ unsigned int cnt = 0;
+ assert(data || len == 0);
+
+ if (buflen == 0 || len == 0)
+ return 0;
+
+ while (len) {
+ if (!encode_always && isprint(*data)) {
+ if (cnt == buflen)
+ break;
+ *result++ = *data;
+ ++cnt;
+ } else {
+ if (cnt+4 < buflen) {
+ *result++ = '\\';
+ *result++ = 'x';
+ *result++ = hex[(*data & 0xf0) >> 4];
+ *result++ = hex[*data & 0x0f];
+ cnt += 4;
+ } else
+ break;
+ }
+
+ ++data; --len;
+ }
+
+ *result = '\0';
+ return cnt;
+}
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+size_t
+coap_print_addr(const struct coap_address_t *addr, unsigned char *buf, size_t len) {
+TODO(FIX: Fix this)
+ (void)addr;
+ (void)buf;
+ (void)len;
+#if 0
+#ifdef HAVE_ARPA_INET_H
+ const void *addrptr = NULL;
+ in_port_t port;
+ unsigned char *p = buf;
+
+ switch (addr->addr.sa.sa_family) {
+ case AF_INET:
+ addrptr = &addr->addr.sin.sin_addr;
+ port = ntohs(addr->addr.sin.sin_port);
+ break;
+ case AF_INET6:
+ if (len < 7) /* do not proceed if buffer is even too short for [::]:0 */
+ return 0;
+
+ *p++ = '[';
+
+ addrptr = &addr->addr.sin6.sin6_addr;
+ port = ntohs(addr->addr.sin6.sin6_port);
+
+ break;
+ default:
+ memcpy(buf, "(unknown address type)", min(22, len));
+ return min(22, len);
+ }
+
+ if (inet_ntop(addr->addr.sa.sa_family, addrptr, (char *)p, len) == 0) {
+ perror("coap_print_addr");
+ return 0;
+ }
+
+ p += strnlen((char *)p, len);
+
+ if (addr->addr.sa.sa_family == AF_INET6) {
+ if (p < buf + len) {
+ *p++ = ']';
+ } else
+ return 0;
+ }
+
+ p += snprintf((char *)p, buf + len - p + 1, ":%d", port);
+
+ return buf + len - p;
+#else /* HAVE_ARPA_INET_H */
+# if WITH_CONTIKI
+ unsigned char *p = buf;
+ uint8_t i;
+# if WITH_UIP6
+ const unsigned char hex[] = "0123456789ABCDEF";
+
+ if (len < 41)
+ return 0;
+
+ *p++ = '[';
+
+ for (i=0; i < 16; i += 2) {
+ if (i) {
+ *p++ = ':';
+ }
+ *p++ = hex[(addr->addr.u8[i] & 0xf0) >> 4];
+ *p++ = hex[(addr->addr.u8[i] & 0x0f)];
+ *p++ = hex[(addr->addr.u8[i+1] & 0xf0) >> 4];
+ *p++ = hex[(addr->addr.u8[i+1] & 0x0f)];
+ }
+ *p++ = ']';
+# else /* WITH_UIP6 */
+# warning "IPv4 network addresses will not be included in debug output"
+
+ if (len < 21)
+ return 0;
+# endif /* WITH_UIP6 */
+ if (buf + len - p < 6)
+ return 0;
+
+#ifdef HAVE_SNPRINTF
+ p += snprintf((char *)p, buf + len - p + 1, ":%d", uip_htons(addr->port));
+#else /* HAVE_SNPRINTF */
+ /* @todo manual conversion of port number */
+#endif /* HAVE_SNPRINTF */
+
+ return p - buf;
+# else /* WITH_CONTIKI */
+ /* TODO: output addresses manually */
+# warning "inet_ntop() not available, network addresses will not be included in debug output"
+# endif /* WITH_CONTIKI */
+ return 0;
+#endif
+#endif //if 0
+}
+
+#ifndef WITH_CONTIKI
+void
+coap_show_pdu(const coap_pdu_t *pdu) {
+ unsigned char buf[COAP_MAX_PDU_SIZE]; /* need some space for output creation */
+ int encode = 0, have_options = 0;
+ coap_opt_iterator_t opt_iter;
+ coap_opt_t *option;
+
+ fprintf(COAP_DEBUG_FD, "v:%d t:%d tkl:%d c:%d id:%u",
+ pdu->hdr->version, pdu->hdr->type,
+ pdu->hdr->token_length,
+ pdu->hdr->code, ntohs(pdu->hdr->id));
+
+ /* show options, if any */
+ coap_option_iterator_init((coap_pdu_t *)pdu, &opt_iter, COAP_OPT_ALL);
+
+ while ((option = coap_option_next(&opt_iter))) {
+ if (!have_options) {
+ have_options = 1;
+ fprintf(COAP_DEBUG_FD, " o: [");
+ } else {
+ fprintf(COAP_DEBUG_FD, ",");
+ }
+
+ if (opt_iter.type == COAP_OPTION_URI_PATH ||
+ opt_iter.type == COAP_OPTION_PROXY_URI ||
+ opt_iter.type == COAP_OPTION_URI_HOST ||
+ opt_iter.type == COAP_OPTION_LOCATION_PATH ||
+ opt_iter.type == COAP_OPTION_LOCATION_QUERY ||
+ opt_iter.type == COAP_OPTION_URI_PATH ||
+ opt_iter.type == COAP_OPTION_URI_QUERY) {
+ encode = 0;
+ } else {
+ encode = 1;
+ }
+
+ if (print_readable(COAP_OPT_VALUE(option),
+ COAP_OPT_LENGTH(option),
+ buf, sizeof(buf), encode ))
+ fprintf(COAP_DEBUG_FD, " %d:'%s'", opt_iter.type, buf);
+ }
+
+ if (have_options)
+ fprintf(COAP_DEBUG_FD, " ]");
+
+ if (pdu->data) {
+ assert(pdu->data < (unsigned char *)pdu->hdr + pdu->length);
+ print_readable(pdu->data,
+ (unsigned char *)pdu->hdr + pdu->length - pdu->data,
+ buf, sizeof(buf), 0 );
+ fprintf(COAP_DEBUG_FD, " d:%s", buf);
+ }
+ fprintf(COAP_DEBUG_FD, "\n");
+ fflush(COAP_DEBUG_FD);
+}
+
+#else /* WITH_CONTIKI */
+
+void
+coap_show_pdu(const coap_pdu_t *pdu) {
+ unsigned char buf[80]; /* need some space for output creation */
+
+ PRINTF("v:%d t:%d oc:%d c:%d id:%u",
+ pdu->hdr->version, pdu->hdr->type,
+ pdu->hdr->optcnt, pdu->hdr->code, uip_ntohs(pdu->hdr->id));
+
+ /* show options, if any */
+ if (pdu->hdr->optcnt) {
+ coap_opt_iterator_t opt_iter;
+ coap_opt_t *option;
+ coap_option_iterator_init((coap_pdu_t *)pdu, &opt_iter, COAP_OPT_ALL);
+
+ PRINTF(" o:");
+ while ((option = coap_option_next(&opt_iter))) {
+
+ if (print_readable(COAP_OPT_VALUE(option),
+ COAP_OPT_LENGTH(option),
+ buf, sizeof(buf), 0))
+ PRINTF(" %d:%s", opt_iter.type, buf);
+ }
+ }
+
+ if (pdu->data < (unsigned char *)pdu->hdr + pdu->length) {
+ print_readable(pdu->data,
+ (unsigned char *)pdu->hdr + pdu->length - pdu->data,
+ buf, sizeof(buf), 0 );
+ PRINTF(" d:%s", buf);
+ }
+ PRINTF("\r\n");
+}
+#endif /* WITH_CONTIKI */
+
+#endif /* NDEBUG */
+
+#ifndef WITH_CONTIKI
+void
+coap_log_impl(coap_log_t level, const char *format, ...) {
+ char timebuf[32];
+ coap_tick_t now;
+ va_list ap;
+ FILE *log_fd;
+
+ if (maxlog < level)
+ return;
+
+ log_fd = level <= LOG_CRIT ? COAP_ERR_FD : COAP_DEBUG_FD;
+
+ coap_ticks(&now);
+ if (print_timestamp(timebuf,sizeof(timebuf), now))
+ fprintf(log_fd, "%s ", timebuf);
+
+ if (level <= LOG_DEBUG)
+ fprintf(log_fd, "%s ", loglevels[level]);
+
+ va_start(ap, format);
+ vfprintf(log_fd, format, ap);
+ va_end(ap);
+ fflush(log_fd);
+}
+#else /* WITH_CONTIKI */
+void
+coap_log_impl(coap_log_t level, const char *format, ...) {
+ char timebuf[32];
+ coap_tick_t now;
+ va_list ap;
+
+ if (maxlog < level)
+ return;
+
+ coap_ticks(&now);
+ if (print_timestamp(timebuf,sizeof(timebuf), now))
+ PRINTF("%s ", timebuf);
+
+ if (level <= LOG_DEBUG)
+ PRINTF("%s ", loglevels[level]);
+
+ va_start(ap, format);
+ PRINTF(format, ap);
+ va_end(ap);
+}
+#endif /* WITH_CONTIKI */
--- /dev/null
+/* debug.h -- debug utilities
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef _COAP_DEBUG_H_
+#define _COAP_DEBUG_H_
+
+#include "config.h"
+
+#ifndef COAP_DEBUG_FD
+#define COAP_DEBUG_FD stdout
+#endif
+
+#ifndef COAP_ERR_FD
+#define COAP_ERR_FD stderr
+#endif
+
+#ifdef HAVE_SYSLOG_H
+#include <syslog.h>
+typedef short coap_log_t;
+#else
+/** Pre-defined log levels akin to what is used in \b syslog. */
+typedef enum { LOG_EMERG=0, LOG_ALERT, LOG_CRIT, LOG_WARNING,
+ LOG_NOTICE, LOG_INFO, LOG_DEBUG
+} coap_log_t;
+#endif
+
+
+#define DO_PRAGMA(x) _Pragma (#x)
+#define TODO(x) DO_PRAGMA(message ("TODO - " #x))
+
+/** Returns the current log level. */
+coap_log_t coap_get_log_level();
+
+/** Sets the log level to the specified value. */
+void coap_set_log_level(coap_log_t level);
+
+/**
+ * Writes the given text to @c COAP_ERR_FD (for @p level <= @c
+ * LOG_CRIT) or @c COAP_DEBUG_FD (for @p level >= @c LOG_WARNING). The
+ * text is output only when @p level is below or equal to the log
+ * level that set by coap_set_log_level().
+ */
+void coap_log_impl(coap_log_t level, const char *format, ...);
+
+#ifndef coap_log
+#define coap_log(...) coap_log_impl(__VA_ARGS__)
+#endif
+
+#ifndef NDEBUG
+
+/* A set of convenience macros for common log levels. */
+#define info(...) coap_log(LOG_INFO, __VA_ARGS__)
+#define warn(...) coap_log(LOG_WARNING, __VA_ARGS__)
+#define debug(...) coap_log(LOG_DEBUG, __VA_ARGS__)
+
+#include "pdu.h"
+void coap_show_pdu(const coap_pdu_t *);
+
+struct coap_address_t;
+size_t coap_print_addr(const struct coap_address_t *, unsigned char *, size_t);
+
+#else
+
+#define debug(...)
+#define info(...)
+#define warn(...)
+
+#define coap_show_pdu(x)
+#define coap_print_addr(...)
+
+#endif
+
+#endif /* _COAP_DEBUG_H_ */
--- /dev/null
+# Doxyfile 1.6.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = libcoap
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = 4.1.1
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses.
+# With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
+# The format is ext=language, where ext is a file extension, and language is one of
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = .. ../examples
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
+# For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
--- /dev/null
+# Doxyfile 1.6.3
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# This tag specifies the encoding used for all characters in the config file
+# that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# http://www.gnu.org/software/libiconv for the list of possible encodings.
+
+DOXYFILE_ENCODING = UTF-8
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = @PACKAGE_NAME@
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER = @PACKAGE_VERSION@
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY =
+
+# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
+# 4096 sub-directories (in 2 levels) under the output directory of each output
+# format and will distribute the generated files over these directories.
+# Enabling this option can be useful when feeding doxygen a huge amount of
+# source files, where putting all generated files in the same directory would
+# otherwise cause performance problems for the file system.
+
+CREATE_SUBDIRS = NO
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional,
+# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German,
+# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English
+# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian,
+# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrilic, Slovak,
+# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese.
+
+OUTPUT_LANGUAGE = English
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is
+# used as the annotated text. Otherwise, the brief description is used as-is.
+# If left blank, the following values are used ("$name" is automatically
+# replaced with the name of the entity): "The $name class" "The $name widget"
+# "The $name file" "is" "provides" "specifies" "contains"
+# "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
+# inherited members of a class in the documentation of that class as if those
+# members were ordinary class members. Constructors, destructors and assignment
+# operators of the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. The tag can be used to show relative paths in the file list.
+# If left blank the directory from which doxygen is run is used as the
+# path to strip.
+
+STRIP_FROM_PATH =
+
+# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
+# the path mentioned in the documentation of a class, which tells
+# the reader which header file to include in order to use a class.
+# If left blank only the name of the header file containing the class
+# definition is used. Otherwise one should specify the include paths that
+# are normally passed to the compiler using the -I flag.
+
+STRIP_FROM_INC_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like regular Qt-style comments
+# (thus requiring an explicit @brief command for a brief description.)
+
+JAVADOC_AUTOBRIEF = YES
+
+# If the QT_AUTOBRIEF tag is set to YES then Doxygen will
+# interpret the first line (until the first dot) of a Qt-style
+# comment as the brief description. If set to NO, the comments
+# will behave just like regular Qt-style comments (thus requiring
+# an explicit \brief command for a brief description.)
+
+QT_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce
+# a new page for each member. If set to NO, the documentation of a member will
+# be part of the file/class/namespace that contains it.
+
+SEPARATE_MEMBER_PAGES = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 4
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C
+# sources only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java
+# sources only. Doxygen will then generate output that is more tailored for
+# Java. For instance, namespaces will be presented as packages, qualified
+# scopes will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
+# sources only. Doxygen will then generate output that is more tailored for
+# Fortran.
+
+OPTIMIZE_FOR_FORTRAN = NO
+
+# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
+# sources. Doxygen will then generate output that is tailored for
+# VHDL.
+
+OPTIMIZE_OUTPUT_VHDL = NO
+
+# Doxygen selects the parser to use depending on the extension of the files it parses.
+# With this tag you can assign which parser to use for a given extension.
+# Doxygen has a built-in mapping, but you can override or extend it using this tag.
+# The format is ext=language, where ext is a file extension, and language is one of
+# the parsers supported by doxygen: IDL, Java, Javascript, C#, C, C++, D, PHP,
+# Objective-C, Python, Fortran, VHDL, C, C++. For instance to make doxygen treat
+# .inc files as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C. Note that for custom extensions you also need to set FILE_PATTERNS otherwise the files are not read by doxygen.
+
+EXTENSION_MAPPING =
+
+# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
+# to include (a tag file for) the STL sources as input, then you should
+# set this tag to YES in order to let doxygen match functions declarations and
+# definitions whose arguments contain STL classes (e.g. func(std::string); v.s.
+# func(std::string) {}). This also make the inheritance and collaboration
+# diagrams that involve STL classes more complete and accurate.
+
+BUILTIN_STL_SUPPORT = NO
+
+# If you use Microsoft's C++/CLI language, you should set this option to YES to
+# enable parsing support.
+
+CPP_CLI_SUPPORT = NO
+
+# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only.
+# Doxygen will parse them like normal C++ but will assume all classes use public
+# instead of private inheritance when no explicit protection keyword is present.
+
+SIP_SUPPORT = NO
+
+# For Microsoft's IDL there are propget and propput attributes to indicate getter
+# and setter methods for a property. Setting this option to YES (the default)
+# will make doxygen to replace the get and set methods by a property in the
+# documentation. This will only work if the methods are indeed getting or
+# setting a simple type. If this is not the case, or you want to show the
+# methods anyway, you should set this option to NO.
+
+IDL_PROPERTY_SUPPORT = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum
+# is documented as struct, union, or enum with the name of the typedef. So
+# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
+# with name TypeT. When disabled the typedef will appear as a member of a file,
+# namespace, or class. And the struct will be named TypeS. This can typically
+# be useful for C code in case the coding convention dictates that all compound
+# types are typedef'ed and only the typedef is referenced, never the tag name.
+
+TYPEDEF_HIDES_STRUCT = NO
+
+# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
+# determine which symbols to keep in memory and which to flush to disk.
+# When the cache is full, less often used symbols will be written to disk.
+# For small to medium size projects (<1000 input files) the default value is
+# probably good enough. For larger projects a too small cache size can cause
+# doxygen to be busy swapping symbols to and from disk most of the time
+# causing a significant performance penality.
+# If the system has enough physical memory increasing the cache will improve the
+# performance by keeping more symbols in memory. Note that the value works on
+# a logarithmic scale so increasing the size by one will rougly double the
+# memory usage. The cache size is given by this formula:
+# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
+# corresponding to a cache size of 2^16 = 65536 symbols
+
+SYMBOL_CACHE_SIZE = 0
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = YES
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = YES
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# This flag is only useful for Objective-C code. When set to YES local
+# methods, which are defined in the implementation section but not in
+# the interface are included in the documentation.
+# If set to NO (the default) only methods in the interface are included.
+
+EXTRACT_LOCAL_METHODS = NO
+
+# If this flag is set to YES, the members of anonymous namespaces will be
+# extracted and appear in the documentation as a namespace called
+# 'anonymous_namespace{file}', where file will be replaced with the base
+# name of the file that contains the anonymous namespace. By default
+# anonymous namespace are hidden.
+
+EXTRACT_ANON_NSPACES = NO
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# and Mac users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen
+# will list include files with double quotes in the documentation
+# rather than with sharp brackets.
+
+FORCE_LOCAL_INCLUDES = NO
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the
+# brief documentation of file, namespace and class members alphabetically
+# by member name. If set to NO (the default) the members will appear in
+# declaration order.
+
+SORT_BRIEF_DOCS = NO
+
+# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the (brief and detailed) documentation of class members so that constructors and destructors are listed first. If set to NO (the default) the constructors will appear in the respective orders defined by SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO.
+
+SORT_MEMBERS_CTORS_1ST = NO
+
+# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the
+# hierarchy of group names into alphabetical order. If set to NO (the default)
+# the group names will appear in their defined order.
+
+SORT_GROUP_NAMES = NO
+
+# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be
+# sorted by fully-qualified names, including namespaces. If set to
+# NO (the default), the class list will be sorted only by class name,
+# not including the namespace part.
+# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
+# Note: This option applies only to the class list, not to the
+# alphabetical list.
+
+SORT_BY_SCOPE_NAME = NO
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+# If the sources in your project are distributed over multiple directories
+# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
+# in the documentation. The default is NO.
+
+SHOW_DIRECTORIES = NO
+
+# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
+# This will remove the Files entry from the Quick Index and from the
+# Folder Tree View (if specified). The default is YES.
+
+SHOW_FILES = YES
+
+# Set the SHOW_NAMESPACES tag to NO to disable the generation of the
+# Namespaces page.
+# This will remove the Namespaces entry from the Quick Index
+# and from the Folder Tree View (if specified). The default is YES.
+
+SHOW_NAMESPACES = YES
+
+# The FILE_VERSION_FILTER tag can be used to specify a program or script that
+# doxygen should invoke to get the current version for each file (typically from
+# the version control system). Doxygen will invoke the program by executing (via
+# popen()) the command <command> <input-file>, where <command> is the value of
+# the FILE_VERSION_FILTER tag, and <input-file> is the name of an input file
+# provided by doxygen. Whatever the program writes to standard output
+# is used as the file version. See the manual for examples.
+
+FILE_VERSION_FILTER =
+
+# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed by
+# doxygen. The layout file controls the global structure of the generated output files
+# in an output format independent way. The create the layout file that represents
+# doxygen's defaults, run doxygen with the -l option. You can optionally specify a
+# file name after the option, if omitted DoxygenLayout.xml will be used as the name
+# of the layout file.
+
+LAYOUT_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# This WARN_NO_PARAMDOC option can be abled to get warnings for
+# functions that are documented, but have no documentation for their parameters
+# or return value. If set to NO (the default) doxygen will only warn about
+# wrong or incomplete parameter documentation, but not about the absence of
+# documentation.
+
+WARN_NO_PARAMDOC = NO
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text. Optionally the format may contain
+# $version, which will be replaced by the version of the file (if it could
+# be obtained via FILE_VERSION_FILTER)
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT = .. ../examples
+
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is
+# also the default input encoding. Doxygen uses libiconv (or the iconv built
+# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for
+# the list of possible encodings.
+
+INPUT_ENCODING = UTF-8
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
+# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or
+# directories that are symbolic links (a Unix filesystem feature) are excluded
+# from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories. Note that the wildcards are matched
+# against the file with absolute path, so to exclude all test directories
+# for example use the pattern */test/*
+
+EXCLUDE_PATTERNS =
+
+# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
+# (namespaces, classes, functions, etc.) that should be excluded from the
+# output. The symbol name can be a fully qualified name, a word, or if the
+# wildcard * is used, a substring. Examples: ANamespace, AClass,
+# AClass::ANamespace, ANamespace::*Test
+
+EXCLUDE_SYMBOLS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+# If FILTER_PATTERNS is specified, this tag will be
+# ignored.
+
+INPUT_FILTER =
+
+# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
+# basis.
+# Doxygen will compare the file name with each pattern and apply the
+# filter if there is a match.
+# The filters are a list of the form:
+# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further
+# info on how filters are used. If FILTER_PATTERNS is empty, INPUT_FILTER
+# is applied to all files.
+
+FILTER_PATTERNS =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = YES
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = NO
+
+# If the REFERENCES_RELATION tag is set to YES
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = NO
+
+# If the REFERENCES_LINK_SOURCE tag is set to YES (the default)
+# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from
+# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will
+# link to the source code.
+# Otherwise they will link to the documentation.
+
+REFERENCES_LINK_SOURCE = YES
+
+# If the USE_HTAGS tag is set to YES then the references to source code
+# will point to the HTML generated by the htags(1) tool instead of doxygen
+# built-in source browser. The htags tool is part of GNU's global source
+# tagging system (see http://www.gnu.org/software/global/global.html). You
+# will need version 4.8.6 or higher.
+
+USE_HTAGS = NO
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
+# page will contain the date and time when the page was generated. Setting
+# this to NO can help when comparing the output of multiple runs.
+
+HTML_TIMESTAMP = YES
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
+# documentation will contain sections that can be hidden and shown after the
+# page has loaded. For this to work a browser that supports
+# JavaScript and DHTML is required (for instance Mozilla 1.0+, Firefox
+# Netscape 6.0+, Internet explorer 5.0+, Konqueror, or Safari).
+
+HTML_DYNAMIC_SECTIONS = NO
+
+# If the GENERATE_DOCSET tag is set to YES, additional index files
+# will be generated that can be used as input for Apple's Xcode 3
+# integrated development environment, introduced with OSX 10.5 (Leopard).
+# To create a documentation set, doxygen will generate a Makefile in the
+# HTML output directory. Running make will produce the docset in that
+# directory and running "make install" will install the docset in
+# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find
+# it at startup.
+# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html for more information.
+
+GENERATE_DOCSET = NO
+
+# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the
+# feed. A documentation feed provides an umbrella under which multiple
+# documentation sets from a single provider (such as a company or product suite)
+# can be grouped.
+
+DOCSET_FEEDNAME = "Doxygen generated docs"
+
+# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that
+# should uniquely identify the documentation set bundle. This should be a
+# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen
+# will append .docset to the name.
+
+DOCSET_BUNDLE_ID = org.doxygen.Project
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compiled HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING
+# is used to encode HtmlHelp index (hhk), content (hhc) and project file
+# content.
+
+CHM_INDEX_ENCODING =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and QHP_VIRTUAL_FOLDER
+# are set, an additional index file will be generated that can be used as input for
+# Qt's qhelpgenerator to generate a Qt Compressed Help (.qch) of the generated
+# HTML documentation.
+
+GENERATE_QHP = NO
+
+# If the QHG_LOCATION tag is specified, the QCH_FILE tag can
+# be used to specify the file name of the resulting .qch file.
+# The path specified is relative to the HTML output folder.
+
+QCH_FILE =
+
+# The QHP_NAMESPACE tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#namespace
+
+QHP_NAMESPACE = org.doxygen.Project
+
+# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating
+# Qt Help Project output. For more information please see
+# http://doc.trolltech.com/qthelpproject.html#virtual-folders
+
+QHP_VIRTUAL_FOLDER = doc
+
+# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to add.
+# For more information please see
+# http://doc.trolltech.com/qthelpproject.html#custom-filters
+
+QHP_CUST_FILTER_NAME =
+
+# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the custom filter to add.For more information please see
+# <a href="http://doc.trolltech.com/qthelpproject.html#custom-filters">Qt Help Project / Custom Filters</a>.
+
+QHP_CUST_FILTER_ATTRS =
+
+# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this project's
+# filter section matches.
+# <a href="http://doc.trolltech.com/qthelpproject.html#filter-attributes">Qt Help Project / Filter Attributes</a>.
+
+QHP_SECT_FILTER_ATTRS =
+
+# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can
+# be used to specify the location of Qt's qhelpgenerator.
+# If non-empty doxygen will try to run qhelpgenerator on the generated
+# .qhp file.
+
+QHG_LOCATION =
+
+# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files
+# will be generated, which together with the HTML files, form an Eclipse help
+# plugin. To install this plugin and make it available under the help contents
+# menu in Eclipse, the contents of the directory containing the HTML and XML
+# files needs to be copied into the plugins directory of eclipse. The name of
+# the directory within the plugins directory should be the same as
+# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before the help appears.
+
+GENERATE_ECLIPSEHELP = NO
+
+# A unique identifier for the eclipse help plugin. When installing the plugin
+# the directory name containing the HTML and XML files should also have
+# this name.
+
+ECLIPSE_DOC_ID = org.doxygen.Project
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
+# structure should be generated to display hierarchical information.
+# If the tag value is set to YES, a side panel will be generated
+# containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser).
+# Windows users are probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
+# and Class Hierarchy pages using a tree view instead of an ordered list.
+
+USE_INLINE_TREES = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+# Use this tag to change the font size of Latex formulas included
+# as images in the HTML documentation. The default is 10. Note that
+# when you change the font size after a successful doxygen run you need
+# to manually remove any form_*.png images from the HTML output directory
+# to force them to be regenerated.
+
+FORMULA_FONTSIZE = 10
+
+# When the SEARCHENGINE tag is enabled doxygen will generate a search box for the HTML output. The underlying search engine uses javascript
+# and DHTML and should work on any modern browser. Note that when using HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) there is already a search function so this one should
+# typically be disabled. For large projects the javascript based search engine
+# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution.
+
+SEARCHENGINE = YES
+
+# When the SERVER_BASED_SEARCH tag is enabled the search engine will be implemented using a PHP enabled web server instead of at the web client using Javascript. Doxygen will generate the search PHP script and index
+# file to put on the web server. The advantage of the server based approach is that it scales better to large projects and allows full text search. The disadvances is that it is more difficult to setup
+# and does not have live searching capabilities.
+
+SERVER_BASED_SEARCH = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = NO
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+# Note that when enabling USE_PDFLATEX this option is only used for
+# generating bitmaps for formulas in the HTML output, but not in the
+# Makefile that is written to the output directory.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = YES
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = YES
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+# If LATEX_SOURCE_CODE is set to YES then doxygen will include source code with syntax highlighting in the LaTeX output. Note that which sources are shown also depends on other settings such as SOURCE_BROWSER.
+
+LATEX_SOURCE_CODE = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader.
+# This is useful
+# if you want to understand what is going on.
+# On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_DEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed. To prevent a macro definition from being
+# undefined via #undef or recursively expanded use the := operator
+# instead of the = operator.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse
+# the parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::additions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+#
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+#
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base
+# or super classes. Setting the tag to NO turns the diagrams off. Note that
+# this option is superseded by the HAVE_DOT option below. This is only a
+# fallback. It is recommended to install and use dot, since it yields more
+# powerful graphs.
+
+CLASS_DIAGRAMS = NO
+
+# You can define message sequence charts within doxygen comments using the \msc
+# command. Doxygen will then run the mscgen tool (see
+# http://www.mcternan.me.uk/mscgen/) to produce the chart and insert it in the
+# documentation. The MSCGEN_PATH tag allows you to specify the directory where
+# the mscgen tool resides. If left empty the tool is assumed to be found in the
+# default search path.
+
+MSCGEN_PATH =
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# By default doxygen will write a font called FreeSans.ttf to the output
+# directory and reference it in all dot files that doxygen generates. This
+# font does not include all possible unicode characters however, so when you need
+# these (or just want a differently looking font) you can specify the font name
+# using DOT_FONTNAME. You need need to make sure dot is able to find the font,
+# which can be done by putting it in a standard location or by setting the
+# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
+# containing the font.
+
+DOT_FONTNAME = FreeSans
+
+# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
+# The default size is 10pt.
+
+DOT_FONTSIZE = 10
+
+# By default doxygen will tell dot to use the output directory to look for the
+# FreeSans.ttf font (which doxygen will put there itself). If you specify a
+# different font using DOT_FONTNAME you can set the path where dot
+# can find it using this tag.
+
+DOT_FONTPATH =
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the GROUP_GRAPHS and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for groups, showing the direct groups dependencies
+
+GROUP_GRAPHS = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT options are set to YES then
+# doxygen will generate a call dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable call graphs
+# for selected functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the CALLER_GRAPH and HAVE_DOT tags are set to YES then
+# doxygen will generate a caller dependency graph for every global function
+# or class method. Note that enabling this option will significantly increase
+# the time of a run. So in most cases it will be better to enable caller
+# graphs for selected functions only using the \callergraph command.
+
+CALLER_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# If the DIRECTORY_GRAPH, SHOW_DIRECTORIES and HAVE_DOT tags are set to YES
+# then doxygen will show the dependencies a directory has on other directories
+# in a graphical way. The dependency relations are determined by the #include
+# relations between the files in the directories.
+
+DIRECTORY_GRAPH = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found in the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of
+# nodes that will be shown in the graph. If the number of nodes in a graph
+# becomes larger than this value, doxygen will truncate the graph, which is
+# visualized by representing a node as a red box. Note that doxygen if the
+# number of direct children of the root node in a graph is already larger than
+# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note
+# that the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
+
+DOT_GRAPH_MAX_NODES = 50
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes
+# that lay further from the root node will be omitted. Note that setting this
+# option to 1 or 2 may greatly reduce the computation time needed for large
+# code bases. Also note that the size of a graph can be further restricted by
+# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
+# background. This is disabled by default, because dot on Windows does not
+# seem to support this out of the box. Warning: Depending on the platform used,
+# enabling this option may lead to badly anti-aliased labels on the edges of
+# a graph (i.e. they become hard to read).
+
+DOT_TRANSPARENT = NO
+
+# Set the DOT_MULTI_TARGETS tag to YES allow dot to generate multiple output
+# files in one run (i.e. multiple -o and -T options on the command line). This
+# makes dot run faster, but since only newer versions of dot (>1.8.10)
+# support this, this feature is disabled by default.
+
+DOT_MULTI_TARGETS = YES
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
--- /dev/null
+# Makefile for libcoap
+#
+# Copyright (C) 2010 Olaf Bergmann <bergmann@tzi.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# the library's version
+VERSION:=4.1.1
+
+# tools
+
+SHELL = /bin/sh
+MKDIR = mkdir
+DOXYGEN= /usr/bin/doxygen
+
+top_builddir = ..
+
+DISTDIR?=$(top_builddir)/libcoap-4.1.1
+FILES:=Makefile.in Doxyfile.in html
+
+doc: Doxyfile
+ @mkdir html
+ $(DOXYGEN) $< >./doxygen.out 2>&1
+
+clean:
+ @rm -rf html doxygen.out
+
+distclean: clean
+ @rm -rf $(DISTDIR)
+ @rm -f *~
+
+dist: doc
+ test -d $(DISTDIR)/doc || mkdir $(DISTDIR)/doc
+ cp -r $(FILES) $(DISTDIR)/doc
--- /dev/null
+# Makefile for libcoap
+#
+# Copyright (C) 2010 Olaf Bergmann <bergmann@tzi.org>
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License
+# as published by the Free Software Foundation; either version 2
+# of the License, or (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+
+# the library's version
+VERSION:=@PACKAGE_VERSION@
+
+# tools
+@SET_MAKE@
+SHELL = /bin/sh
+MKDIR = mkdir
+DOXYGEN= @DOXYGEN@
+
+top_builddir = @top_builddir@
+
+DISTDIR?=$(top_builddir)/@PACKAGE_TARNAME@-@PACKAGE_VERSION@
+FILES:=Makefile.in Doxyfile.in html
+
+doc: Doxyfile
+ $(DOXYGEN) $< >./doxygen.out 2>&1
+
+clean:
+ @rm -rf html
+
+distclean: clean
+ @rm -rf $(DISTDIR)
+ @rm -f *~
+
+dist: doc
+ test -d $(DISTDIR)/doc || mkdir $(DISTDIR)/doc
+ cp -r $(FILES) $(DISTDIR)/doc
--- /dev/null
+/* encode.c -- encoding and decoding of CoAP data types
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef NDEBUG
+# include <stdio.h>
+#endif
+
+#include "config.h"
+#include "encode.h"
+
+/* Carsten suggested this when fls() is not available: */
+int coap_fls(unsigned int i) {
+ int n;
+ for (n = 0; i; n++)
+ i >>= 1;
+ return n;
+}
+
+unsigned int
+coap_decode_var_bytes(unsigned char *buf,unsigned int len) {
+ unsigned int i, n = 0;
+ for (i = 0; i < len; ++i)
+ n = (n << 8) + buf[i];
+
+ return n;
+}
+
+unsigned int
+coap_encode_var_bytes(unsigned char *buf, unsigned int val) {
+ unsigned int n, i;
+
+ for (n = 0, i = val; i && n < sizeof(val); ++n)
+ i >>= 8;
+
+ i = n;
+ while (i--) {
+ buf[i] = val & 0xff;
+ val >>= 8;
+ }
+
+ return n;
+}
+
--- /dev/null
+/* encode.h -- encoding and decoding of CoAP data types
+ *
+ * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef _COAP_ENCODE_H_
+#define _COAP_ENCODE_H_
+
+#if (BSD >= 199103) || defined(WITH_CONTIKI)
+# include <string.h>
+#else
+# include <strings.h>
+#endif
+
+#define Nn 8 /* duplicate definition of N if built on sky motes */
+#define E 4
+#define HIBIT (1 << (Nn - 1))
+#define EMASK ((1 << E) - 1)
+#define MMASK ((1 << Nn) - 1 - EMASK)
+#define MAX_VALUE ( (1 << Nn) - (1 << E) ) * (1 << ((1 << E) - 1))
+
+#define COAP_PSEUDOFP_DECODE_8_4(r) (r < HIBIT ? r : (r & MMASK) << (r & EMASK))
+
+#ifndef HAVE_FLS
+/* include this only if fls() is not available */
+extern int coap_fls(unsigned int i);
+#else
+#define coap_fls(i) fls(i)
+#endif
+
+/* ls and s must be integer variables */
+#define COAP_PSEUDOFP_ENCODE_8_4_DOWN(v,ls) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (v >> ls) & MMASK) + ls)
+#define COAP_PSEUDOFP_ENCODE_8_4_UP(v,ls,s) (v < HIBIT ? v : (ls = coap_fls(v) - Nn, (s = (((v + ((1<<E<<ls)-1)) >> ls) & MMASK)), s == 0 ? HIBIT + ls + 1 : s + ls))
+
+/**
+ * Decodes multiple-length byte sequences. buf points to an input byte
+ * sequence of length len. Returns the decoded value.
+ */
+unsigned int coap_decode_var_bytes(unsigned char *buf,unsigned int len);
+
+/**
+ * Encodes multiple-length byte sequences. buf points to an output
+ * buffer of sufficient length to store the encoded bytes. val is
+ * the value to encode. Returns the number of bytes used to encode
+ * val or 0 on error.
+ */
+unsigned int coap_encode_var_bytes(unsigned char *buf, unsigned int val);
+
+#endif /* _COAP_ENCODE_H_ */
--- /dev/null
+VERSION:=4.1.1
+
+#other options are android, arduino
+PLATFORM=linux
+
+ROOT_DIR = ../..
+OCSOCK_DIR = $(ROOT_DIR)/ocsocket
+LOGGER_DIR = $(ROOT_DIR)/logger
+RANDOM_DIR = $(ROOT_DIR)/ocrandom
+OBJ_DIR = ./
+INC_DIRS = -I.. -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include -I$(RANDOM_DIR)/include
+
+ifeq ($(PLATFORM),android)
+ CCPLUS=arm-linux-androideabi-g++
+ CC=arm-linux-androideabi-gcc
+ AR=arm-linux-androideabi-ar
+ RANLIB=arm-linux-androideabi-ranlib
+ CFLAGS_ANDROID = -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
+ LDFLAGS_ANDROID = -march=armv7-a -Wl,--fix-cortex-a8 -llog
+else ifeq ($(PLATFORM),linux)
+ CCPLUS=g++
+ CC=gcc
+ AR=ar
+ RANLIB=ranlib
+else
+ $(error Wrong value for PLATFORM !!)
+endif
+
+DEP_LIBS = ../libcoap.a
+
+CFLAGS += -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions \
+ -Wextra -Wno-variadic-macros -pedantic -std=gnu99 -DWITH_POSIX -DTB_LOG
+
+PROGRAMS = coap-server coap-client
+
+SOURCES:= client.c server.c
+
+OBJECTS:= $(patsubst %.c, %.o, $(SOURCES))
+
+all: $(PROGRAMS)
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $(CFLAGS_ANDROID) $(INC_DIRS) $< -o $@
+
+coap-client: client.o $(DEP_LIBS)
+ $(CC) -Os -Wl,--gc-sections $(LDFLAGS_ANDROID) $^ -o $@
+
+coap-server: server.o $(DEP_LIBS)
+ $(CC) -Os -Wl,--gc-sections $(LDFLAGS_ANDROID) $^ -o $@
+
+install: all
+ @echo "Installing for PLATFORM $(PLATFORM)"
+ifeq ($(PLATFORM),android)
+ adb push coap-client /data/local/tmp/
+ adb push coap-server /data/local/tmp/
+endif
+
+.PHONY: clean
+
+clean:
+ rm -f *.o $(PROGRAMS)
+
--- /dev/null
+/* coap-client -- simple CoAP client
+ *
+ * Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "config.h"
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <logger.h>
+
+#include "coap.h"
+
+int flags = 0;
+
+static unsigned char _token_data[8];
+str the_token = { 0, _token_data };
+
+#define MOD_NAME ("CoAP-Client")
+#define FLAGS_BLOCK 0x01
+
+static coap_list_t *optlist = NULL;
+/* Request URI.
+ * TODO: associate the resources with transaction id and make it expireable */
+static coap_uri_t uri;
+static str proxy = { 0, NULL };
+static unsigned short proxy_port = COAP_DEFAULT_PORT;
+
+/* reading is done when this flag is set */
+static int ready = 0;
+
+static str output_file = { 0, NULL }; /* output file name */
+static FILE *file = NULL; /* output file stream */
+
+static str payload = { 0, NULL }; /* optional payload to send */
+
+unsigned char msgtype = COAP_MESSAGE_CON; /* usually, requests are sent confirmable */
+
+typedef unsigned char method_t;
+method_t method = 1; /* the method we are using in our requests */
+
+coap_block_t block = { .num = 0, .m = 0, .szx = 6 };
+
+unsigned int wait_seconds = 90; /* default timeout in seconds */
+coap_tick_t max_wait; /* global timeout (changed by set_timeout()) */
+
+unsigned int obs_seconds = 30; /* default observe time */
+coap_tick_t obs_wait = 0; /* timeout for current subscription */
+
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+static inline void
+set_timeout(coap_tick_t *timer, const unsigned int seconds) {
+ coap_ticks(timer);
+ *timer += seconds * COAP_TICKS_PER_SECOND;
+}
+
+int
+append_to_output(const unsigned char *data, size_t len) {
+ size_t written;
+
+ if (!file) {
+ if (!output_file.s || (output_file.length && output_file.s[0] == '-'))
+ file = stdout;
+ else {
+ if (!(file = fopen((char *)output_file.s, "w"))) {
+ perror("fopen");
+ return -1;
+ }
+ }
+ }
+
+ do {
+ written = fwrite(data, 1, len, file);
+ len -= written;
+ data += written;
+ } while ( written && len );
+ fflush(file);
+
+ return 0;
+}
+
+void
+close_output() {
+ if (file) {
+
+ /* add a newline before closing in case were writing to stdout */
+ if (!output_file.s || (output_file.length && output_file.s[0] == '-'))
+ fwrite("\n", 1, 1, file);
+
+ fflush(file);
+ fclose(file);
+ }
+}
+
+coap_pdu_t *
+new_ack( coap_context_t *ctx, coap_queue_t *node ) {
+ coap_pdu_t *pdu = coap_new_pdu();
+ (void)ctx;
+
+ if (pdu) {
+ pdu->hdr->type = COAP_MESSAGE_ACK;
+ pdu->hdr->code = 0;
+ pdu->hdr->id = node->pdu->hdr->id;
+ }
+
+ return pdu;
+}
+
+coap_pdu_t *
+new_response( coap_context_t *ctx, coap_queue_t *node, unsigned int code ) {
+ coap_pdu_t *pdu = new_ack(ctx, node);
+
+ if (pdu)
+ pdu->hdr->code = code;
+
+ return pdu;
+}
+
+coap_pdu_t *
+coap_new_request(coap_context_t *ctx, method_t m, coap_list_t *options ) {
+ coap_pdu_t *pdu;
+ coap_list_t *opt;
+
+ if ( ! ( pdu = coap_new_pdu() ) )
+ return NULL;
+
+ pdu->hdr->type = msgtype;
+ pdu->hdr->id = coap_new_message_id(ctx);
+ pdu->hdr->code = m;
+
+ pdu->hdr->token_length = the_token.length;
+ if ( !coap_add_token(pdu, the_token.length, the_token.s)) {
+ debug("cannot add token to request\n");
+ }
+
+ coap_show_pdu(pdu);
+
+ for (opt = options; opt; opt = opt->next) {
+ coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)opt->data),
+ COAP_OPTION_LENGTH(*(coap_option *)opt->data),
+ COAP_OPTION_DATA(*(coap_option *)opt->data));
+ }
+
+ if (payload.length) {
+ if ((flags & FLAGS_BLOCK) == 0)
+ coap_add_data(pdu, payload.length, payload.s);
+ else
+ coap_add_block(pdu, payload.length, payload.s, block.num, block.szx);
+ }
+
+ return pdu;
+}
+
+coap_tid_t
+clear_obs(coap_context_t *ctx, const coap_address_t *remote) {
+ coap_list_t *option;
+ coap_pdu_t *pdu;
+ coap_tid_t tid = COAP_INVALID_TID;
+
+ /* create bare PDU w/o any option */
+ pdu = coap_new_request(ctx, COAP_REQUEST_GET, NULL);
+
+ if (pdu) {
+ /* FIXME: add token */
+ /* add URI components from optlist */
+ for (option = optlist; option; option = option->next ) {
+ switch (COAP_OPTION_KEY(*(coap_option *)option->data)) {
+ case COAP_OPTION_URI_HOST :
+ case COAP_OPTION_URI_PORT :
+ case COAP_OPTION_URI_PATH :
+ case COAP_OPTION_URI_QUERY :
+ coap_add_option ( pdu, COAP_OPTION_KEY(*(coap_option *)option->data),
+ COAP_OPTION_LENGTH(*(coap_option *)option->data),
+ COAP_OPTION_DATA(*(coap_option *)option->data) );
+ break;
+ default:
+ ; /* skip other options */
+ }
+ }
+
+ if (pdu->hdr->type == COAP_MESSAGE_CON)
+ tid = coap_send_confirmed(ctx, remote, pdu);
+ else
+ tid = coap_send(ctx, remote, pdu);
+
+ if (tid == COAP_INVALID_TID) {
+ debug("clear_obs: error sending new request");
+ coap_delete_pdu(pdu);
+ } else if (pdu->hdr->type != COAP_MESSAGE_CON)
+ coap_delete_pdu(pdu);
+ }
+ return tid;
+}
+
+int
+resolve_address(const str *server, struct sockaddr *dst) {
+
+ struct addrinfo *res, *ainfo;
+ struct addrinfo hints;
+ static char addrstr[256];
+ int error, len=-1;
+
+
+ memset(addrstr, 0, sizeof(addrstr));
+ if (server->length)
+ memcpy(addrstr, server->s, server->length);
+ else
+ memcpy(addrstr, "localhost", 9);
+
+ OC_LOG_V(DEBUG, MOD_NAME, "Line %d, server %s", __LINE__, addrstr);
+
+ memset ((char *)&hints, 0, sizeof(hints));
+ hints.ai_socktype = SOCK_DGRAM;
+ hints.ai_family = AF_UNSPEC;
+
+ error = getaddrinfo(addrstr, NULL, &hints, &res);
+
+ if (error != 0) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(error));
+ return error;
+ }
+
+ for (ainfo = res; ainfo != NULL; ainfo = ainfo->ai_next) {
+ switch (ainfo->ai_family) {
+ case AF_INET6:
+ case AF_INET:
+ len = ainfo->ai_addrlen;
+ memcpy(dst, ainfo->ai_addr, len);
+ goto finish;
+ default:
+ ;
+ }
+ }
+
+ finish:
+ freeaddrinfo(res);
+ return len;
+}
+
+static inline coap_opt_t *
+get_block(coap_pdu_t *pdu, coap_opt_iterator_t *opt_iter) {
+ coap_opt_filter_t f;
+
+ assert(pdu);
+
+ memset(f, 0, sizeof(coap_opt_filter_t));
+ coap_option_setb(f, COAP_OPTION_BLOCK1);
+ coap_option_setb(f, COAP_OPTION_BLOCK2);
+
+ coap_option_iterator_init(pdu, opt_iter, f);
+ return coap_option_next(opt_iter);
+}
+
+#define HANDLE_BLOCK1(Pdu) \
+ ((method == COAP_REQUEST_PUT || method == COAP_REQUEST_POST) && \
+ ((flags & FLAGS_BLOCK) == 0) && \
+ ((Pdu)->hdr->code == COAP_RESPONSE_CODE(201) || \
+ (Pdu)->hdr->code == COAP_RESPONSE_CODE(204)))
+
+inline int
+check_token(coap_pdu_t *received) {
+ return received->hdr->token_length == the_token.length &&
+ memcmp(received->hdr->token, the_token.s, the_token.length) == 0;
+}
+
+void
+message_handler(struct coap_context_t *ctx,
+ const coap_address_t *remote,
+ coap_pdu_t *sent,
+ coap_pdu_t *received,
+ const coap_tid_t id) {
+
+ coap_pdu_t *pdu = NULL;
+ coap_opt_t *block_opt;
+ coap_opt_iterator_t opt_iter;
+ unsigned char buf[4];
+ coap_list_t *option;
+ size_t len;
+ unsigned char *databuf;
+ coap_tid_t tid;
+ (void)id;
+
+#ifndef NDEBUG
+ if (LOG_DEBUG <= coap_get_log_level()) {
+ debug("** process incoming %d.%02d response:\n",
+ (received->hdr->code >> 5), received->hdr->code & 0x1F);
+ coap_show_pdu(received);
+ }
+#endif
+
+ /* check if this is a response to our original request */
+ if (!check_token(received)) {
+ /* drop if this was just some message, or send RST in case of notification */
+ if (!sent && (received->hdr->type == COAP_MESSAGE_CON ||
+ received->hdr->type == COAP_MESSAGE_NON))
+ coap_send_rst(ctx, remote, received);
+ return;
+ }
+
+ switch (received->hdr->type) {
+ case COAP_MESSAGE_CON:
+ /* acknowledge received response if confirmable (TODO: check Token) */
+ coap_send_ack(ctx, remote, received);
+ break;
+ case COAP_MESSAGE_RST:
+ info("got RST\n");
+ return;
+ default:
+ ;
+ }
+
+ /* output the received data, if any */
+ if (received->hdr->code == COAP_RESPONSE_CODE(205)) {
+
+ /* set obs timer if we have successfully subscribed a resource */
+ if (sent && coap_check_option(received, COAP_OPTION_SUBSCRIPTION, &opt_iter)) {
+ debug("observation relationship established, set timeout to %d\n", obs_seconds);
+ set_timeout(&obs_wait, obs_seconds);
+ }
+
+ /* Got some data, check if block option is set. Behavior is undefined if
+ * both, Block1 and Block2 are present. */
+ block_opt = get_block(received, &opt_iter);
+ if (!block_opt) {
+ /* There is no block option set, just read the data and we are done. */
+ if (coap_get_data(received, &len, &databuf))
+ append_to_output(databuf, len);
+ } else {
+ unsigned short blktype = opt_iter.type;
+
+ /* TODO: check if we are looking at the correct block number */
+ if (coap_get_data(received, &len, &databuf))
+ append_to_output(databuf, len);
+
+ if (COAP_OPT_BLOCK_MORE(block_opt)) {
+ /* more bit is set */
+ debug("found the M bit, block size is %u, block nr. %u\n",
+ COAP_OPT_BLOCK_SZX(block_opt), coap_opt_block_num(block_opt));
+
+ /* create pdu with request for next block */
+ pdu = coap_new_request(ctx, method, NULL); /* first, create bare PDU w/o any option */
+ if ( pdu ) {
+ /* add URI components from optlist */
+ for (option = optlist; option; option = option->next ) {
+ switch (COAP_OPTION_KEY(*(coap_option *)option->data)) {
+ case COAP_OPTION_URI_HOST :
+ case COAP_OPTION_URI_PORT :
+ case COAP_OPTION_URI_PATH :
+ case COAP_OPTION_URI_QUERY :
+ coap_add_option ( pdu, COAP_OPTION_KEY(*(coap_option *)option->data),
+ COAP_OPTION_LENGTH(*(coap_option *)option->data),
+ COAP_OPTION_DATA(*(coap_option *)option->data) );
+ break;
+ default:
+ ; /* skip other options */
+ }
+ }
+
+ /* finally add updated block option from response, clear M bit */
+ /* blocknr = (blocknr & 0xfffffff7) + 0x10; */
+ debug("query block %d\n", (coap_opt_block_num(block_opt) + 1));
+ coap_add_option(pdu, blktype, coap_encode_var_bytes(buf,
+ ((coap_opt_block_num(block_opt) + 1) << 4) |
+ COAP_OPT_BLOCK_SZX(block_opt)), buf);
+
+ if (received->hdr->type == COAP_MESSAGE_CON)
+ tid = coap_send_confirmed(ctx, remote, pdu);
+ else
+ tid = coap_send(ctx, remote, pdu);
+
+ if (tid == COAP_INVALID_TID) {
+ debug("message_handler: error sending new request");
+ coap_delete_pdu(pdu);
+ } else {
+ set_timeout(&max_wait, wait_seconds);
+ if (received->hdr->type != COAP_MESSAGE_CON)
+ coap_delete_pdu(pdu);
+ }
+
+ return;
+ }
+ }
+ }
+ } else { /* no 2.05 */
+
+ /* check if an error was signaled and output payload if so */
+ if (COAP_RESPONSE_CLASS(received->hdr->code) >= 4) {
+ fprintf(stderr, "%d.%02d",
+ (received->hdr->code >> 5), received->hdr->code & 0x1F);
+ if (coap_get_data(received, &len, &databuf)) {
+ fprintf(stderr, " ");
+ while(len--)
+ fprintf(stderr, "%c", *databuf++);
+ }
+ fprintf(stderr, "\n");
+ }
+
+ }
+
+ /* finally send new request, if needed */
+ if (pdu && coap_send(ctx, remote, pdu) == COAP_INVALID_TID) {
+ debug("message_handler: error sending response");
+ }
+ coap_delete_pdu(pdu);
+
+ /* our job is done, we can exit at any time */
+ ready = coap_check_option(received, COAP_OPTION_SUBSCRIPTION, &opt_iter) == NULL;
+}
+
+void
+usage( const char *program, const char *version) {
+ const char *p;
+
+ p = strrchr( program, '/' );
+ if ( p )
+ program = ++p;
+
+ fprintf( stderr, "%s v%s -- a small CoAP implementation\n"
+ "(c) 2010-2013 Olaf Bergmann <bergmann@tzi.org>\n\n"
+ "usage: %s [-A type...] [-t type] [-b [num,]size] [-B seconds] [-e text]\n"
+ "\t\t[-g group] [-m method] [-N] [-o file] [-P addr[:port]] [-p port]\n"
+ "\t\t[-s duration] [-O num,text] [-T string] [-v num] URI\n\n"
+ "\tURI can be an absolute or relative coap URI,\n"
+ "\t-A type...\taccepted media types as comma-separated list of\n"
+ "\t\t\tsymbolic or numeric values\n"
+ "\t-t type\t\tcontent type for given resource for PUT/POST\n"
+ "\t-b [num,]size\tblock size to be used in GET/PUT/POST requests\n"
+ "\t \t\t(value must be a multiple of 16 not larger than 1024)\n"
+ "\t \t\tIf num is present, the request chain will start at\n"
+ "\t \t\tblock num\n"
+ "\t-B seconds\tbreak operation after waiting given seconds\n"
+ "\t\t\t(default is %d)\n"
+ "\t-e text\t\tinclude text as payload (use percent-encoding for\n"
+ "\t\t\tnon-ASCII characters)\n"
+ "\t-f file\t\tfile to send with PUT/POST (use '-' for STDIN)\n"
+ "\t-g group\tjoin the given multicast group\n"
+ "\t-m method\trequest method (get|put|post|delete), default is 'get'\n"
+ "\t-N\t\tsend NON-confirmable message\n"
+ "\t-o file\t\toutput received data to this file (use '-' for STDOUT)\n"
+ "\t-p port\t\tlisten on specified port\n"
+ "\t-s duration\tsubscribe for given duration [s]\n"
+ "\t-v num\t\tverbosity level (default: 3)\n"
+ "\t-O num,text\tadd option num with contents text to request\n"
+ "\t-P addr[:port]\tuse proxy (automatically adds Proxy-Uri option to\n"
+ "\t\t\trequest)\n"
+ "\t-T token\tinclude specified token\n"
+ "\n"
+ "examples:\n"
+ "\tcoap-client -m get coap://[::1]/\n"
+ "\tcoap-client -m get coap://[::1]/.well-known/core\n"
+ "\tcoap-client -m get -T cafe coap://[::1]/time\n"
+ "\techo 1000 | coap-client -m put -T cafe coap://[::1]/time -f -\n"
+ ,program, version, program, wait_seconds);
+}
+
+int
+join( coap_context_t *ctx, char *group_name ){
+ struct ipv6_mreq mreq;
+ struct addrinfo *reslocal = NULL, *resmulti = NULL, hints, *ainfo;
+ int result = -1;
+
+ /* we have to resolve the link-local interface to get the interface id */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ result = getaddrinfo("::", NULL, &hints, &reslocal);
+ if ( result < 0 ) {
+ fprintf(stderr, "join: cannot resolve link-local interface: %s\n",
+ gai_strerror(result));
+ goto finish;
+ }
+
+ /* get the first suitable interface identifier */
+ for (ainfo = reslocal; ainfo != NULL; ainfo = ainfo->ai_next) {
+ if ( ainfo->ai_family == AF_INET6 ) {
+ mreq.ipv6mr_interface =
+ ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_scope_id;
+ break;
+ }
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ /* resolve the multicast group address */
+ result = getaddrinfo(group_name, NULL, &hints, &resmulti);
+
+ if ( result < 0 ) {
+ fprintf(stderr, "join: cannot resolve multicast address: %s\n",
+ gai_strerror(result));
+ goto finish;
+ }
+
+ for (ainfo = resmulti; ainfo != NULL; ainfo = ainfo->ai_next) {
+ if ( ainfo->ai_family == AF_INET6 ) {
+ mreq.ipv6mr_multiaddr =
+ ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_addr;
+ break;
+ }
+ }
+
+ result = setsockopt( ctx->sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ (char *)&mreq, sizeof(mreq) );
+ if ( result < 0 )
+ perror("join: setsockopt");
+
+ finish:
+ freeaddrinfo(resmulti);
+ freeaddrinfo(reslocal);
+
+ return result;
+}
+
+int
+order_opts(void *a, void *b) {
+ if (!a || !b)
+ return a < b ? -1 : 1;
+
+ if (COAP_OPTION_KEY(*(coap_option *)a) < COAP_OPTION_KEY(*(coap_option *)b))
+ return -1;
+
+ return COAP_OPTION_KEY(*(coap_option *)a) == COAP_OPTION_KEY(*(coap_option *)b);
+}
+
+
+coap_list_t *
+new_option_node(unsigned short key, unsigned int length, unsigned char *data) {
+ coap_option *option;
+ coap_list_t *node;
+
+ option = coap_malloc(sizeof(coap_option) + length);
+ if ( !option )
+ goto error;
+
+ COAP_OPTION_KEY(*option) = key;
+ COAP_OPTION_LENGTH(*option) = length;
+ memcpy(COAP_OPTION_DATA(*option), data, length);
+
+ /* we can pass NULL here as delete function since option is released automatically */
+ node = coap_new_listnode(option, NULL);
+
+ if ( node )
+ return node;
+
+ error:
+ perror("new_option_node: malloc");
+ coap_free( option );
+ return NULL;
+}
+
+typedef struct {
+ unsigned char code;
+ char *media_type;
+} content_type_t;
+
+void
+cmdline_content_type(char *arg, unsigned short key) {
+ static content_type_t content_types[] = {
+ { 0, "plain" },
+ { 0, "text/plain" },
+ { 40, "link" },
+ { 40, "link-format" },
+ { 40, "application/link-format" },
+ { 41, "xml" },
+ { 42, "binary" },
+ { 42, "octet-stream" },
+ { 42, "application/octet-stream" },
+ { 47, "exi" },
+ { 47, "application/exi" },
+ { 50, "json" },
+ { 50, "application/json" },
+ { 255, NULL }
+ };
+ coap_list_t *node;
+ unsigned char i, value[10];
+ int valcnt = 0;
+ unsigned char buf[2];
+ char *p, *q = arg;
+
+ while (q && *q) {
+ p = strchr(q, ',');
+
+ if (isdigit(*q)) {
+ if (p)
+ *p = '\0';
+ value[valcnt++] = atoi(q);
+ } else {
+ for (i=0; content_types[i].media_type &&
+ strncmp(q,content_types[i].media_type, p ? p-q : strlen(q)) != 0 ;
+ ++i)
+ ;
+
+ if (content_types[i].media_type) {
+ value[valcnt] = content_types[i].code;
+ valcnt++;
+ } else {
+ warn("W: unknown content-type '%s'\n",arg);
+ }
+ }
+
+ if (!p || key == COAP_OPTION_CONTENT_TYPE)
+ break;
+
+ q = p+1;
+ }
+
+ for (i = 0; i < valcnt; ++i) {
+ node = new_option_node(key, coap_encode_var_bytes(buf, value[i]), buf);
+ if (node)
+ coap_insert( &optlist, node, order_opts );
+ }
+}
+
+void
+cmdline_uri(char *arg) {
+ unsigned char portbuf[2];
+#define BUFSIZE 40
+ unsigned char _buf[BUFSIZE];
+ unsigned char *buf = _buf;
+ size_t buflen;
+ int res;
+
+ if (proxy.length) { /* create Proxy-Uri from argument */
+ size_t len = strlen(arg);
+ while (len > 270) {
+ coap_insert(&optlist,
+ new_option_node(COAP_OPTION_PROXY_URI,
+ 270, (unsigned char *)arg),
+ order_opts);
+ len -= 270;
+ arg += 270;
+ }
+
+ coap_insert(&optlist,
+ new_option_node(COAP_OPTION_PROXY_URI,
+ len, (unsigned char *)arg),
+ order_opts);
+ } else { /* split arg into Uri-* options */
+ coap_split_uri((unsigned char *)arg, strlen(arg), &uri );
+
+ if (uri.port != COAP_DEFAULT_PORT) {
+ coap_insert( &optlist,
+ new_option_node(COAP_OPTION_URI_PORT,
+ coap_encode_var_bytes(portbuf, uri.port),
+ portbuf),
+ order_opts);
+ }
+
+ if (uri.path.length) {
+ buflen = BUFSIZE;
+ res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
+
+ while (res--) {
+ coap_insert(&optlist, new_option_node(COAP_OPTION_URI_PATH,
+ COAP_OPT_LENGTH(buf),
+ COAP_OPT_VALUE(buf)),
+ order_opts);
+
+ buf += COAP_OPT_SIZE(buf);
+ }
+ }
+
+ if (uri.query.length) {
+ buflen = BUFSIZE;
+ buf = _buf;
+ res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
+
+ while (res--) {
+ coap_insert(&optlist, new_option_node(COAP_OPTION_URI_QUERY,
+ COAP_OPT_LENGTH(buf),
+ COAP_OPT_VALUE(buf)),
+ order_opts);
+
+ buf += COAP_OPT_SIZE(buf);
+ }
+ }
+ }
+}
+
+int
+cmdline_blocksize(char *arg) {
+ unsigned short size;
+
+ again:
+ size = 0;
+ while(*arg && *arg != ',')
+ size = size * 10 + (*arg++ - '0');
+
+ if (*arg == ',') {
+ arg++;
+ block.num = size;
+ goto again;
+ }
+
+ if (size)
+ block.szx = (coap_fls(size >> 4) - 1) & 0x07;
+
+ flags |= FLAGS_BLOCK;
+ return 1;
+}
+
+/* Called after processing the options from the commandline to set
+ * Block1 or Block2 depending on method. */
+void
+set_blocksize() {
+ static unsigned char buf[4]; /* hack: temporarily take encoded bytes */
+ unsigned short opt;
+
+ if (method != COAP_REQUEST_DELETE) {
+ opt = method == COAP_REQUEST_GET ? COAP_OPTION_BLOCK2 : COAP_OPTION_BLOCK1;
+
+ coap_insert(&optlist, new_option_node(opt,
+ coap_encode_var_bytes(buf, (block.num << 4 | block.szx)), buf),
+ order_opts);
+ }
+}
+
+void
+cmdline_subscribe(char *arg) {
+ (void)arg;
+ obs_seconds = atoi(optarg);
+ coap_insert(&optlist, new_option_node(COAP_OPTION_SUBSCRIPTION, 0, NULL),
+ order_opts);
+}
+
+int
+cmdline_proxy(char *arg) {
+ char *proxy_port_str = strrchr((const char *)arg, ':'); /* explicit port ? */
+ if (proxy_port_str) {
+ char *ipv6_delimiter = strrchr((const char *)arg, ']');
+ if (!ipv6_delimiter) {
+ if (proxy_port_str == strchr((const char *)arg, ':')) {
+ /* host:port format - host not in ipv6 hexadecimal string format */
+ *proxy_port_str++ = '\0'; /* split */
+ proxy_port = atoi(proxy_port_str);
+ }
+ } else {
+ arg = strchr((const char *)arg, '[');
+ if (!arg) return 0;
+ arg++;
+ *ipv6_delimiter = '\0'; /* split */
+ if (ipv6_delimiter + 1 == proxy_port_str++) {
+ /* [ipv6 address]:port */
+ proxy_port = atoi(proxy_port_str);
+ }
+ }
+ }
+
+ proxy.length = strlen(arg);
+ if ( (proxy.s = coap_malloc(proxy.length + 1)) == NULL) {
+ proxy.length = 0;
+ return 0;
+ }
+
+ memcpy(proxy.s, arg, proxy.length+1);
+ return 1;
+}
+
+inline void
+cmdline_token(char *arg) {
+ strncpy((char *)the_token.s, arg, min(sizeof(_token_data), strlen(arg)));
+ the_token.length = strlen(arg);
+}
+
+void
+cmdline_option(char *arg) {
+ unsigned int num = 0;
+
+ while (*arg && *arg != ',') {
+ num = num * 10 + (*arg - '0');
+ ++arg;
+ }
+ if (*arg == ',')
+ ++arg;
+
+ coap_insert( &optlist, new_option_node(num,
+ strlen(arg),
+ (unsigned char *)arg), order_opts);
+}
+
+extern int check_segment(const unsigned char *s, size_t length);
+extern void decode_segment(const unsigned char *seg, size_t length, unsigned char *buf);
+
+int
+cmdline_input(char *text, str *buf) {
+ int len;
+ len = check_segment((unsigned char *)text, strlen(text));
+
+ if (len < 0)
+ return 0;
+
+ buf->s = (unsigned char *)coap_malloc(len);
+ if (!buf->s)
+ return 0;
+
+ buf->length = len;
+ decode_segment((unsigned char *)text, strlen(text), buf->s);
+ return 1;
+}
+
+int
+cmdline_input_from_file(char *filename, str *buf) {
+ FILE *inputfile = NULL;
+ size_t len;
+ int result = 1;
+ struct stat statbuf;
+
+ if (!filename || !buf)
+ return 0;
+
+ if (filename[0] == '-' && !filename[1]) { /* read from stdin */
+ buf->length = 20000;
+ buf->s = (unsigned char *)coap_malloc(buf->length);
+ if (!buf->s)
+ return 0;
+
+ inputfile = stdin;
+ } else {
+ /* read from specified input file */
+ if (stat(filename, &statbuf) < 0) {
+ perror("cmdline_input_from_file: stat");
+ return 0;
+ }
+
+ buf->length = statbuf.st_size;
+ buf->s = (unsigned char *)coap_malloc(buf->length);
+ if (!buf->s)
+ return 0;
+
+ inputfile = fopen(filename, "r");
+ if ( !inputfile ) {
+ perror("cmdline_input_from_file: fopen");
+ coap_free(buf->s);
+ return 0;
+ }
+ }
+
+ len = fread(buf->s, 1, buf->length, inputfile);
+
+ if (len < buf->length) {
+ if (ferror(inputfile) != 0) {
+ perror("cmdline_input_from_file: fread");
+ coap_free(buf->s);
+ buf->length = 0;
+ buf->s = NULL;
+ result = 0;
+ } else {
+ buf->length = len;
+ }
+ }
+
+ if (inputfile != stdin)
+ fclose(inputfile);
+
+ return result;
+}
+
+method_t
+cmdline_method(char *arg) {
+ static char *methods[] =
+ { 0, "get", "post", "put", "delete", 0};
+ unsigned char i;
+
+ for (i=1; methods[i] && strcasecmp(arg,methods[i]) != 0 ; ++i)
+ ;
+
+ return i; /* note that we do not prevent illegal methods */
+}
+
+coap_context_t *
+get_context(const char *node, const char *port) {
+ coap_context_t *ctx = NULL;
+ int s;
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */
+#ifndef __ANDROID__
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL;
+#endif //__ANDROID__
+
+
+ OC_LOG_V(DEBUG, MOD_NAME, "Line %d, node %s, port %d", __LINE__, node, port);
+ s = getaddrinfo(node, port, &hints, &result);
+ if ( s != 0 ) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
+ return NULL;
+ }
+
+ /* iterate through results until success */
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ coap_address_t addr;
+
+ if (rp->ai_addrlen <= sizeof(addr.addr)) {
+ coap_address_init(&addr);
+ addr.size = rp->ai_addrlen;
+ memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen);
+
+ ctx = coap_new_context(&addr);
+ if (ctx) {
+ /* TODO: output address:port for successful binding */
+ goto finish;
+ }
+ }
+ }
+
+ fprintf(stderr, "no context available for interface '%s'\n", node);
+
+ finish:
+ freeaddrinfo(result);
+ return ctx;
+}
+
+int
+main(int argc, char **argv) {
+ coap_context_t *ctx = NULL;
+ coap_address_t dst;
+ static char addr[INET6_ADDRSTRLEN];
+ void *addrptr = NULL;
+ fd_set readfds;
+ struct timeval tv;
+ int result;
+ coap_tick_t now;
+ coap_queue_t *nextpdu;
+ coap_pdu_t *pdu;
+ static str server;
+ unsigned short port = COAP_DEFAULT_PORT;
+ char port_str[NI_MAXSERV] = "0";
+ int opt, res;
+ char *group = NULL;
+ coap_log_t log_level = LOG_WARNING;
+ coap_tid_t tid = COAP_INVALID_TID;
+
+ while ((opt = getopt(argc, argv, "Nb:e:f:g:m:p:s:t:o:v:A:B:O:P:T:")) != -1) {
+ switch (opt) {
+ case 'b' :
+ cmdline_blocksize(optarg);
+ break;
+ case 'B' :
+ wait_seconds = atoi(optarg);
+ break;
+ case 'e' :
+ if (!cmdline_input(optarg,&payload))
+ payload.length = 0;
+ break;
+ case 'f' :
+ if (!cmdline_input_from_file(optarg,&payload))
+ payload.length = 0;
+ break;
+ case 'g' :
+ group = optarg;
+ break;
+ case 'p' :
+ strncpy(port_str, optarg, NI_MAXSERV-1);
+ port_str[NI_MAXSERV - 1] = '\0';
+ break;
+ case 'm' :
+ method = cmdline_method(optarg);
+ break;
+ case 'N' :
+ msgtype = COAP_MESSAGE_NON;
+ break;
+ case 's' :
+ cmdline_subscribe(optarg);
+ break;
+ case 'o' :
+ output_file.length = strlen(optarg);
+ output_file.s = (unsigned char *)coap_malloc(output_file.length + 1);
+
+ if (!output_file.s) {
+ fprintf(stderr, "cannot set output file: insufficient memory\n");
+ exit(-1);
+ } else {
+ /* copy filename including trailing zero */
+ memcpy(output_file.s, optarg, output_file.length + 1);
+ }
+ break;
+ case 'A' :
+ cmdline_content_type(optarg,COAP_OPTION_ACCEPT);
+ break;
+ case 't' :
+ cmdline_content_type(optarg,COAP_OPTION_CONTENT_TYPE);
+ break;
+ case 'O' :
+ cmdline_option(optarg);
+ break;
+ case 'P' :
+ if (!cmdline_proxy(optarg)) {
+ fprintf(stderr, "error specifying proxy address\n");
+ exit(-1);
+ }
+ break;
+ case 'T' :
+ cmdline_token(optarg);
+ break;
+ case 'v' :
+ log_level = strtol(optarg, NULL, 10);
+ break;
+ default:
+ usage( argv[0], PACKAGE_VERSION );
+ exit( 1 );
+ }
+ }
+
+ coap_set_log_level(log_level);
+
+ if ( optind < argc )
+ cmdline_uri( argv[optind] );
+ else {
+ usage( argv[0], PACKAGE_VERSION );
+ exit( 1 );
+ }
+
+ if (proxy.length) {
+ server = proxy;
+ port = proxy_port;
+ } else {
+ server = uri.host;
+ port = uri.port;
+ }
+
+ /* resolve destination address where server should be sent */
+ res = resolve_address(&server, &dst.addr.sa);
+
+ if (res < 0) {
+ fprintf(stderr, "failed to resolve address\n");
+ exit(-1);
+ }
+
+ dst.size = res;
+ dst.addr.sin.sin_port = htons(port);
+
+ /* add Uri-Host if server address differs from uri.host */
+
+ switch (dst.addr.sa.sa_family) {
+ case AF_INET:
+ addrptr = &dst.addr.sin.sin_addr;
+
+ /* create context for IPv4 */
+ ctx = get_context("0.0.0.0", port_str);
+ break;
+ case AF_INET6:
+ addrptr = &dst.addr.sin6.sin6_addr;
+
+ /* create context for IPv6 */
+ ctx = get_context("::", port_str);
+ break;
+ default:
+ ;
+ }
+
+ if (!ctx) {
+ coap_log(LOG_EMERG, "cannot create context\n");
+ return -1;
+ }
+
+ coap_register_option(ctx, COAP_OPTION_BLOCK2);
+ coap_register_response_handler(ctx, message_handler);
+
+ /* join multicast group if requested at command line */
+ if (group)
+ join(ctx, group);
+
+ /* construct CoAP message */
+
+ if (!proxy.length && addrptr
+ && (inet_ntop(dst.addr.sa.sa_family, addrptr, addr, sizeof(addr)) != 0)
+ && (strlen(addr) != uri.host.length
+ || memcmp(addr, uri.host.s, uri.host.length) != 0)) {
+ /* add Uri-Host */
+
+ coap_insert(&optlist, new_option_node(COAP_OPTION_URI_HOST,
+ uri.host.length, uri.host.s),
+ order_opts);
+ }
+
+ /* set block option if requested at commandline */
+ if (flags & FLAGS_BLOCK)
+ set_blocksize();
+
+ if (! (pdu = coap_new_request(ctx, method, optlist)))
+ return -1;
+
+#ifndef NDEBUG
+ if (LOG_DEBUG <= coap_get_log_level()) {
+ debug("sending CoAP request:\n");
+ coap_show_pdu(pdu);
+ }
+#endif
+
+ if (pdu->hdr->type == COAP_MESSAGE_CON)
+ tid = coap_send_confirmed(ctx, &dst, pdu);
+ else
+ tid = coap_send(ctx, &dst, pdu);
+
+ if (pdu->hdr->type != COAP_MESSAGE_CON || tid == COAP_INVALID_TID)
+ coap_delete_pdu(pdu);
+
+ set_timeout(&max_wait, wait_seconds);
+ debug("timeout is set to %d seconds\n", wait_seconds);
+
+ while ( !(ready && coap_can_exit(ctx)) ) {
+ FD_ZERO(&readfds);
+ FD_SET( ctx->sockfd, &readfds );
+
+ nextpdu = coap_peek_next( ctx );
+
+ coap_ticks(&now);
+ while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) {
+ coap_retransmit( ctx, coap_pop_next( ctx ));
+ nextpdu = coap_peek_next( ctx );
+ }
+
+ if (nextpdu && nextpdu->t < min(obs_wait ? obs_wait : max_wait, max_wait) - now) {
+ /* set timeout if there is a pdu to send */
+ tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND;
+ tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND;
+ } else {
+ /* check if obs_wait fires before max_wait */
+ if (obs_wait && obs_wait < max_wait) {
+ tv.tv_usec = ((obs_wait - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND;
+ tv.tv_sec = (obs_wait - now) / COAP_TICKS_PER_SECOND;
+ } else {
+ tv.tv_usec = ((max_wait - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND;
+ tv.tv_sec = (max_wait - now) / COAP_TICKS_PER_SECOND;
+ }
+ }
+
+ result = select(ctx->sockfd + 1, &readfds, 0, 0, &tv);
+
+ if ( result < 0 ) { /* error */
+ perror("select");
+ } else if ( result > 0 ) { /* read from socket */
+ if ( FD_ISSET( ctx->sockfd, &readfds ) ) {
+ coap_read( ctx, ctx->sockfd ); /* read received data */
+ coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */
+ }
+ } else { /* timeout */
+ coap_ticks(&now);
+ if (max_wait <= now) {
+ info("timeout\n");
+ break;
+ }
+ if (obs_wait && obs_wait <= now) {
+ debug("clear observation relationship\n");
+ clear_obs(ctx, &dst); /* FIXME: handle error case COAP_TID_INVALID */
+
+ /* make sure that the obs timer does not fire again */
+ obs_wait = 0;
+ obs_seconds = 0;
+ }
+ }
+ }
+
+ close_output();
+
+ coap_free_context( ctx );
+
+ return 0;
+}
--- /dev/null
+/* coap -- simple implementation of the Constrained Application Protocol (CoAP)
+ * as defined in draft-ietf-core-coap
+ *
+ * Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+
+/**
+ * @file rd.c
+ * @brief CoRE resource directory
+ *
+ * @see http://tools.ietf.org/id/draft-shelby-core-resource-directory
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "config.h"
+#include "utlist.h"
+#include "resource.h"
+#include "coap.h"
+
+#define COAP_RESOURCE_CHECK_TIME 2
+
+#define RD_ROOT_STR ((unsigned char *)"rd")
+#define RD_ROOT_SIZE 2
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+typedef struct rd_t {
+ UT_hash_handle hh; /**< hash handle (for internal use only) */
+ coap_key_t key; /**< the actual key bytes for this resource */
+
+ size_t etag_len; /**< actual length of @c etag */
+ unsigned char etag[8]; /**< ETag for current description */
+
+ str data; /**< points to the resource description */
+} rd_t;
+
+rd_t *resources = NULL;
+
+inline rd_t *
+rd_new() {
+ rd_t *rd;
+ rd = (rd_t *)coap_malloc(sizeof(rd_t));
+ if (rd)
+ memset(rd, 0, sizeof(rd_t));
+
+ return rd;
+}
+
+inline void
+rd_delete(rd_t *rd) {
+ if (rd) {
+ coap_free(rd->data.s);
+ coap_free(rd);
+ }
+}
+
+/* temporary storage for dynamic resource representations */
+static int quit = 0;
+
+/* SIGINT handler: set quit to 1 for graceful termination */
+void
+handle_sigint(int signum) {
+ quit = 1;
+}
+
+void
+hnd_get_resource(coap_context_t *ctx, struct coap_resource_t *resource,
+ coap_address_t *peer, coap_pdu_t *request, str *token,
+ coap_pdu_t *response) {
+ rd_t *rd = NULL;
+ unsigned char buf[3];
+
+ HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd);
+
+ response->hdr->code = COAP_RESPONSE_CODE(205);
+
+ coap_add_option(response, COAP_OPTION_CONTENT_TYPE,
+ coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf);
+
+ if (rd && rd->etag_len)
+ coap_add_option(response, COAP_OPTION_ETAG, rd->etag_len, rd->etag);
+
+ if (rd && rd->data.s)
+ coap_add_data(response, rd->data.length, rd->data.s);
+}
+
+void
+hnd_put_resource(coap_context_t *ctx, struct coap_resource_t *resource,
+ coap_address_t *peer, coap_pdu_t *request, str *token,
+ coap_pdu_t *response) {
+#if 1
+ response->hdr->code = COAP_RESPONSE_CODE(501);
+#else /* FIXME */
+ coap_opt_iterator_t opt_iter;
+ coap_opt_t *token, *etag;
+ coap_pdu_t *response;
+ size_t size = sizeof(coap_hdr_t);
+ int type = (request->hdr->type == COAP_MESSAGE_CON)
+ ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON;
+ rd_t *rd = NULL;
+ unsigned char code; /* result code */
+ unsigned char *data;
+ str tmp;
+
+ HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd);
+ if (rd) {
+ /* found resource object, now check Etag */
+ etag = coap_check_option(request, COAP_OPTION_ETAG, &opt_iter);
+ if (!etag || (COAP_OPT_LENGTH(etag) != rd->etag_len)
+ || memcmp(COAP_OPT_VALUE(etag), rd->etag, rd->etag_len) != 0) {
+
+ if (coap_get_data(request, &tmp.length, &data)) {
+
+ tmp.s = (unsigned char *)coap_malloc(tmp.length);
+ if (!tmp.s) {
+ debug("hnd_put_rd: cannot allocate storage for new rd\n");
+ code = COAP_RESPONSE_CODE(503);
+ goto finish;
+ }
+
+ coap_free(rd->data.s);
+ rd->data.s = tmp.s;
+ rd->data.length = tmp.length;
+ memcpy(rd->data.s, data, rd->data.length);
+ }
+ }
+
+ if (etag) {
+ rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag));
+ memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len);
+ }
+
+ code = COAP_RESPONSE_CODE(204);
+ /* FIXME: update lifetime */
+
+ } else {
+
+ code = COAP_RESPONSE_CODE(503);
+ }
+
+ finish:
+ /* FIXME: do not create a new response but use the old one instead */
+ response = coap_pdu_init(type, code, request->hdr->id, size);
+
+ if (!response) {
+ debug("cannot create response for message %d\n", request->hdr->id);
+ return;
+ }
+
+ if (request->hdr->token_length)
+ coap_add_token(response, request->hdr->token_length, request->hdr->token);
+
+ if (coap_send(ctx, peer, response) == COAP_INVALID_TID) {
+ debug("hnd_get_rd: cannot send response for message %d\n",
+ request->hdr->id);
+ }
+ coap_delete_pdu(response);
+#endif
+}
+
+void
+hnd_delete_resource(coap_context_t *ctx, struct coap_resource_t *resource,
+ coap_address_t *peer, coap_pdu_t *request, str *token,
+ coap_pdu_t *response) {
+ rd_t *rd = NULL;
+
+ HASH_FIND(hh, resources, resource->key, sizeof(coap_key_t), rd);
+ if (rd) {
+ HASH_DELETE(hh, resources, rd);
+ rd_delete(rd);
+ }
+ /* FIXME: link attributes for resource have been created dynamically
+ * using coap_malloc() and must be released. */
+ coap_delete_resource(ctx, resource->key);
+
+ response->hdr->code = COAP_RESPONSE_CODE(202);
+}
+
+void
+hnd_get_rd(coap_context_t *ctx, struct coap_resource_t *resource,
+ coap_address_t *peer, coap_pdu_t *request, str *token,
+ coap_pdu_t *response) {
+ unsigned char buf[3];
+
+ response->hdr->code = COAP_RESPONSE_CODE(205);
+
+ coap_add_option(response, COAP_OPTION_CONTENT_TYPE,
+ coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT), buf);
+
+ coap_add_option(response, COAP_OPTION_MAXAGE,
+ coap_encode_var_bytes(buf, 0x2ffff), buf);
+}
+
+int
+parse_param(unsigned char *search, size_t search_len,
+ unsigned char *data, size_t data_len, str *result) {
+
+ if (result)
+ memset(result, 0, sizeof(str));
+
+ if (!search_len)
+ return 0;
+
+ while (search_len <= data_len) {
+
+ /* handle parameter if found */
+ if (memcmp(search, data, search_len) == 0) {
+ data += search_len;
+ data_len -= search_len;
+
+ /* key is only valid if we are at end of string or delimiter follows */
+ if (!data_len || *data == '=' || *data == '&') {
+ while (data_len && *data != '=') {
+ ++data; --data_len;
+ }
+
+ if (data_len > 1 && result) {
+ /* value begins after '=' */
+
+ result->s = ++data;
+ while (--data_len && *data != '&') {
+ ++data; result->length++;
+ }
+ }
+
+ return 1;
+ }
+ }
+
+ /* otherwise proceed to next */
+ while (--data_len && *data++ != '&')
+ ;
+ }
+
+ return 0;
+}
+
+void
+add_source_address(struct coap_resource_t *resource, coap_address_t *peer) {
+#define BUFSIZE 64
+ char *buf;
+ size_t n = 1;
+
+ buf = (char *)coap_malloc(BUFSIZE);
+ if (!buf)
+ return;
+
+ buf[0] = '"';
+
+ switch(peer->addr.sa.sa_family) {
+
+ case AF_INET:
+ /* FIXME */
+ break;
+
+ case AF_INET6:
+ n += snprintf(buf + n, BUFSIZE - n,
+ "[%02x%02x:%02x%02x:%02x%02x:%02x%02x" \
+ ":%02x%02x:%02x%02x:%02x%02x:%02x%02x]",
+ peer->addr.sin6.sin6_addr.s6_addr[0],
+ peer->addr.sin6.sin6_addr.s6_addr[1],
+ peer->addr.sin6.sin6_addr.s6_addr[2],
+ peer->addr.sin6.sin6_addr.s6_addr[3],
+ peer->addr.sin6.sin6_addr.s6_addr[4],
+ peer->addr.sin6.sin6_addr.s6_addr[5],
+ peer->addr.sin6.sin6_addr.s6_addr[6],
+ peer->addr.sin6.sin6_addr.s6_addr[7],
+ peer->addr.sin6.sin6_addr.s6_addr[8],
+ peer->addr.sin6.sin6_addr.s6_addr[9],
+ peer->addr.sin6.sin6_addr.s6_addr[10],
+ peer->addr.sin6.sin6_addr.s6_addr[11],
+ peer->addr.sin6.sin6_addr.s6_addr[12],
+ peer->addr.sin6.sin6_addr.s6_addr[13],
+ peer->addr.sin6.sin6_addr.s6_addr[14],
+ peer->addr.sin6.sin6_addr.s6_addr[15]);
+
+ if (peer->addr.sin6.sin6_port != htons(COAP_DEFAULT_PORT)) {
+ n +=
+ snprintf(buf + n, BUFSIZE - n, ":%d", peer->addr.sin6.sin6_port);
+ }
+ break;
+ default:
+ ;
+ }
+
+ if (n < BUFSIZE)
+ buf[n++] = '"';
+
+ coap_add_attr(resource, (unsigned char *)"A", 1, (unsigned char *)buf, n, COAP_ATTR_FLAGS_RELEASE_VALUE);
+#undef BUFSIZE
+}
+
+
+rd_t *
+make_rd(coap_address_t *peer, coap_pdu_t *pdu) {
+ rd_t *rd;
+ unsigned char *data;
+ coap_opt_iterator_t opt_iter;
+ coap_opt_t *etag;
+
+ rd = rd_new();
+
+ if (!rd) {
+ debug("hnd_get_rd: cannot allocate storage for rd\n");
+ return NULL;
+ }
+
+ if (coap_get_data(pdu, &rd->data.length, &data)) {
+ rd->data.s = (unsigned char *)coap_malloc(rd->data.length);
+ if (!rd->data.s) {
+ debug("hnd_get_rd: cannot allocate storage for rd->data\n");
+ rd_delete(rd);
+ return NULL;
+ }
+ memcpy(rd->data.s, data, rd->data.length);
+ }
+
+ etag = coap_check_option(pdu, COAP_OPTION_ETAG, &opt_iter);
+ if (etag) {
+ rd->etag_len = min(COAP_OPT_LENGTH(etag), sizeof(rd->etag));
+ memcpy(rd->etag, COAP_OPT_VALUE(etag), rd->etag_len);
+ }
+
+ return rd;
+}
+
+void
+hnd_post_rd(coap_context_t *ctx, struct coap_resource_t *resource,
+ coap_address_t *peer, coap_pdu_t *request, str *token,
+ coap_pdu_t *response) {
+ coap_resource_t *r;
+ coap_opt_iterator_t opt_iter;
+ coap_opt_t *query;
+#define LOCSIZE 68
+ unsigned char *loc;
+ size_t loc_size;
+ str h = {0, NULL}, ins = {0, NULL}, rt = {0, NULL}, lt = {0, NULL}; /* store query parameters */
+ unsigned char *buf;
+
+ loc = (unsigned char *)coap_malloc(LOCSIZE);
+ if (!loc) {
+ response->hdr->code = COAP_RESPONSE_CODE(500);
+ return;
+ }
+ memcpy(loc, RD_ROOT_STR, RD_ROOT_SIZE);
+
+ loc_size = RD_ROOT_SIZE;
+ loc[loc_size++] = '/';
+
+ /* store query parameters for later use */
+ query = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter);
+ if (query) {
+ parse_param((unsigned char *)"h", 1,
+ COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &h);
+ parse_param((unsigned char *)"ins", 3,
+ COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &ins);
+ parse_param((unsigned char *)"lt", 2,
+ COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), <);
+ parse_param((unsigned char *)"rt", 2,
+ COAP_OPT_VALUE(query), COAP_OPT_LENGTH(query), &rt);
+ }
+
+ if (h.length) { /* client has specified a node name */
+ memcpy(loc + loc_size, h.s, min(h.length, LOCSIZE - loc_size - 1));
+ loc_size += min(h.length, LOCSIZE - loc_size - 1);
+
+ if (ins.length && loc_size > 1) {
+ loc[loc_size++] = '-';
+ memcpy((char *)(loc + loc_size),
+ ins.s, min(ins.length, LOCSIZE - loc_size - 1));
+ loc_size += min(ins.length, LOCSIZE - loc_size - 1);
+ }
+
+ } else { /* generate node identifier */
+ loc_size +=
+ snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1,
+ "%x", request->hdr->id);
+
+ if (loc_size > 1) {
+ if (ins.length) {
+ loc[loc_size++] = '-';
+ memcpy((char *)(loc + loc_size),
+ ins.s, min(ins.length, LOCSIZE - loc_size - 1));
+ loc_size += min(ins.length, LOCSIZE - loc_size - 1);
+ } else {
+ coap_tick_t now;
+ coap_ticks(&now);
+
+ loc_size +=
+ snprintf((char *)(loc + loc_size), LOCSIZE - loc_size - 1,
+ "-%x", now);
+ }
+ }
+ }
+
+ /* TODO:
+ * - use lt to check expiration
+ */
+
+ r = coap_resource_init(loc, loc_size, COAP_RESOURCE_FLAGS_RELEASE_URI);
+ coap_register_handler(r, COAP_REQUEST_GET, hnd_get_resource);
+ coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_resource);
+ coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_resource);
+
+ if (ins.s) {
+ buf = (unsigned char *)coap_malloc(ins.length + 2);
+ if (buf) {
+ /* add missing quotes */
+ buf[0] = '"';
+ memcpy(buf + 1, ins.s, ins.length);
+ buf[ins.length + 1] = '"';
+ coap_add_attr(r, (unsigned char *)"ins", 3, buf, ins.length + 2, COAP_ATTR_FLAGS_RELEASE_VALUE);
+ }
+ }
+
+ if (rt.s) {
+ buf = (unsigned char *)coap_malloc(rt.length + 2);
+ if (buf) {
+ /* add missing quotes */
+ buf[0] = '"';
+ memcpy(buf + 1, rt.s, rt.length);
+ buf[rt.length + 1] = '"';
+ coap_add_attr(r, (unsigned char *)"rt", 2, buf, rt.length + 2, COAP_ATTR_FLAGS_RELEASE_VALUE);
+ }
+ }
+
+ add_source_address(r, peer);
+
+ {
+ rd_t *rd;
+ rd = make_rd(peer, request);
+ if (rd) {
+ coap_hash_path(loc, loc_size, rd->key);
+ HASH_ADD(hh, resources, key, sizeof(coap_key_t), rd);
+ } else {
+ /* FIXME: send error response and delete r */
+ }
+ }
+
+ coap_add_resource(ctx, r);
+
+
+ /* create response */
+
+ response->hdr->code = COAP_RESPONSE_CODE(201);
+
+ { /* split path into segments and add Location-Path options */
+ unsigned char _b[LOCSIZE];
+ unsigned char *b = _b;
+ size_t buflen = sizeof(_b);
+ int nseg;
+
+ nseg = coap_split_path(loc, loc_size, b, &buflen);
+ while (nseg--) {
+ coap_add_option(response, COAP_OPTION_LOCATION_PATH,
+ COAP_OPT_LENGTH(b), COAP_OPT_VALUE(b));
+ b += COAP_OPT_SIZE(b);
+ }
+ }
+}
+
+void
+init_resources(coap_context_t *ctx) {
+ coap_resource_t *r;
+
+ r = coap_resource_init(RD_ROOT_STR, RD_ROOT_SIZE, 0);
+ coap_register_handler(r, COAP_REQUEST_GET, hnd_get_rd);
+ coap_register_handler(r, COAP_REQUEST_POST, hnd_post_rd);
+
+ coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"40", 2, 0);
+ coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"\"core-rd\"", 9, 0);
+ coap_add_attr(r, (unsigned char *)"ins", 2, (unsigned char *)"\"default\"", 9, 0);
+
+ coap_add_resource(ctx, r);
+
+}
+
+void
+usage( const char *program, const char *version) {
+ const char *p;
+
+ p = strrchr( program, '/' );
+ if ( p )
+ program = ++p;
+
+ fprintf( stderr, "%s v%s -- CoRE Resource Directory implementation\n"
+ "(c) 2011-2012 Olaf Bergmann <bergmann@tzi.org>\n\n"
+ "usage: %s [-A address] [-p port]\n\n"
+ "\t-A address\tinterface address to bind to\n"
+ "\t-p port\t\tlisten on specified port\n"
+ "\t-v num\t\tverbosity level (default: 3)\n",
+ program, version, program );
+}
+
+coap_context_t *
+get_context(const char *node, const char *port) {
+ coap_context_t *ctx = NULL;
+ int s;
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+
+ s = getaddrinfo(node, port, &hints, &result);
+ if ( s != 0 ) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
+ return NULL;
+ }
+
+ /* iterate through results until success */
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ coap_address_t addr;
+
+ if (rp->ai_addrlen <= sizeof(addr.addr)) {
+ coap_address_init(&addr);
+ addr.size = rp->ai_addrlen;
+ memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen);
+
+ ctx = coap_new_context(&addr);
+ if (ctx) {
+ /* TODO: output address:port for successful binding */
+ goto finish;
+ }
+ }
+ }
+
+ fprintf(stderr, "no context available for interface '%s'\n", node);
+
+ finish:
+ freeaddrinfo(result);
+ return ctx;
+}
+
+int
+join(coap_context_t *ctx, char *group_name) {
+ struct ipv6_mreq mreq;
+ struct addrinfo *reslocal = NULL, *resmulti = NULL, hints, *ainfo;
+ int result = -1;
+
+ /* we have to resolve the link-local interface to get the interface id */
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ result = getaddrinfo("::", NULL, &hints, &reslocal);
+ if ( result < 0 ) {
+ perror("join: cannot resolve link-local interface");
+ goto finish;
+ }
+
+ /* get the first suitable interface identifier */
+ for (ainfo = reslocal; ainfo != NULL; ainfo = ainfo->ai_next) {
+ if ( ainfo->ai_family == AF_INET6 ) {
+ mreq.ipv6mr_interface =
+ ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_scope_id;
+ break;
+ }
+ }
+
+ memset(&hints, 0, sizeof(hints));
+ hints.ai_family = AF_INET6;
+ hints.ai_socktype = SOCK_DGRAM;
+
+ /* resolve the multicast group address */
+ result = getaddrinfo(group_name, NULL, &hints, &resmulti);
+
+ if ( result < 0 ) {
+ perror("join: cannot resolve multicast address");
+ goto finish;
+ }
+
+ for (ainfo = resmulti; ainfo != NULL; ainfo = ainfo->ai_next) {
+ if ( ainfo->ai_family == AF_INET6 ) {
+ mreq.ipv6mr_multiaddr =
+ ((struct sockaddr_in6 *)ainfo->ai_addr)->sin6_addr;
+ break;
+ }
+ }
+
+ result = setsockopt( ctx->sockfd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
+ (char *)&mreq, sizeof(mreq) );
+ if ( result < 0 )
+ perror("join: setsockopt");
+
+ finish:
+ freeaddrinfo(resmulti);
+ freeaddrinfo(reslocal);
+
+ return result;
+}
+
+int
+main(int argc, char **argv) {
+ coap_context_t *ctx;
+ fd_set readfds;
+ struct timeval tv, *timeout;
+ int result;
+ coap_tick_t now;
+ coap_queue_t *nextpdu;
+ char addr_str[NI_MAXHOST] = "::";
+ char port_str[NI_MAXSERV] = "5683";
+ char *group = NULL;
+ int opt;
+ coap_log_t log_level = LOG_WARNING;
+
+ while ((opt = getopt(argc, argv, "A:g:p:v:")) != -1) {
+ switch (opt) {
+ case 'A' :
+ strncpy(addr_str, optarg, NI_MAXHOST-1);
+ addr_str[NI_MAXHOST - 1] = '\0';
+ break;
+ case 'g' :
+ group = optarg;
+ break;
+ case 'p' :
+ strncpy(port_str, optarg, NI_MAXSERV-1);
+ port_str[NI_MAXSERV - 1] = '\0';
+ break;
+ case 'v' :
+ log_level = strtol(optarg, NULL, 10);
+ break;
+ default:
+ usage( argv[0], PACKAGE_VERSION );
+ exit( 1 );
+ }
+ }
+
+ coap_set_log_level(log_level);
+
+ ctx = get_context(addr_str, port_str);
+ if (!ctx)
+ return -1;
+
+ if (group)
+ join(ctx, group);
+
+ init_resources(ctx);
+
+ signal(SIGINT, handle_sigint);
+
+ while ( !quit ) {
+ FD_ZERO(&readfds);
+ FD_SET( ctx->sockfd, &readfds );
+
+ nextpdu = coap_peek_next( ctx );
+
+ coap_ticks(&now);
+ while ( nextpdu && nextpdu->t <= now ) {
+ coap_retransmit( ctx, coap_pop_next( ctx ) );
+ nextpdu = coap_peek_next( ctx );
+ }
+
+ if ( nextpdu && nextpdu->t <= now + COAP_RESOURCE_CHECK_TIME ) {
+ /* set timeout if there is a pdu to send before our automatic timeout occurs */
+ tv.tv_usec = ((nextpdu->t - now) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND;
+ tv.tv_sec = (nextpdu->t - now) / COAP_TICKS_PER_SECOND;
+ timeout = &tv;
+ } else {
+ tv.tv_usec = 0;
+ tv.tv_sec = COAP_RESOURCE_CHECK_TIME;
+ timeout = &tv;
+ }
+ result = select( FD_SETSIZE, &readfds, 0, 0, timeout );
+
+ if ( result < 0 ) { /* error */
+ if (errno != EINTR)
+ perror("select");
+ } else if ( result > 0 ) { /* read from socket */
+ if ( FD_ISSET( ctx->sockfd, &readfds ) ) {
+ coap_read( ctx ); /* read received data */
+ coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */
+ }
+ } else { /* timeout */
+ /* coap_check_resource_list( ctx ); */
+ }
+ }
+
+ coap_free_context( ctx );
+
+ return 0;
+}
--- /dev/null
+/* coap -- simple implementation of the Constrained Application Protocol (CoAP)
+ * as defined in draft-ietf-core-coap
+ *
+ * Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <errno.h>
+#include <signal.h>
+
+#include "config.h"
+#include "resource.h"
+#include "coap.h"
+#include <logger.h>
+#include <ocsocket.h>
+
+#define COAP_RESOURCE_CHECK_TIME 2
+
+#define MOD_NAME ("CoAP-Server")
+static uint8_t coap_wellknown_addr[] = {224,0,1,187};
+static short coap_def_port = 5683;
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+/* temporary storage for dynamic resource representations */
+static int quit = 0;
+
+/* changeable clock base (see handle_put_time()) */
+static time_t my_clock_base = 0;
+
+struct coap_resource_t *time_resource = NULL;
+
+#ifndef WITHOUT_ASYNC
+/* This variable is used to mimic long-running tasks that require
+ * asynchronous responses. */
+static coap_async_state_t *async = NULL;
+#endif /* WITHOUT_ASYNC */
+
+/* SIGINT handler: set quit to 1 for graceful termination */
+void
+handle_sigint(int signum) {
+ (void)signum;
+ quit = 1;
+}
+
+#define INDEX "This is a test server made with libcoap (see http://libcoap.sf.net)\n" \
+ "Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>\n\n"
+
+void
+hnd_get_index(coap_context_t *ctx, struct coap_resource_t *resource,
+ coap_address_t *peer, coap_pdu_t *request, str *token,
+ coap_pdu_t *response) {
+ unsigned char buf[3];
+ (void)ctx;
+ (void)resource;
+ (void)peer;
+ (void)request;
+ (void)token;
+
+ response->hdr->code = COAP_RESPONSE_CODE(205);
+
+ coap_add_option(response, COAP_OPTION_CONTENT_TYPE,
+ coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf);
+
+ coap_add_option(response, COAP_OPTION_MAXAGE,
+ coap_encode_var_bytes(buf, 0x2ffff), buf);
+
+ coap_add_data(response, strlen(INDEX), (unsigned char *)INDEX);
+}
+
+void
+hnd_get_time(coap_context_t *ctx, struct coap_resource_t *resource,
+ coap_address_t *peer, coap_pdu_t *request, str *token,
+ coap_pdu_t *response) {
+ coap_opt_iterator_t opt_iter;
+ coap_opt_t *option;
+ unsigned char buf[40];
+ size_t len;
+ time_t now;
+ coap_tick_t t;
+ coap_subscription_t *subscription;
+
+ /* FIXME: return time, e.g. in human-readable by default and ticks
+ * when query ?ticks is given. */
+
+ /* if my_clock_base was deleted, we pretend to have no such resource */
+ response->hdr->code =
+ my_clock_base ? COAP_RESPONSE_CODE(205) : COAP_RESPONSE_CODE(404);
+
+ if (request != NULL &&
+ coap_check_option(request, COAP_OPTION_OBSERVE, &opt_iter)) {
+ subscription = coap_add_observer(resource, peer, token);
+ if (subscription) {
+ subscription->non = request->hdr->type == COAP_MESSAGE_NON;
+ coap_add_option(response, COAP_OPTION_OBSERVE, 0, NULL);
+ }
+ }
+ if (resource->dirty == 1)
+ coap_add_option(response, COAP_OPTION_OBSERVE,
+ coap_encode_var_bytes(buf, ctx->observe), buf);
+
+
+ if (my_clock_base)
+ coap_add_option(response, COAP_OPTION_CONTENT_FORMAT,
+ coap_encode_var_bytes(buf, COAP_MEDIATYPE_TEXT_PLAIN), buf);
+
+ coap_add_option(response, COAP_OPTION_MAXAGE,
+ coap_encode_var_bytes(buf, 0x01), buf);
+
+ if (my_clock_base) {
+
+ /* calculate current time */
+ coap_ticks(&t);
+ now = my_clock_base + (t / COAP_TICKS_PER_SECOND);
+
+ if (request != NULL
+ && (option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter))
+ && memcmp(COAP_OPT_VALUE(option), "ticks",
+ min(5, COAP_OPT_LENGTH(option))) == 0) {
+ /* output ticks */
+ len = snprintf((char *)buf,
+ min(sizeof(buf), response->max_size - response->length),
+ "%u", (unsigned int)now);
+ coap_add_data(response, len, buf);
+
+ } else { /* output human-readable time */
+ struct tm *tmp;
+ tmp = gmtime(&now);
+ len = strftime((char *)buf,
+ min(sizeof(buf), response->max_size - response->length),
+ "%b %d %H:%M:%S", tmp);
+ coap_add_data(response, len, buf);
+ }
+ }
+}
+
+void
+hnd_put_time(coap_context_t *ctx, struct coap_resource_t *resource,
+ coap_address_t *peer, coap_pdu_t *request, str *token,
+ coap_pdu_t *response) {
+ coap_tick_t t;
+ size_t size;
+ unsigned char *data;
+ (void)ctx;
+ (void)peer;
+ (void)token;
+
+ /* FIXME: re-set my_clock_base to clock_offset if my_clock_base == 0
+ * and request is empty. When not empty, set to value in request payload
+ * (insist on query ?ticks). Return Created or Ok.
+ */
+
+ /* if my_clock_base was deleted, we pretend to have no such resource */
+ response->hdr->code =
+ my_clock_base ? COAP_RESPONSE_CODE(204) : COAP_RESPONSE_CODE(201);
+
+ resource->dirty = 1;
+
+ coap_get_data(request, &size, &data);
+
+ if (size == 0) /* re-init */
+ my_clock_base = clock_offset;
+ else {
+ my_clock_base = 0;
+ coap_ticks(&t);
+ while(size--)
+ my_clock_base = my_clock_base * 10 + *data++;
+ my_clock_base -= t / COAP_TICKS_PER_SECOND;
+ }
+}
+
+void
+hnd_delete_time(coap_context_t *ctx, struct coap_resource_t *resource,
+ coap_address_t *peer, coap_pdu_t *request, str *token,
+ coap_pdu_t *response) {
+ (void)ctx;
+ (void)resource;
+ (void)peer;
+ (void)request;
+ (void)token;
+ (void)response;
+ my_clock_base = 0; /* mark clock as "deleted" */
+
+ /* type = request->hdr->type == COAP_MESSAGE_CON */
+ /* ? COAP_MESSAGE_ACK : COAP_MESSAGE_NON; */
+}
+
+#ifndef WITHOUT_ASYNC
+void
+hnd_get_async(coap_context_t *ctx, struct coap_resource_t *resource,
+ coap_address_t *peer, coap_pdu_t *request, str *token,
+ coap_pdu_t *response) {
+ coap_opt_iterator_t opt_iter;
+ coap_opt_t *option;
+ unsigned long delay = 5;
+ size_t size;
+ (void)resource;
+ (void)token;
+
+ if (async) {
+ if (async->id != request->hdr->id) {
+ coap_opt_filter_t f;
+ coap_option_filter_clear(f);
+ response->hdr->code = COAP_RESPONSE_CODE(503);
+ }
+ return;
+ }
+
+ option = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter);
+ if (option) {
+ unsigned char *p = COAP_OPT_VALUE(option);
+
+ delay = 0;
+ for (size = COAP_OPT_LENGTH(option); size; --size, ++p)
+ delay = delay * 10 + (*p - '0');
+ }
+
+ async = coap_register_async(ctx, peer, request,
+ COAP_ASYNC_SEPARATE | COAP_ASYNC_CONFIRM,
+ (void *)(COAP_TICKS_PER_SECOND * delay));
+}
+
+void
+check_async(coap_context_t *ctx, coap_tick_t now) {
+ coap_pdu_t *response;
+ coap_async_state_t *tmp;
+
+ size_t size = sizeof(coap_hdr_t) + 8;
+
+ if (!async || now < async->created + (unsigned long)async->appdata)
+ return;
+
+ response = coap_pdu_init(async->flags & COAP_ASYNC_CONFIRM
+ ? COAP_MESSAGE_CON
+ : COAP_MESSAGE_NON,
+ COAP_RESPONSE_CODE(205), 0, size);
+ if (!response) {
+ debug("check_async: insufficient memory, we'll try later\n");
+ async->appdata =
+ (void *)((unsigned long)async->appdata + 15 * COAP_TICKS_PER_SECOND);
+ return;
+ }
+
+ response->hdr->id = coap_new_message_id(ctx);
+
+ if (async->tokenlen)
+ coap_add_token(response, async->tokenlen, async->token);
+
+ coap_add_data(response, 4, (unsigned char *)"done");
+
+ if (coap_send(ctx, &async->peer, response) == COAP_INVALID_TID) {
+ debug("check_async: cannot send response for message %d\n",
+ response->hdr->id);
+ }
+ coap_delete_pdu(response);
+ coap_remove_async(ctx, async->id, &tmp);
+ coap_free_async(async);
+ async = NULL;
+}
+#endif /* WITHOUT_ASYNC */
+
+void
+init_resources(coap_context_t *ctx) {
+ coap_resource_t *r;
+
+ r = coap_resource_init(NULL, 0, 0);
+ coap_register_handler(r, COAP_REQUEST_GET, hnd_get_index);
+
+ coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
+ coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"General Info\"", 14, 0);
+ coap_add_resource(ctx, r);
+
+ /* store clock base to use in /time */
+ my_clock_base = clock_offset;
+
+ r = coap_resource_init((unsigned char *)"time", 4, 0);
+ coap_register_handler(r, COAP_REQUEST_GET, hnd_get_time);
+ coap_register_handler(r, COAP_REQUEST_PUT, hnd_put_time);
+ coap_register_handler(r, COAP_REQUEST_DELETE, hnd_delete_time);
+
+ coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
+ coap_add_attr(r, (unsigned char *)"title", 5, (unsigned char *)"\"Internal Clock\"", 16, 0);
+ coap_add_attr(r, (unsigned char *)"rt", 2, (unsigned char *)"\"Ticks\"", 7, 0);
+ r->observable = 1;
+ coap_add_attr(r, (unsigned char *)"if", 2, (unsigned char *)"\"clock\"", 7, 0);
+
+ coap_add_resource(ctx, r);
+ time_resource = r;
+
+#ifndef WITHOUT_ASYNC
+ r = coap_resource_init((unsigned char *)"async", 5, 0);
+ coap_register_handler(r, COAP_REQUEST_GET, hnd_get_async);
+
+ coap_add_attr(r, (unsigned char *)"ct", 2, (unsigned char *)"0", 1, 0);
+ coap_add_resource(ctx, r);
+#endif /* WITHOUT_ASYNC */
+}
+
+void
+usage( const char *program, const char *version) {
+ const char *p;
+
+ p = strrchr( program, '/' );
+ if ( p )
+ program = ++p;
+
+ fprintf( stderr, "%s v%s -- a small CoAP implementation\n"
+ "(c) 2010,2011 Olaf Bergmann <bergmann@tzi.org>\n\n"
+ "usage: %s [-A address] [-p port]\n\n"
+ "\t-A address\tinterface address to bind to\n"
+ "\t-p port\t\tlisten on specified port\n"
+ "\t-v num\t\tverbosity level (default: 3)\n",
+ program, version, program );
+}
+
+coap_context_t *
+get_context(const char *node, const char *port) {
+ coap_context_t *ctx = NULL;
+ int s;
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
+ OCDevAddr mcast_addr;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST;
+
+ s = getaddrinfo(node, port, &hints, &result);
+ if ( s != 0 ) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
+ return NULL;
+ }
+
+ /* iterate through results until success */
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ coap_address_t addr;
+
+ if (rp->ai_addrlen <= sizeof(addr.addr)) {
+ coap_address_init(&addr);
+ addr.size = rp->ai_addrlen;
+ memcpy(&addr.addr, rp->ai_addr, rp->ai_addrlen);
+ OC_LOG_BUFFER(DEBUG, MOD_NAME, (uint8_t *)&addr, addr.size + 4 );
+
+ ctx = coap_new_context(&addr);
+ if (ctx) {
+ /* TODO: output address:port for successful binding */
+ OCBuildIPv4Address(coap_wellknown_addr[0], coap_wellknown_addr[1],
+ coap_wellknown_addr[2], coap_wellknown_addr[3], coap_def_port, &mcast_addr);
+ if (coap_join_wellknown_group(ctx, (coap_address_t*)&mcast_addr) != 0) {
+ OC_LOG(ERROR, MOD_NAME, "Unable to join to wellknown multicast group" );
+ }
+ goto finish;
+ }
+ }
+ }
+
+ fprintf(stderr, "no context available for interface '%s'\n", node);
+
+ finish:
+ freeaddrinfo(result);
+ return ctx;
+}
+
+int
+main(int argc, char **argv) {
+ coap_context_t *ctx;
+ fd_set readfds;
+ struct timeval tv, *timeout;
+ int result;
+ coap_tick_t now;
+ coap_queue_t *nextpdu;
+ char addr_str[NI_MAXHOST] = "::";
+ char port_str[NI_MAXSERV] = "5683";
+ int opt;
+ coap_log_t log_level = LOG_WARNING;
+
+ while ((opt = getopt(argc, argv, "A:p:v:")) != -1) {
+ switch (opt) {
+ case 'A' :
+ strncpy(addr_str, optarg, NI_MAXHOST-1);
+ addr_str[NI_MAXHOST - 1] = '\0';
+ break;
+ case 'p' :
+ strncpy(port_str, optarg, NI_MAXSERV-1);
+ port_str[NI_MAXSERV - 1] = '\0';
+ break;
+ case 'v' :
+ log_level = strtol(optarg, NULL, 10);
+ break;
+ default:
+ usage( argv[0], PACKAGE_VERSION );
+ exit( 1 );
+ }
+ }
+
+ coap_set_log_level(log_level);
+
+ ctx = get_context(addr_str, port_str);
+ if (!ctx)
+ return -1;
+
+ init_resources(ctx);
+
+ signal(SIGINT, handle_sigint);
+
+ while ( !quit ) {
+ FD_ZERO(&readfds);
+ FD_SET( ctx->sockfd, &readfds );
+ if (ctx->sockfd_wellknown != -1) {
+ FD_SET( ctx->sockfd_wellknown, &readfds );
+ }
+
+
+ nextpdu = coap_peek_next( ctx );
+
+ coap_ticks(&now);
+ while (nextpdu && nextpdu->t <= now - ctx->sendqueue_basetime) {
+ coap_retransmit( ctx, coap_pop_next( ctx ) );
+ nextpdu = coap_peek_next( ctx );
+ }
+
+ if ( nextpdu && nextpdu->t <= COAP_RESOURCE_CHECK_TIME ) {
+ /* set timeout if there is a pdu to send before our automatic timeout occurs */
+ tv.tv_usec = ((nextpdu->t) % COAP_TICKS_PER_SECOND) * 1000000 / COAP_TICKS_PER_SECOND;
+ tv.tv_sec = (nextpdu->t) / COAP_TICKS_PER_SECOND;
+ timeout = &tv;
+ } else {
+ tv.tv_usec = 0;
+ tv.tv_sec = COAP_RESOURCE_CHECK_TIME;
+ timeout = &tv;
+ }
+ result = select( FD_SETSIZE, &readfds, 0, 0, timeout );
+
+ if ( result < 0 ) { /* error */
+ if (errno != EINTR)
+ perror("select");
+ } else if ( result > 0 ) { /* read from unicast socket */
+ if ( FD_ISSET( ctx->sockfd, &readfds ) ) {
+ coap_read( ctx, ctx->sockfd ); /* read received data */
+ coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */
+ }
+
+ if (ctx->sockfd_wellknown != -1) {
+ if ( FD_ISSET( ctx->sockfd_wellknown, &readfds ) ) { /* read from multicast socket */
+
+ OC_LOG(DEBUG, MOD_NAME, "Device Discovery request at well-known address !!" );
+ coap_read( ctx, ctx->sockfd_wellknown ); /* read received data */
+ TODO("Do we need to call coap_dispatch separately for unicast and multicast sockets")
+ coap_dispatch( ctx ); /* and dispatch PDUs from receivequeue */
+ }
+ }
+ } else { /* timeout */
+ if (time_resource) {
+ time_resource->dirty = 1;
+ }
+ }
+
+#ifndef WITHOUT_ASYNC
+ /* check if we have to send asynchronous responses */
+ check_async(ctx, now);
+#endif /* WITHOUT_ASYNC */
+
+#ifndef WITHOUT_OBSERVE
+ /* check if we have to send observe notifications */
+ coap_check_notify(ctx);
+#endif /* WITHOUT_OBSERVE */
+ }
+
+ coap_free_context( ctx );
+
+ return 0;
+}
--- /dev/null
+/* tiny -- tiny sender
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <ctype.h>
+#include <limits.h>
+#include <sys/select.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include "../coap.h"
+
+static coap_tid_t id;
+
+coap_pdu_t *
+make_pdu( unsigned int value ) {
+ coap_pdu_t *pdu;
+ unsigned char enc;
+ static unsigned char buf[20];
+ int len, ls;
+
+ if ( ! ( pdu = coap_new_pdu() ) )
+ return NULL;
+
+ pdu->hdr->type = COAP_MESSAGE_NON;
+ pdu->hdr->code = COAP_REQUEST_POST;
+ pdu->hdr->id = htons(id++);
+
+ enc = COAP_PSEUDOFP_ENCODE_8_4_DOWN(value,ls);
+ coap_add_data( pdu, 1, &enc);
+
+ len = sprintf((char *)buf, "%u", COAP_PSEUDOFP_DECODE_8_4(enc));
+ if ( len > 0 ) {
+ coap_add_data( pdu, len, buf );
+ }
+
+ return pdu;
+}
+
+void
+usage( const char *program ) {
+ const char *p;
+
+ p = strrchr( program, '/' );
+ if ( p )
+ program = ++p;
+
+ fprintf( stderr, "%s -- tiny fake sensor\n"
+ "(c) 2010 Olaf Bergmann <bergmann@tzi.org>\n\n"
+ "usage: %s [group address]\n"
+ "\n\nSends some fake sensor values to specified multicast group\n",
+ program, program );
+}
+
+coap_context_t *
+get_context(const char *node, const char *port) {
+ coap_context_t *ctx = NULL;
+ int s;
+ struct addrinfo hints;
+ struct addrinfo *result, *rp;
+
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
+ hints.ai_socktype = SOCK_DGRAM; /* Coap uses UDP */
+ hints.ai_flags = AI_PASSIVE | AI_NUMERICHOST | AI_NUMERICSERV | AI_ALL;
+
+ s = getaddrinfo(node, port, &hints, &result);
+ if ( s != 0 ) {
+ fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));
+ return NULL;
+ }
+
+ /* iterate through results until success */
+ for (rp = result; rp != NULL; rp = rp->ai_next) {
+ ctx = coap_new_context(rp->ai_addr, rp->ai_addrlen);
+ if (ctx) {
+ /* TODO: output address:port for successful binding */
+ goto finish;
+ }
+ }
+
+ fprintf(stderr, "no context available for interface '%s'\n", node);
+
+ finish:
+ freeaddrinfo(result);
+ return ctx;
+}
+
+int
+main(int argc, char **argv) {
+ coap_context_t *ctx;
+ struct timeval tv;
+ coap_pdu_t *pdu;
+ struct sockaddr_in6 dst;
+ int hops = 16;
+
+ if ( argc > 1 && strncmp(argv[1], "-h", 2) == 0 ) {
+ usage( argv[0] );
+ exit( 1 );
+ }
+
+ ctx = get_context("::", NULL);
+ if ( !ctx )
+ return -1;
+
+ id = rand() & INT_MAX;
+
+ memset(&dst, 0, sizeof(struct sockaddr_in6 ));
+ dst.sin6_family = AF_INET6;
+ inet_pton( AF_INET6, argc > 1 ? argv[1] : "::1", &dst.sin6_addr );
+ dst.sin6_port = htons( COAP_DEFAULT_PORT );
+
+ if ( IN6_IS_ADDR_MULTICAST(&dst.sin6_addr) ) {
+ /* set socket options for multicast */
+
+ if ( setsockopt( ctx->sockfd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
+ (char *)&hops, sizeof(hops) ) < 0 )
+ perror("setsockopt: IPV6_MULTICAST_HOPS");
+
+ }
+
+ while ( 1 ) {
+
+ if (! (pdu = make_pdu( rand() & 0xfff ) ) )
+ return -1;
+
+ coap_send( ctx, (struct sockaddr *)&dst, sizeof(dst), pdu );
+ coap_delete_pdu(pdu);
+
+ tv.tv_sec = 5; tv.tv_usec = 0;
+
+ select( 0, 0, 0, 0, &tv );
+
+ }
+
+ coap_free_context( ctx );
+
+ return 0;
+}
--- /dev/null
+/* hashkey.c -- definition of hash key type and helper functions
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "hashkey.h"
+
+/* Caution: When changing this, update COAP_DEFAULT_WKC_HASHKEY
+ * accordingly (see int coap_hash_path());
+ */
+void
+coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h) {
+ size_t j;
+
+ while (len--) {
+ j = sizeof(coap_key_t)-1;
+
+ while (j) {
+ h[j] = ((h[j] << 7) | (h[j-1] >> 1)) + h[j];
+ --j;
+ }
+
+ h[0] = (h[0] << 7) + h[0] + *s++;
+ }
+}
+
--- /dev/null
+/* hashkey.h -- definition of hash key type and helper functions
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+/**
+ * @file hashkey.h
+ * @brief definition of hash key type and helper functions
+ */
+
+#ifndef _COAP_HASHKEY_H_
+#define _COAP_HASHKEY_H_
+
+#include "str.h"
+
+typedef unsigned char coap_key_t[4];
+
+#ifndef coap_hash
+/**
+ * Calculates a fast hash over the given string @p s of length @p len
+ * and stores the result into @p h. Depending on the exact
+ * implementation, this function cannot be used as one-way function to
+ * check message integrity or simlar.
+ *
+ * @param s The string used for hash calculation.
+ * @param len The length of @p s.
+ * @param h The result buffer to store the calculated hash key.
+ */
+void coap_hash_impl(const unsigned char *s, unsigned int len, coap_key_t h);
+
+#define coap_hash(String,Length,Result) \
+ coap_hash_impl((String),(Length),(Result))
+
+/* This is used to control the pre-set hash-keys for resources. */
+#define __COAP_DEFAULT_HASH
+#else
+#undef __COAP_DEFAULT_HASH
+#endif /* coap_hash */
+
+/**
+ * Calls coap_hash() with given @c str object as parameter.
+ *
+ * @param Str Must contain a pointer to a coap string object.
+ * @param H A coap_key_t object to store the result.
+ *
+ * @hideinitializer
+ */
+#define coap_str_hash(Str,H) { \
+ assert(Str); \
+ memset((H), 0, sizeof(coap_key_t)); \
+ coap_hash((H), (Str)->s, (Str)->length); \
+ }
+
+#endif /* _COAP_HASHKEY_H_ */
--- /dev/null
+/* mem.h -- CoAP memory handling
+ * Currently, this is just a dummy for malloc/free
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef _COAP_MEM_H_
+#define _COAP_MEM_H_
+
+#include <stdlib.h>
+
+#define coap_malloc(size) malloc(size)
+#define coap_free(size) free(size)
+
+#endif /* _COAP_MEM_H_ */
--- /dev/null
+/* net.c -- CoAP network interface
+ *
+ * Copyright (C) 2010--2014 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "config.h"
+
+#include <ctype.h>
+#include <stdio.h>
+#ifdef HAVE_LIMITS_H
+#include <limits.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#elif HAVE_SYS_UNISTD_H
+#include <sys/unistd.h>
+#endif
+#include <sys/types.h>
+#ifdef HAVE_SYS_SOCKET_H
+#include <sys/socket.h>
+#endif
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#ifdef WITH_LWIP
+#include <lwip/pbuf.h>
+#include <lwip/udp.h>
+#include <lwip/timers.h>
+#endif
+
+#include "debug.h"
+#include "mem.h"
+#include "str.h"
+#include "async.h"
+#include "resource.h"
+#include "option.h"
+#include "encode.h"
+#include "block.h"
+#include "net.h"
+
+#if defined(WITH_POSIX)
+
+#include <ocsocket.h>
+#include <logger.h>
+
+#define MOD_NAME ("net.c")
+
+time_t clock_offset;
+
+static inline coap_queue_t *
+coap_malloc_node() {
+ return (coap_queue_t *)coap_malloc(sizeof(coap_queue_t));
+}
+
+static inline void
+coap_free_node(coap_queue_t *node) {
+ coap_free(node);
+}
+#endif /* WITH_POSIX */
+#ifdef WITH_LWIP
+
+#include <lwip/memp.h>
+
+static void coap_retransmittimer_execute(void *arg);
+static void coap_retransmittimer_restart(coap_context_t *ctx);
+
+static inline coap_queue_t *
+coap_malloc_node() {
+ return (coap_queue_t *)memp_malloc(MEMP_COAP_NODE);
+}
+
+static inline void
+coap_free_node(coap_queue_t *node) {
+ memp_free(MEMP_COAP_NODE, node);
+}
+
+#endif /* WITH_LWIP */
+#ifdef WITH_CONTIKI
+# ifndef DEBUG
+# define DEBUG DEBUG_PRINT
+# endif /* DEBUG */
+
+#include "memb.h"
+#include "net/uip-debug.h"
+
+clock_time_t clock_offset;
+
+#define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN])
+#define UIP_UDP_BUF ((struct uip_udp_hdr *)&uip_buf[UIP_LLIPH_LEN])
+
+void coap_resources_init();
+void coap_pdu_resources_init();
+
+unsigned char initialized = 0;
+coap_context_t the_coap_context;
+
+MEMB(node_storage, coap_queue_t, COAP_PDU_MAXCNT);
+
+PROCESS(coap_retransmit_process, "message retransmit process");
+
+static inline coap_queue_t *
+coap_malloc_node() {
+ return (coap_queue_t *)memb_alloc(&node_storage);
+}
+
+static inline void
+coap_free_node(coap_queue_t *node) {
+ memb_free(&node_storage, node);
+}
+#endif /* WITH_CONTIKI */
+#ifdef WITH_LWIP
+
+/** Callback to udp_recv when using lwIP. Gets called by lwIP on arriving
+ * packages, places a reference in context->pending_package, and calls
+ * coap_read to process the package. Thus, coap_read needs not be called in
+ * lwIP main loops. (When modifying this for thread-like operation, ie. if you
+ * remove the coap_read call from this, make sure that coap_read gets a chance
+ * to run before this callback is entered the next time.)
+ */
+static void received_package(void *arg, struct udp_pcb *upcb, struct pbuf *p, ip_addr_t *addr, u16_t port)
+{
+ struct coap_context_t *context = (coap_context_t *)arg;
+
+ LWIP_ASSERT("pending_package was not cleared.", context->pending_package == NULL);
+
+ context->pending_package = p; /* we don't free it, coap_read has to do that */
+ context->pending_address.addr = addr->addr; /* FIXME: this has to become address-type independent, probably there'll be an lwip function for that */
+ context->pending_port = port;
+
+ coap_read(context, -1); /* we want to read from unicast socket */
+}
+
+#endif /* WITH_LWIP */
+
+int print_wellknown(coap_context_t *, unsigned char *, size_t *, size_t,
+ coap_opt_t *);
+
+void coap_handle_failed_notify(coap_context_t *, const coap_address_t *,
+ const str *);
+
+unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now) {
+ unsigned int result = 0;
+ coap_tick_diff_t delta = now - ctx->sendqueue_basetime;
+
+ if (ctx->sendqueue) {
+ /* delta < 0 means that the new time stamp is before the old. */
+ if (delta <= 0) {
+ ctx->sendqueue->t -= delta;
+ } else {
+ /* This case is more complex: The time must be advanced forward,
+ * thus possibly leading to timed out elements at the queue's
+ * start. For every element that has timed out, its relative
+ * time is set to zero and the result counter is increased. */
+
+ coap_queue_t *q = ctx->sendqueue;
+ coap_tick_t t = 0;
+ while (q && (t + q->t < (coap_tick_t) delta)) {
+ t += q->t;
+ q->t = 0;
+ result++;
+ q = q->next;
+ }
+
+ /* finally adjust the first element that has not expired */
+ if (q) {
+ q->t = (coap_tick_t) delta - t;
+ }
+ }
+ }
+
+ /* adjust basetime */
+ ctx->sendqueue_basetime += delta;
+
+ return result;
+}
+
+int coap_insert_node(coap_queue_t **queue, coap_queue_t *node) {
+ coap_queue_t *p, *q;
+ if (!queue || !node)
+ return 0;
+
+ /* set queue head if empty */
+ if (!*queue) {
+ *queue = node;
+ return 1;
+ }
+
+ /* replace queue head if PDU's time is less than head's time */
+ q = *queue;
+ if (node->t < q->t) {
+ node->next = q;
+ *queue = node;
+ q->t -= node->t; /* make q->t relative to node->t */
+ return 1;
+ }
+
+ /* search for right place to insert */
+ do {
+ node->t -= q->t; /* make node-> relative to q->t */
+ p = q;
+ q = q->next;
+ } while (q && q->t <= node->t);
+
+ /* insert new item */
+ if (q) {
+ q->t -= node->t; /* make q->t relative to node->t */
+ }
+ node->next = q;
+ p->next = node;
+ return 1;
+}
+
+int coap_delete_node(coap_queue_t *node) {
+ if (!node)
+ return 0;
+
+ coap_delete_pdu(node->pdu);
+ coap_free_node(node);
+
+ return 1;
+}
+
+void coap_delete_all(coap_queue_t *queue) {
+ if (!queue)
+ return;
+
+ coap_delete_all(queue->next);
+ coap_delete_node(queue);
+}
+
+coap_queue_t *
+coap_new_node() {
+ coap_queue_t *node;
+ node = coap_malloc_node();
+
+ if (!node) {
+#ifndef NDEBUG
+ coap_log(LOG_WARNING, "coap_new_node: malloc\n");
+#endif
+ return NULL;
+ }
+
+ memset(node, 0, sizeof *node);
+ return node;
+}
+
+coap_queue_t *
+coap_peek_next(coap_context_t *context) {
+ if (!context || !context->sendqueue)
+ return NULL;
+
+ return context->sendqueue;
+}
+
+coap_queue_t *
+coap_pop_next(coap_context_t *context) {
+ coap_queue_t *next;
+
+ if (!context || !context->sendqueue)
+ return NULL;
+
+ next = context->sendqueue;
+ context->sendqueue = context->sendqueue->next;
+ if (context->sendqueue) {
+ context->sendqueue->t += next->t;
+ }
+ next->next = NULL;
+ return next;
+}
+
+#ifdef COAP_DEFAULT_WKC_HASHKEY
+/** Checks if @p Key is equal to the pre-defined hash key for.well-known/core. */
+#define is_wkc(Key) \
+ (memcmp((Key), COAP_DEFAULT_WKC_HASHKEY, sizeof(coap_key_t)) == 0)
+#else
+/* Implements a singleton to store a hash key for the .wellknown/core
+ * resources. */
+int
+is_wkc(coap_key_t k) {
+ static coap_key_t wkc;
+ static unsigned char _initialized = 0;
+ if (!_initialized) {
+ _initialized = coap_hash_path((unsigned char *)COAP_DEFAULT_URI_WELLKNOWN,
+ sizeof(COAP_DEFAULT_URI_WELLKNOWN) - 1, wkc);
+ }
+ return memcmp(k, wkc, sizeof(coap_key_t)) == 0;
+}
+#endif
+
+coap_context_t *
+coap_new_context(const coap_address_t *listen_addr) {
+#ifdef WITH_POSIX
+ coap_context_t *c = (coap_context_t*)coap_malloc( sizeof( coap_context_t ) );
+ //int reuse = 1;
+#endif /* WITH_POSIX */
+#ifdef WITH_LWIP
+ coap_context_t *c = memp_malloc(MEMP_COAP_CONTEXT);
+#endif /* WITH_LWIP */
+#ifdef WITH_CONTIKI
+ coap_context_t *c;
+
+ if (initialized)
+ return NULL;
+#endif /* WITH_CONTIKI */
+
+ if (!listen_addr) {
+ coap_log(LOG_EMERG, "no listen address specified\n");
+ return NULL;
+ }
+
+ coap_clock_init();
+#ifdef WITH_LWIP
+ prng_init(LWIP_RAND());
+#else /* WITH_LWIP */
+ prng_init((unsigned long)listen_addr ^ clock_offset);
+#endif /* WITH_LWIP */
+
+#ifndef WITH_CONTIKI
+ if (!c) {
+#ifndef NDEBUG
+ coap_log(LOG_EMERG, "coap_init: malloc:\n");
+#endif
+ return NULL;
+ }
+#endif /* not WITH_CONTIKI */
+#ifdef WITH_CONTIKI
+ coap_resources_init();
+ coap_pdu_resources_init();
+
+ c = &the_coap_context;
+ initialized = 1;
+#endif /* WITH_CONTIKI */
+
+ memset(c, 0, sizeof(coap_context_t));
+
+ /* set well-known sockfd to uninitialize value */
+ c->sockfd_wellknown = -1;
+
+ /* initialize message id */
+ prng((unsigned char * )&c->message_id, sizeof(unsigned short));
+
+ /* register the critical options that we know */
+ coap_register_option(c, COAP_OPTION_IF_MATCH);
+ coap_register_option(c, COAP_OPTION_URI_HOST);
+ coap_register_option(c, COAP_OPTION_IF_NONE_MATCH);
+ coap_register_option(c, COAP_OPTION_URI_PORT);
+ coap_register_option(c, COAP_OPTION_URI_PATH);
+ coap_register_option(c, COAP_OPTION_URI_QUERY);
+ coap_register_option(c, COAP_OPTION_ACCEPT);
+ coap_register_option(c, COAP_OPTION_PROXY_URI);
+ coap_register_option(c, COAP_OPTION_PROXY_SCHEME);
+ coap_register_option(c, COAP_OPTION_BLOCK2);
+ coap_register_option(c, COAP_OPTION_BLOCK1);
+
+#ifdef WITH_POSIX
+#if 0
+ c->sockfd = socket(listen_addr->addr.sa.sa_family, SOCK_DGRAM, 0);
+ if ( c->sockfd < 0 ) {
+#ifndef NDEBUG
+ coap_log(LOG_EMERG, "coap_new_context: socket\n");
+#endif /* WITH_NDEBUG */
+ goto onerror;
+ }
+
+ if ( setsockopt( c->sockfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse) ) < 0 ) {
+#ifndef NDEBUG
+ coap_log(LOG_WARNING, "setsockopt SO_REUSEADDR\n");
+#endif
+ }
+
+ if (bind(c->sockfd, &listen_addr->addr.sa, listen_addr->size) < 0) {
+#ifndef NDEBUG
+ coap_log(LOG_EMERG, "coap_new_context: bind\n");
+#endif
+ goto onerror;
+ }
+
+ return c;
+
+ onerror:
+ if ( c->sockfd >= 0 )
+ close ( c->sockfd );
+ coap_free( c );
+ return NULL;
+#endif //0
+ if (OCInitUDP((OCDevAddr *)listen_addr, (int32_t *)&(c->sockfd)) != ERR_SUCCESS) {
+ coap_free( c);
+ return NULL;
+ }
+ else {
+ return c;
+ }
+
+#endif /* WITH_POSIX */
+#ifdef WITH_CONTIKI
+ c->conn = udp_new(NULL, 0, NULL);
+ udp_bind(c->conn, listen_addr->port);
+
+ process_start(&coap_retransmit_process, (char *)c);
+
+ PROCESS_CONTEXT_BEGIN(&coap_retransmit_process);
+#ifndef WITHOUT_OBSERVE
+ etimer_set(&c->notify_timer, COAP_RESOURCE_CHECK_TIME * COAP_TICKS_PER_SECOND);
+#endif /* WITHOUT_OBSERVE */
+ /* the retransmit timer must be initialized to some large value */
+ etimer_set(&the_coap_context.retransmit_timer, 0xFFFF);
+ PROCESS_CONTEXT_END(&coap_retransmit_process);
+ return c;
+#endif /* WITH_CONTIKI */
+#ifdef WITH_LWIP
+ c->pcb = udp_new();
+ /* hard assert: this is not expected to fail dynamically */
+ LWIP_ASSERT("Failed to allocate PCB for CoAP", c->pcb != NULL);
+
+ udp_recv(c->pcb, received_package, (void*)c);
+ udp_bind(c->pcb, &listen_addr->addr, listen_addr->port);
+
+ c->timer_configured = 0;
+
+ return c;
+#endif
+}
+
+void coap_free_context(coap_context_t *context) {
+#if defined(WITH_POSIX) || defined(WITH_LWIP)
+ coap_resource_t *res;
+#ifndef COAP_RESOURCES_NOHASH
+ coap_resource_t *rtmp;
+#endif
+#endif /* WITH_POSIX || WITH_LWIP */
+ if (!context)
+ return;
+
+ coap_delete_all(context->recvqueue);
+ coap_delete_all(context->sendqueue);
+
+#ifdef WITH_LWIP
+ context->sendqueue = NULL;
+ coap_retransmittimer_restart(context);
+#endif
+
+#if defined(WITH_POSIX) || defined(WITH_LWIP)
+#ifdef COAP_RESOURCES_NOHASH
+ LL_FOREACH(context->resources, res) {
+#else
+ HASH_ITER(hh, context->resources, res, rtmp) {
+#endif
+ coap_delete_resource(context, res->key);
+ }
+#endif /* WITH_POSIX || WITH_LWIP */
+
+#ifdef WITH_POSIX
+ /* coap_delete_list(context->subscriptions); */
+ OCClose( context->sockfd );
+ if (context->sockfd_wellknown != -1) {
+ OCClose( context->sockfd_wellknown );
+ }
+ coap_free( context );
+#endif
+#ifdef WITH_LWIP
+ udp_remove(context->pcb);
+ memp_free(MEMP_COAP_CONTEXT, context);
+#endif
+#ifdef WITH_CONTIKI
+ memset(&the_coap_context, 0, sizeof(coap_context_t));
+ initialized = 0;
+#endif /* WITH_CONTIKI */
+}
+
+int coap_join_wellknown_group(coap_context_t *ctx,
+ const coap_address_t *multicast_addr) {
+#ifdef WITH_POSIX
+ if (OCInitUDPMulticast((OCDevAddr *)multicast_addr,
+ (int32_t *)&(ctx->sockfd_wellknown)) != ERR_SUCCESS) {
+ return 1;
+ }
+ return 0;
+#endif
+}
+
+int coap_option_check_critical(coap_context_t *ctx, coap_pdu_t *pdu,
+ coap_opt_filter_t unknown) {
+
+ coap_opt_iterator_t opt_iter;
+ int ok = 1;
+
+ coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL);
+
+ while (coap_option_next(&opt_iter)) {
+
+ /* The following condition makes use of the fact that
+ * coap_option_getb() returns -1 if type exceeds the bit-vector
+ * filter. As the vector is supposed to be large enough to hold
+ * the largest known option, we know that everything beyond is
+ * bad.
+ */
+ if (opt_iter.type & 0x01
+ && coap_option_getb(ctx->known_options, opt_iter.type) < 1) {
+ debug("unknown critical option %d\n", opt_iter.type);
+
+ ok = 0;
+
+ /* When opt_iter.type is beyond our known option range,
+ * coap_option_setb() will return -1 and we are safe to leave
+ * this loop. */
+ if (coap_option_setb(unknown, opt_iter.type) == -1)
+ break;
+ }
+ }
+
+ return ok;
+}
+
+void coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu,
+ coap_tid_t *id) {
+ coap_key_t h;
+
+ memset(h, 0, sizeof(coap_key_t));
+
+ /* Compare the complete address structure in case of IPv4. For IPv6,
+ * we need to look at the transport address only. */
+
+#ifdef WITH_POSIX
+ switch (peer->addr.sa.sa_family) {
+ case AF_INET:
+ coap_hash((const unsigned char *)&peer->addr.sa, peer->size, h);
+ break;
+ case AF_INET6:
+ coap_hash((const unsigned char *)&peer->addr.sin6.sin6_port,
+ sizeof(peer->addr.sin6.sin6_port), h);
+ coap_hash((const unsigned char *)&peer->addr.sin6.sin6_addr,
+ sizeof(peer->addr.sin6.sin6_addr), h);
+ break;
+ default:
+ return;
+ }
+#endif
+#if defined(WITH_LWIP) || defined(WITH_CONTIKI)
+ /* FIXME: with lwip, we can do better */
+ coap_hash((const unsigned char *)&peer->port, sizeof(peer->port), h);
+ coap_hash((const unsigned char *)&peer->addr, sizeof(peer->addr), h);
+#endif /* WITH_LWIP || WITH_CONTIKI */
+
+ coap_hash((const unsigned char * )&pdu->hdr->id, sizeof(unsigned short), h);
+
+ *id = ((h[0] << 8) | h[1]) ^ ((h[2] << 8) | h[3]);
+}
+
+coap_tid_t coap_send_ack(coap_context_t *context, const coap_address_t *dst,
+ coap_pdu_t *request) {
+ coap_pdu_t *response;
+ coap_tid_t result = COAP_INVALID_TID;
+
+ if (request && request->hdr->type == COAP_MESSAGE_CON) {
+ response = coap_pdu_init(COAP_MESSAGE_ACK, 0, request->hdr->id,
+ sizeof(coap_pdu_t));
+ if (response) {
+ result = coap_send(context, dst, response);
+ coap_delete_pdu(response);
+ }
+ }
+ return result;
+}
+
+#ifdef WITH_POSIX
+/* releases space allocated by PDU if free_pdu is set */
+coap_tid_t
+coap_send_impl(coap_context_t *context,
+ const coap_address_t *dst,
+ coap_pdu_t *pdu) {
+ ssize_t bytes_written;
+ coap_tid_t id = COAP_INVALID_TID;
+
+ if ( !context || !dst || !pdu )
+ return id;
+
+ //bytes_written = sendto( context->sockfd, pdu->hdr, pdu->length, 0,
+ // &dst->addr.sa, dst->size);
+ bytes_written = OCSendTo( context->sockfd, (uint8_t*)(pdu->hdr), pdu->length, 0,
+ (OCDevAddr*)dst);
+ printf("bytes_written %d\n", (int)bytes_written);
+
+ if (bytes_written >= 0) {
+ coap_transaction_id(dst, pdu, &id);
+ } else {
+ coap_log(LOG_CRIT, "coap_send: sendto\n");
+ }
+
+ return id;
+}
+#endif /* WITH_POSIX */
+#ifdef WITH_CONTIKI
+/* releases space allocated by PDU if free_pdu is set */
+coap_tid_t
+coap_send_impl(coap_context_t *context,
+ const coap_address_t *dst,
+ coap_pdu_t *pdu) {
+ coap_tid_t id = COAP_INVALID_TID;
+
+ if ( !context || !dst || !pdu )
+ return id;
+
+ /* FIXME: is there a way to check if send was successful? */
+ uip_udp_packet_sendto(context->conn, pdu->hdr, pdu->length,
+ &dst->addr, dst->port);
+
+ coap_transaction_id(dst, pdu, &id);
+
+ return id;
+}
+#endif /* WITH_CONTIKI */
+#ifdef WITH_LWIP
+coap_tid_t
+coap_send_impl(coap_context_t *context,
+ const coap_address_t *dst,
+ coap_pdu_t *pdu) {
+ coap_tid_t id = COAP_INVALID_TID;
+ struct pbuf *p;
+ uint8_t err;
+ char *data_backup;
+
+ if ( !context || !dst || !pdu )
+ {
+ return id;
+ }
+
+ data_backup = pdu->data;
+
+ /* FIXME: we can't check this here with the existing infrastructure, but we
+ * should actually check that the pdu is not held by anyone but us. the
+ * respective pbuf is already exclusively owned by the pdu. */
+
+ p = pdu->pbuf;
+ LWIP_ASSERT("The PDU header is not where it is expected", pdu->hdr == p->payload + sizeof(coap_pdu_t));
+
+ err = pbuf_header(p, -sizeof(coap_pdu_t));
+ if (err)
+ {
+ debug("coap_send_impl: pbuf_header failed\n");
+ pbuf_free(p);
+ return id;
+ }
+
+ coap_transaction_id(dst, pdu, &id);
+
+ pbuf_realloc(p, pdu->length);
+
+ udp_sendto(context->pcb, p,
+ &dst->addr, dst->port);
+
+ pbuf_header(p, -(ptrdiff_t)((uint8_t*)pdu - (uint8_t*)p->payload) - sizeof(coap_pdu_t)); /* FIXME hack around udp_sendto not restoring; see http://lists.gnu.org/archive/html/lwip-users/2013-06/msg00008.html. for udp over ip over ethernet, this was -42; as we're doing ppp too, this has to be calculated generically */
+
+ err = pbuf_header(p, sizeof(coap_pdu_t));
+ LWIP_ASSERT("Cannot undo pbuf_header", err == 0);
+
+ /* restore destroyed pdu data */
+ LWIP_ASSERT("PDU not restored", p->payload == pdu);
+ pdu->max_size = p->tot_len - sizeof(coap_pdu_t); /* reduced after pbuf_realloc */
+ pdu->hdr = p->payload + sizeof(coap_pdu_t);
+ pdu->max_delta = 0; /* won't be used any more */
+ pdu->length = pdu->max_size;
+ pdu->data = data_backup;
+ pdu->pbuf = p;
+
+ return id;
+}
+#endif /* WITH_LWIP */
+
+coap_tid_t coap_send(coap_context_t *context, const coap_address_t *dst,
+ coap_pdu_t *pdu) {
+ return coap_send_impl(context, dst, pdu);
+}
+
+coap_tid_t coap_send_error(coap_context_t *context, coap_pdu_t *request,
+ const coap_address_t *dst, unsigned char code, coap_opt_filter_t opts) {
+ coap_pdu_t *response;
+ coap_tid_t result = COAP_INVALID_TID;
+
+ assert(request);
+ assert(dst);
+
+ response = coap_new_error_response(request, code, opts);
+ if (response) {
+ result = coap_send(context, dst, response);
+ coap_delete_pdu(response);
+ }
+
+ return result;
+}
+
+coap_tid_t coap_send_message_type(coap_context_t *context,
+ const coap_address_t *dst, coap_pdu_t *request, unsigned char type) {
+ coap_pdu_t *response;
+ coap_tid_t result = COAP_INVALID_TID;
+
+ if (request) {
+ response = coap_pdu_init(type, 0, request->hdr->id, sizeof(coap_pdu_t));
+ if (response) {
+ result = coap_send(context, dst, response);
+ coap_delete_pdu(response);
+ }
+ }
+ return result;
+}
+
+coap_tid_t coap_send_confirmed(coap_context_t *context,
+ const coap_address_t *dst, coap_pdu_t *pdu) {
+ coap_queue_t *node;
+ coap_tick_t now;
+ int r;
+
+ node = coap_new_node();
+ if (!node) {
+ debug("coap_send_confirmed: insufficient memory\n");
+ return COAP_INVALID_TID;
+ }
+
+ node->id = coap_send_impl(context, dst, pdu);
+ if (COAP_INVALID_TID == node->id) {
+ debug("coap_send_confirmed: error sending pdu\n");
+ coap_free_node(node);
+ return COAP_INVALID_TID;
+ }
+
+ prng((unsigned char * )&r, sizeof(r));
+
+ /* add randomized RESPONSE_TIMEOUT to determine retransmission timeout */
+ node->timeout = COAP_DEFAULT_RESPONSE_TIMEOUT * COAP_TICKS_PER_SECOND
+ + (COAP_DEFAULT_RESPONSE_TIMEOUT >> 1)
+ * ((COAP_TICKS_PER_SECOND * (r & 0xFF)) >> 8);
+
+ memcpy(&node->remote, dst, sizeof(coap_address_t));
+ node->pdu = pdu;
+
+ /* Set timer for pdu retransmission. If this is the first element in
+ * the retransmission queue, the base time is set to the current
+ * time and the retransmission time is node->timeout. If there is
+ * already an entry in the sendqueue, we must check if this node is
+ * to be retransmitted earlier. Therefore, node->timeout is first
+ * normalized to the base time and then inserted into the queue with
+ * an adjusted relative time.
+ */coap_ticks(&now);
+ if (context->sendqueue == NULL) {
+ node->t = node->timeout;
+ context->sendqueue_basetime = now;
+ } else {
+ /* make node->t relative to context->sendqueue_basetime */
+ node->t = (now - context->sendqueue_basetime) + node->timeout;
+ }
+
+ coap_insert_node(&context->sendqueue, node);
+
+#ifdef WITH_LWIP
+ if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */
+ coap_retransmittimer_restart(context);
+#endif
+
+#ifdef WITH_CONTIKI
+ { /* (re-)initialize retransmission timer */
+ coap_queue_t *nextpdu;
+
+ nextpdu = coap_peek_next(context);
+ assert(nextpdu); /* we have just inserted a node */
+
+ /* must set timer within the context of the retransmit process */
+ PROCESS_CONTEXT_BEGIN(&coap_retransmit_process);
+ etimer_set(&context->retransmit_timer, nextpdu->t);
+ PROCESS_CONTEXT_END(&coap_retransmit_process);
+ }
+#endif /* WITH_CONTIKI */
+
+ return node->id;
+}
+
+coap_tid_t coap_retransmit(coap_context_t *context, coap_queue_t *node) {
+ if (!context || !node)
+ return COAP_INVALID_TID;
+
+ /* re-initialize timeout when maximum number of retransmissions are not reached yet */
+ if (node->retransmit_cnt < COAP_DEFAULT_MAX_RETRANSMIT) {
+ node->retransmit_cnt++;
+ node->t = node->timeout << node->retransmit_cnt;
+ coap_insert_node(&context->sendqueue, node);
+#ifdef WITH_LWIP
+ if (node == context->sendqueue) /* don't bother with timer stuff if there are earlier retransmits */
+ coap_retransmittimer_restart(context);
+#endif
+
+ debug("** retransmission #%d of transaction %d\n", node->retransmit_cnt,
+ ntohs(node->pdu->hdr->id));
+
+ node->id = coap_send_impl(context, &node->remote, node->pdu);
+ return node->id;
+ }
+
+ /* no more retransmissions, remove node from system */
+
+#ifndef WITH_CONTIKI
+ debug("** removed transaction %d\n", ntohs(node->id));
+#endif
+
+#ifndef WITHOUT_OBSERVE
+ /* Check if subscriptions exist that should be canceled after
+ COAP_MAX_NOTIFY_FAILURES */
+ if (node->pdu->hdr->code >= 64) {
+ str token = { 0, NULL };
+
+ token.length = node->pdu->hdr->token_length;
+ token.s = node->pdu->hdr->token;
+
+ coap_handle_failed_notify(context, &node->remote, &token);
+ }
+#endif /* WITHOUT_OBSERVE */
+
+ /* And finally delete the node */
+ coap_delete_node(node);
+ return COAP_INVALID_TID;
+}
+
+/**
+ * Checks if @p opt fits into the message that ends with @p maxpos.
+ * This function returns @c 1 on success, or @c 0 if the option @p opt
+ * would exceed @p maxpos.
+ */
+static inline int check_opt_size(coap_opt_t *opt, unsigned char *maxpos) {
+ if (opt && opt < maxpos) {
+ if (((*opt & 0x0f) < 0x0f) || (opt + 1 < maxpos))
+ return opt + COAP_OPT_SIZE(opt) < maxpos;
+ }
+ return 0;
+}
+
+int coap_read(coap_context_t *ctx, int sockfd) {
+#ifdef WITH_POSIX
+ static char buf[COAP_MAX_PDU_SIZE];
+#endif
+#if defined(WITH_LWIP) || defined(WITH_CONTIKI)
+ char *buf;
+#endif
+ coap_hdr_t *pdu;
+ ssize_t bytes_read = -1;
+ coap_address_t src, dst;
+ coap_queue_t *node;
+
+#ifdef WITH_CONTIKI
+ buf = uip_appdata;
+#endif /* WITH_CONTIKI */
+#ifdef WITH_LWIP
+ LWIP_ASSERT("No package pending", ctx->pending_package != NULL);
+ LWIP_ASSERT("Can only deal with contiguous PBUFs to read the initial details", ctx->pending_package->tot_len == ctx->pending_package->len);
+ buf = ctx->pending_package->payload;
+#endif /* WITH_LWIP */
+
+ pdu = (coap_hdr_t *) buf;
+
+ coap_address_init(&src);
+
+#ifdef WITH_POSIX
+ //bytes_read = recvfrom(ctx->sockfd, buf, sizeof(buf), 0,
+ // &src.addr.sa, &src.size);
+
+ bytes_read = OCRecvFrom( sockfd, (uint8_t*)buf, sizeof(buf), 0,
+ (OCDevAddr*)&src);
+#endif /* WITH_POSIX */
+#ifdef WITH_CONTIKI
+ if(uip_newdata()) {
+ uip_ipaddr_copy(&src.addr, &UIP_IP_BUF->srcipaddr);
+ src.port = UIP_UDP_BUF->srcport;
+ uip_ipaddr_copy(&dst.addr, &UIP_IP_BUF->destipaddr);
+ dst.port = UIP_UDP_BUF->destport;
+
+ bytes_read = uip_datalen();
+ ((char *)uip_appdata)[bytes_read] = 0;
+ PRINTF("Server received %d bytes from [", (int)bytes_read);
+ PRINT6ADDR(&src.addr);
+ PRINTF("]:%d\n", uip_ntohs(src.port));
+ }
+#endif /* WITH_CONTIKI */
+#ifdef WITH_LWIP
+ /* FIXME: use lwip address operation functions */
+ src.addr.addr = ctx->pending_address.addr;
+ src.port = ctx->pending_port;
+ bytes_read = ctx->pending_package->tot_len;
+#endif /* WITH_LWIP */
+
+ if (bytes_read < 0) {
+ warn("coap_read: recvfrom");
+ goto error_early;
+ }
+
+ if ((size_t) bytes_read < sizeof(coap_hdr_t)) {
+ debug("coap_read: discarded invalid frame\n");
+ goto error_early;
+ }
+
+ if (pdu->version != COAP_DEFAULT_VERSION) {
+ debug("coap_read: unknown protocol version\n");
+ goto error_early;
+ }
+
+ node = coap_new_node();
+ if (!node)
+ goto error_early;
+
+#ifdef WITH_LWIP
+ node->pdu = coap_pdu_from_pbuf(ctx->pending_package);
+ ctx->pending_package = NULL;
+#else
+ node->pdu = coap_pdu_init(0, 0, 0, bytes_read);
+#endif
+ if (!node->pdu)
+ goto error;
+
+ coap_ticks(&node->t);
+ memcpy(&node->local, &dst, sizeof(coap_address_t));
+ memcpy(&node->remote, &src, sizeof(coap_address_t));
+
+ if (!coap_pdu_parse((unsigned char *) buf, bytes_read, node->pdu)) {
+ warn("discard malformed PDU");
+ goto error;
+ }
+
+ /* and add new node to receive queue */
+ coap_transaction_id(&node->remote, node->pdu, &node->id);
+ coap_insert_node(&ctx->recvqueue, node);
+
+#ifndef NDEBUG
+ if (LOG_DEBUG <= coap_get_log_level()) {
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 40
+#endif
+ unsigned char addr[INET6_ADDRSTRLEN + 8];
+
+ if (coap_print_addr(&src, addr, INET6_ADDRSTRLEN + 8))
+ debug("** received %d bytes from %s:\n", (int )bytes_read, addr);
+
+ coap_show_pdu(node->pdu);
+ }
+#endif
+
+ return 0;
+
+ error:
+ /* FIXME: send back RST? */
+ coap_delete_node(node);
+ return -1;
+ error_early:
+#ifdef WITH_LWIP
+ /* even if there was an error, clean up */
+ pbuf_free(ctx->pending_package);
+ ctx->pending_package = NULL;
+#endif
+ return -1;
+}
+
+int coap_remove_from_queue(coap_queue_t **queue, coap_tid_t id,
+ coap_queue_t **node) {
+ coap_queue_t *p, *q;
+
+ if (!queue || !*queue)
+ return 0;
+
+ /* replace queue head if PDU's time is less than head's time */
+
+ if (id == (*queue)->id) { /* found transaction */
+ *node = *queue;
+ *queue = (*queue)->next;
+ if (*queue) { /* adjust relative time of new queue head */
+ (*queue)->t += (*node)->t;
+ }
+ (*node)->next = NULL;
+ /* coap_delete_node( q ); */
+ debug("*** removed transaction %u\n", id);
+ return 1;
+ }
+
+ /* search transaction to remove (only first occurence will be removed) */
+ q = *queue;
+ do {
+ p = q;
+ q = q->next;
+ } while (q && id != q->id);
+
+ if (q) { /* found transaction */
+ p->next = q->next;
+ if (p->next) { /* must update relative time of p->next */
+ p->next->t += q->t;
+ }
+ q->next = NULL;
+ *node = q;
+ /* coap_delete_node( q ); */
+ debug("*** removed transaction %u\n", id);
+ return 1;
+ }
+
+ return 0;
+
+}
+
+static inline int token_match(const unsigned char *a, size_t alen,
+ const unsigned char *b, size_t blen) {
+ return alen == blen && (alen == 0 || memcmp(a, b, alen) == 0);
+}
+
+void coap_cancel_all_messages(coap_context_t *context,
+ const coap_address_t *dst, const unsigned char *token,
+ size_t token_length) {
+ /* cancel all messages in sendqueue that are for dst
+ * and use the specified token */
+ coap_queue_t *p, *q;
+
+ debug("cancel_all_messages\n");
+ while (context->sendqueue
+ && coap_address_equals(dst, &context->sendqueue->remote)
+ && token_match(token, token_length,
+ context->sendqueue->pdu->hdr->token,
+ context->sendqueue->pdu->hdr->token_length)) {
+ q = context->sendqueue;
+ context->sendqueue = q->next;
+ debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id));
+ coap_delete_node(q);
+ }
+
+ if (!context->sendqueue)
+ return;
+
+ p = context->sendqueue;
+ q = p->next;
+
+ /* when q is not NULL, it does not match (dst, token), so we can skip it */
+ while (q) {
+ if (coap_address_equals(dst, &q->remote)
+ && token_match(token, token_length, q->pdu->hdr->token,
+ q->pdu->hdr->token_length)) {
+ p->next = q->next;
+ debug("**** removed transaction %d\n", ntohs(q->pdu->hdr->id));
+ coap_delete_node(q);
+ q = p->next;
+ } else {
+ p = q;
+ q = q->next;
+ }
+ }
+}
+
+coap_queue_t *
+coap_find_transaction(coap_queue_t *queue, coap_tid_t id) {
+ while (queue && queue->id != id)
+ queue = queue->next;
+
+ return queue;
+}
+
+coap_pdu_t *
+coap_new_error_response(coap_pdu_t *request, unsigned char code,
+ coap_opt_filter_t opts) {
+ coap_opt_iterator_t opt_iter;
+ coap_pdu_t *response;
+ size_t size = sizeof(coap_hdr_t) + request->hdr->token_length;
+ int type;
+ coap_opt_t *option;
+ unsigned short opt_type = 0; /* used for calculating delta-storage */
+
+#if COAP_ERROR_PHRASE_LENGTH > 0
+ char *phrase = coap_response_phrase(code);
+
+ /* Need some more space for the error phrase and payload start marker */
+ if (phrase)
+ size += strlen(phrase) + 1;
+#endif
+
+ assert(request);
+
+ /* cannot send ACK if original request was not confirmable */
+ type = request->hdr->type == COAP_MESSAGE_CON ?
+ COAP_MESSAGE_ACK : COAP_MESSAGE_NON;
+
+ /* Estimate how much space we need for options to copy from
+ * request. We always need the Token, for 4.02 the unknown critical
+ * options must be included as well. */
+ coap_option_clrb(opts, COAP_OPTION_CONTENT_TYPE); /* we do not want this */
+
+ coap_option_iterator_init(request, &opt_iter, opts);
+
+ /* Add size of each unknown critical option. As known critical
+ options as well as elective options are not copied, the delta
+ value might grow.
+ */
+ while ((option = coap_option_next(&opt_iter))) {
+ unsigned short delta = opt_iter.type - opt_type;
+ /* calculate space required to encode (opt_iter.type - opt_type) */
+ if (delta < 13) {
+ size++;
+ } else if (delta < 269) {
+ size += 2;
+ } else {
+ size += 3;
+ }
+
+ /* add coap_opt_length(option) and the number of additional bytes
+ * required to encode the option length */
+
+ size += coap_opt_length(option);
+ switch (*option & 0x0f) {
+ case 0x0e:
+ size++;
+ /* fall through */
+ case 0x0d:
+ size++;
+ break;
+ default:
+ ;
+ }
+
+ opt_type = opt_iter.type;
+ }
+
+ /* Now create the response and fill with options and payload data. */
+ response = coap_pdu_init(type, code, request->hdr->id, size);
+ if (response) {
+ /* copy token */
+ if (!coap_add_token(response, request->hdr->token_length,
+ request->hdr->token)) {
+ debug("cannot add token to error response\n");
+ coap_delete_pdu(response);
+ return NULL;
+ }
+
+ /* copy all options */
+ coap_option_iterator_init(request, &opt_iter, opts);
+ while ((option = coap_option_next(&opt_iter)))
+ coap_add_option(response, opt_iter.type, COAP_OPT_LENGTH(option),
+ COAP_OPT_VALUE(option));
+
+#if COAP_ERROR_PHRASE_LENGTH > 0
+ /* note that diagnostic messages do not need a Content-Format option. */
+ if (phrase)
+ coap_add_data(response, strlen(phrase), (unsigned char *) phrase);
+#endif
+ }
+
+ return response;
+}
+
+/**
+ * Quick hack to determine the size of the resource description for
+ * .well-known/core.
+ */
+static inline size_t get_wkc_len(coap_context_t *context,
+ coap_opt_t *query_filter) {
+ unsigned char buf[1];
+ size_t len = 0;
+
+ if (print_wellknown(context, buf, &len, UINT_MAX,
+ query_filter) & COAP_PRINT_STATUS_ERROR) {
+ warn("cannot determine length of /.well-known/core\n");
+ return 0;
+ }
+
+ debug("get_wkc_len: print_wellknown() returned %zu\n", len);
+
+ return len;
+}
+
+#define SZX_TO_BYTES(SZX) ((size_t)(1 << ((SZX) + 4)))
+
+coap_pdu_t *
+wellknown_response(coap_context_t *context, coap_pdu_t *request) {
+ coap_pdu_t *resp;
+ coap_opt_iterator_t opt_iter;
+ size_t len, wkc_len;
+ unsigned char buf[2];
+ int result = 0;
+ int need_block2 = 0; /* set to 1 if Block2 option is required */
+ coap_block_t block;
+ coap_opt_t *query_filter;
+ size_t offset = 0;
+
+ resp = coap_pdu_init(
+ request->hdr->type == COAP_MESSAGE_CON ?
+ COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
+ COAP_RESPONSE_CODE(205), request->hdr->id, COAP_MAX_PDU_SIZE);
+ if (!resp) {
+ debug("wellknown_response: cannot create PDU\n");
+ return NULL;
+ }
+
+ if (!coap_add_token(resp, request->hdr->token_length,
+ request->hdr->token)) {
+ debug("wellknown_response: cannot add token\n");
+ goto error;
+ }
+
+ query_filter = coap_check_option(request, COAP_OPTION_URI_QUERY, &opt_iter);
+ wkc_len = get_wkc_len(context, query_filter);
+
+ /* check whether the request contains the Block2 option */
+ if (coap_get_block(request, COAP_OPTION_BLOCK2, &block)) {
+ offset = block.num << (block.szx + 4);
+ if (block.szx > 6) { /* invalid, MUST lead to 4.00 Bad Request */
+ resp->hdr->code = COAP_RESPONSE_CODE(400);
+ return resp;
+ } else if (block.szx > COAP_MAX_BLOCK_SZX) {
+ block.szx = COAP_MAX_BLOCK_SZX;
+ block.num = offset >> (block.szx + 4);
+ }
+
+ need_block2 = 1;
+ }
+
+ /* Check if there is sufficient space to add Content-Format option
+ * and data. We do this before adding the Content-Format option to
+ * avoid sending error responses with that option but no actual
+ * content. */
+ if (resp->max_size <= (size_t) resp->length + 3) {
+ debug("wellknown_response: insufficient storage space\n");
+ goto error;
+ }
+
+ /* Add Content-Format. As we have checked for available storage,
+ * nothing should go wrong here. */
+ assert(
+ coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT)
+ == 1);
+ coap_add_option(resp, COAP_OPTION_CONTENT_FORMAT,
+ coap_encode_var_bytes(buf, COAP_MEDIATYPE_APPLICATION_LINK_FORMAT),
+ buf);
+
+ /* check if Block2 option is required even if not requested */
+ if (!need_block2 && (resp->max_size - (size_t) resp->length < wkc_len)) {
+ assert(resp->length <= resp->max_size);
+ const size_t payloadlen = resp->max_size - resp->length;
+ /* yes, need block-wise transfer */
+ block.num = 0;
+ block.m = 0; /* the M bit is set by coap_write_block_opt() */
+ block.szx = COAP_MAX_BLOCK_SZX;
+ while (payloadlen < SZX_TO_BYTES(block.szx)) {
+ if (block.szx == 0) {
+ debug(
+ "wellknown_response: message to small even for szx == 0\n");
+ goto error;
+ } else {
+ block.szx--;
+ }
+ }
+
+ need_block2 = 1;
+ }
+
+ /* write Block2 option if necessary */
+ if (need_block2) {
+ if (coap_write_block_opt(&block, COAP_OPTION_BLOCK2, resp, wkc_len)
+ < 0) {
+ debug("wellknown_response: cannot add Block2 option\n");
+ goto error;
+ }
+ }
+
+ /* Manually set payload of response to let print_wellknown() write,
+ * into our buffer without copying data. */
+
+ resp->data = (unsigned char *) resp->hdr + resp->length;
+ *resp->data = COAP_PAYLOAD_START;
+ resp->data++;
+ resp->length++;
+ len = need_block2 ? SZX_TO_BYTES(block.szx) : resp->max_size - resp->length;
+
+ result = print_wellknown(context, resp->data, &len, offset, query_filter);
+ if ((result & COAP_PRINT_STATUS_ERROR) != 0) {
+ debug("print_wellknown failed\n");
+ goto error;
+ }
+
+ resp->length += COAP_PRINT_OUTPUT_LENGTH(result);
+ return resp;
+
+ error:
+ /* set error code 5.03 and remove all options and data from response */
+ resp->hdr->code = COAP_RESPONSE_CODE(503);
+ resp->length = sizeof(coap_hdr_t) + resp->hdr->token_length;
+ return resp;
+}
+
+#define WANT_WKC(Pdu,Key) \
+ (((Pdu)->hdr->code == COAP_REQUEST_GET) && is_wkc(Key))
+
+#if 0
+void
+handle_request(coap_context_t *context, coap_queue_t *node) {
+ coap_method_handler_t h = NULL;
+ coap_pdu_t *response = NULL;
+ coap_opt_filter_t opt_filter;
+ coap_resource_t *resource;
+ coap_key_t key;
+
+ coap_option_filter_clear(opt_filter);
+
+ /* try to find the resource from the request URI */
+ coap_hash_request_uri(node->pdu, key);
+ resource = coap_get_resource_from_key(context, key);
+
+ if (!resource) {
+ /* The resource was not found. Check if the request URI happens to
+ * be the well-known URI. In that case, we generate a default
+ * response, otherwise, we return 4.04 */
+
+ switch(node->pdu->hdr->code) {
+
+ case COAP_REQUEST_GET:
+ if (is_wkc(key)) { /* GET request for .well-known/core */
+ info("create default response for %s\n", COAP_DEFAULT_URI_WELLKNOWN);
+ response = wellknown_response(context, node->pdu);
+
+ } else { /* GET request for any another resource, return 4.04 */
+
+ debug("GET for unknown resource 0x%02x%02x%02x%02x, return 4.04\n",
+ key[0], key[1], key[2], key[3]);
+ response =
+ coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(404),
+ opt_filter);
+ }
+ break;
+
+ default: /* any other request type */
+
+ debug("unhandled request for unknown resource 0x%02x%02x%02x%02x\r\n",
+ key[0], key[1], key[2], key[3]);
+ if (!coap_is_mcast(&node->local))
+ response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(405),
+ opt_filter);
+ }
+
+ if (response && coap_send(context, &node->remote, response) == COAP_INVALID_TID) {
+ warn("cannot send response for transaction %u\n", node->id);
+ }
+ coap_delete_pdu(response);
+
+ return;
+ }
+
+ /* the resource was found, check if there is a registered handler */
+ if ((size_t)node->pdu->hdr->code - 1 <
+ sizeof(resource->handler)/sizeof(coap_method_handler_t))
+ h = resource->handler[node->pdu->hdr->code - 1];
+
+ if (h) {
+ debug("call custom handler for resource 0x%02x%02x%02x%02x\n",
+ key[0], key[1], key[2], key[3]);
+ response = coap_pdu_init(node->pdu->hdr->type == COAP_MESSAGE_CON
+ ? COAP_MESSAGE_ACK
+ : COAP_MESSAGE_NON,
+ 0, node->pdu->hdr->id, COAP_MAX_PDU_SIZE);
+
+ /* Implementation detail: coap_add_token() immediately returns 0
+ if response == NULL */
+ if (coap_add_token(response, node->pdu->hdr->token_length,
+ node->pdu->hdr->token)) {
+ str token = {node->pdu->hdr->token_length, node->pdu->hdr->token};
+
+ h(context, resource, &node->remote,
+ node->pdu, &token, response);
+ if (response->hdr->type != COAP_MESSAGE_NON ||
+ (response->hdr->code >= 64
+ && !coap_is_mcast(&node->local))) {
+ if (coap_send(context, &node->remote, response) == COAP_INVALID_TID) {
+ debug("cannot send response for message %d\n", node->pdu->hdr->id);
+ }
+ }
+
+ coap_delete_pdu(response);
+ } else {
+ warn("cannot generate response\r\n");
+ }
+ } else {
+ if (WANT_WKC(node->pdu, key)) {
+ debug("create default response for %s\n", COAP_DEFAULT_URI_WELLKNOWN);
+ response = wellknown_response(context, node->pdu);
+ } else
+ response = coap_new_error_response(node->pdu, COAP_RESPONSE_CODE(405),
+ opt_filter);
+
+ if (!response || (coap_send(context, &node->remote, response)
+ == COAP_INVALID_TID)) {
+ debug("cannot send response for transaction %u\n", node->id);
+ }
+ coap_delete_pdu(response);
+ }
+}
+#endif
+static inline void handle_request(coap_context_t *context, coap_queue_t *rcvd) {
+
+ /* Call application-specific reponse handler when available. If
+ * not, we must acknowledge confirmable messages. */
+ if (context->request_handler) {
+ context->request_handler(context, rcvd);
+ } else {
+ /* send ACK if rcvd is confirmable (i.e. a separate response) */
+ coap_send_ack(context, &rcvd->remote, rcvd->pdu);
+ }
+}
+
+static inline void handle_response(coap_context_t *context, coap_queue_t *rcvd) {
+
+ /* Call application-specific reponse handler when available. If
+ * not, we must acknowledge confirmable messages. */
+ if (context->response_handler) {
+ context->response_handler(context, rcvd);
+ } else {
+ /* send ACK if rcvd is confirmable (i.e. a separate response) */
+ coap_send_ack(context, &rcvd->remote, rcvd->pdu);
+ }
+}
+
+static inline int
+#ifdef __GNUC__
+handle_locally(coap_context_t *context __attribute__ ((unused)),
+ coap_queue_t *node __attribute__ ((unused))) {
+#else /* not a GCC */
+ handle_locally(coap_context_t *context, coap_queue_t *node) {
+#endif /* GCC */
+ /* this function can be used to check if node->pdu is really for us */
+ return 1;
+ }
+
+ /**
+ * This function handles RST messages received for the message passed
+ * in @p sent.
+ */
+ static void coap_handle_rst(coap_context_t *context,
+ const coap_queue_t *sent) {
+#ifndef WITHOUT_OBSERVE
+ coap_resource_t *r;
+#ifndef COAP_RESOURCES_NOHASH
+ coap_resource_t *tmp;
+#endif
+ str token = { 0, NULL };
+
+ /* remove observer for this resource, if any
+ * get token from sent and try to find a matching resource. Uh!
+ */
+
+ COAP_SET_STR(&token, sent->pdu->hdr->token_length,
+ sent->pdu->hdr->token);
+
+#ifndef WITH_CONTIKI
+#ifdef COAP_RESOURCES_NOHASH
+ LL_FOREACH(context->resources, r) {
+#else
+ HASH_ITER(hh, context->resources, r, tmp)
+ {
+#endif
+ coap_delete_observer(r, &sent->remote, &token);
+ coap_cancel_all_messages(context, &sent->remote, token.s,
+ token.length);
+ }
+#else /* WITH_CONTIKI */
+ r = (coap_resource_t *)resource_storage.mem;
+ for (i = 0; i < resource_storage.num; ++i, ++r) {
+ if (resource_storage.count[i]) {
+ coap_delete_observer(r, &sent->remote, &token);
+ coap_cancel_all_messages(context, &sent->remote, token.s, token.length);
+ }
+ }
+#endif /* WITH_CONTIKI */
+#endif /* WITOUT_OBSERVE */
+ }
+
+ void coap_dispatch(coap_context_t *context) {
+ coap_queue_t *rcvd = NULL, *sent = NULL;
+ coap_pdu_t *response;
+ coap_opt_filter_t opt_filter;
+
+ if (!context)
+ return;
+
+ memset(opt_filter, 0, sizeof(coap_opt_filter_t));
+
+ while (context->recvqueue) {
+ rcvd = context->recvqueue;
+
+ /* remove node from recvqueue */
+ context->recvqueue = context->recvqueue->next;
+ rcvd->next = NULL;
+
+ if (rcvd->pdu->hdr->version != COAP_DEFAULT_VERSION) {
+ debug("dropped packet with unknown version %u\n",
+ rcvd->pdu->hdr->version);
+ goto cleanup;
+ }
+
+ switch (rcvd->pdu->hdr->type) {
+ case COAP_MESSAGE_NON: /* check for unknown critical options */
+ if (coap_option_check_critical(context, rcvd->pdu, opt_filter)
+ == 0)
+ goto cleanup;
+ break;
+ default:
+ // TODO : need to handle other message types in coap_dispatch;;;;;;;;;;;;;;;;
+ debug("Need to handle other message types in coap_dispatch;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;");
+ }
+#if 0
+ switch (rcvd->pdu->hdr->type) {
+ case COAP_MESSAGE_ACK:
+ /* find transaction in sendqueue to stop retransmission */
+ coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent);
+
+ if (rcvd->pdu->hdr->code == 0)
+ goto cleanup;
+
+ /* FIXME: if sent code was >= 64 the message might have been a
+ * notification. Then, we must flag the observer to be alive
+ * by setting obs->fail_cnt = 0. */
+ if (sent && COAP_RESPONSE_CLASS(sent->pdu->hdr->code) == 2) {
+ const str token = {sent->pdu->hdr->token_length,
+ sent->pdu->hdr->token};
+ coap_touch_observer(context, &sent->remote, &token);
+ }
+ break;
+
+ case COAP_MESSAGE_RST:
+ /* We have sent something the receiver disliked, so we remove
+ * not only the transaction but also the subscriptions we might
+ * have. */
+
+ coap_log(LOG_ALERT, "got RST for message %u\n",
+ ntohs(rcvd->pdu->hdr->id));
+
+ /* find transaction in sendqueue to stop retransmission */
+ coap_remove_from_queue(&context->sendqueue, rcvd->id, &sent);
+
+ if (sent)
+ coap_handle_rst(context, sent);
+ goto cleanup;
+
+ case COAP_MESSAGE_NON: /* check for unknown critical options */
+ if (coap_option_check_critical(context, rcvd->pdu, opt_filter)
+ == 0)
+ goto cleanup;
+ break;
+
+ case COAP_MESSAGE_CON: /* check for unknown critical options */
+ if (coap_option_check_critical(context, rcvd->pdu, opt_filter)
+ == 0) {
+
+ /* FIXME: send response only if we have received a request. Otherwise,
+ * send RST. */
+ response = coap_new_error_response(rcvd->pdu,
+ COAP_RESPONSE_CODE(402), opt_filter);
+
+ if (!response)
+ warn("coap_dispatch: cannot create error reponse\n");
+ else {
+ if (coap_send(context, &rcvd->remote,
+ response) == COAP_INVALID_TID) {
+ warn("coap_dispatch: error sending reponse\n");
+ }
+ coap_delete_pdu(response);
+ }
+
+ goto cleanup;
+ }
+ break;
+ }
+#endif
+
+ /* Pass message to upper layer if a specific handler was
+ * registered for a request that should be handled locally. */
+ if (handle_locally(context, rcvd)) {
+ if (COAP_MESSAGE_IS_REQUEST(rcvd->pdu->hdr))
+ handle_request(context, rcvd);
+ else if (COAP_MESSAGE_IS_RESPONSE(rcvd->pdu->hdr))
+ handle_response(context, rcvd);
+ else {
+ debug("dropped message with invalid code\n");
+ coap_send_message_type(context, &rcvd->remote, rcvd->pdu,
+ COAP_MESSAGE_RST);
+ }
+ }
+
+ // we should not retrying responses.....
+ cleanup: coap_delete_node(sent);
+ coap_delete_node(rcvd);
+ }
+ }
+
+ int coap_can_exit(coap_context_t *context) {
+ return !context
+ || (context->recvqueue == NULL && context->sendqueue == NULL);
+ }
+
+#ifdef WITH_CONTIKI
+
+ /*---------------------------------------------------------------------------*/
+ /* CoAP message retransmission */
+ /*---------------------------------------------------------------------------*/
+ PROCESS_THREAD(coap_retransmit_process, ev, data)
+ {
+ coap_tick_t now;
+ coap_queue_t *nextpdu;
+
+ PROCESS_BEGIN();
+
+ debug("Started retransmit process\r\n");
+
+ while(1) {
+ PROCESS_YIELD();
+ if (ev == PROCESS_EVENT_TIMER) {
+ if (etimer_expired(&the_coap_context.retransmit_timer)) {
+
+ nextpdu = coap_peek_next(&the_coap_context);
+
+ coap_ticks(&now);
+ while (nextpdu && nextpdu->t <= now) {
+ coap_retransmit(&the_coap_context, coap_pop_next(&the_coap_context));
+ nextpdu = coap_peek_next(&the_coap_context);
+ }
+
+ /* need to set timer to some value even if no nextpdu is available */
+ etimer_set(&the_coap_context.retransmit_timer,
+ nextpdu ? nextpdu->t - now : 0xFFFF);
+ }
+#ifndef WITHOUT_OBSERVE
+ if (etimer_expired(&the_coap_context.notify_timer)) {
+ coap_check_notify(&the_coap_context);
+ etimer_reset(&the_coap_context.notify_timer);
+ }
+#endif /* WITHOUT_OBSERVE */
+ }
+ }
+
+ PROCESS_END();
+ }
+ /*---------------------------------------------------------------------------*/
+
+#endif /* WITH_CONTIKI */
+
+#ifdef WITH_LWIP
+ /* FIXME: retransmits that are not required any more due to incoming packages
+ * do *not* get cleared at the moment, the wakeup when the transmission is due
+ * is silently accepted. this is mainly due to the fact that the required
+ * checks are similar in two places in the code (when receiving ACK and RST)
+ * and that they cause more than one patch chunk, as it must be first checked
+ * whether the sendqueue item to be dropped is the next one pending, and later
+ * the restart function has to be called. nothing insurmountable, but it can
+ * also be implemented when things have stabilized, and the performance
+ * penality is minimal
+ *
+ * also, this completely ignores COAP_RESOURCE_CHECK_TIME.
+ * */
+
+ static void coap_retransmittimer_execute(void *arg)
+ {
+ coap_context_t *ctx = (coap_context_t*)arg;
+ coap_tick_t now;
+ coap_tick_t elapsed;
+ coap_queue_t *nextinqueue;
+
+ ctx->timer_configured = 0;
+
+ coap_ticks(&now);
+
+ elapsed = now - ctx->sendqueue_basetime; /* that's positive for sure, and unless we haven't been called for a complete wrapping cycle, did not wrap */
+
+ nextinqueue = coap_peek_next(ctx);
+ while (nextinqueue != NULL)
+ {
+ if (nextinqueue->t > elapsed) {
+ nextinqueue->t -= elapsed;
+ break;
+ } else {
+ elapsed -= nextinqueue->t;
+ coap_retransmit(ctx, coap_pop_next(ctx));
+ nextinqueue = coap_peek_next(ctx);
+ }
+ }
+
+ ctx->sendqueue_basetime = now;
+
+ coap_retransmittimer_restart(ctx);
+ }
+
+ static void coap_retransmittimer_restart(coap_context_t *ctx)
+ {
+ coap_tick_t now, elapsed, delay;
+
+ if (ctx->timer_configured)
+ {
+ printf("clearing\n");
+ sys_untimeout(coap_retransmittimer_execute, (void*)ctx);
+ ctx->timer_configured = 0;
+ }
+ if (ctx->sendqueue != NULL)
+ {
+ coap_ticks(&now);
+ elapsed = now - ctx->sendqueue_basetime;
+ if (ctx->sendqueue->t >= elapsed) {
+ delay = ctx->sendqueue->t - elapsed;
+ } else {
+ /* a strange situation, but not completely impossible.
+ *
+ * this happens, for example, right after
+ * coap_retransmittimer_execute, when a retransmission
+ * was *just not yet* due, and the clock ticked before
+ * our coap_ticks was called.
+ *
+ * not trying to retransmit anything now, as it might
+ * cause uncontrollable recursion; let's just try again
+ * with the next main loop run.
+ * */
+ delay = 0;
+ }
+
+ printf("scheduling for %d ticks\n", delay);
+ sys_timeout(delay, coap_retransmittimer_execute, (void*)ctx);
+ ctx->timer_configured = 1;
+ }
+ }
+#endif
--- /dev/null
+/* net.h -- CoAP network interface
+ *
+ * Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef _COAP_NET_H_
+#define _COAP_NET_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "config.h"
+
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#else
+#ifndef assert
+#warning "assertions are disabled"
+# define assert(x)
+#endif
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#ifdef HAVE_NETINET_IN_H
+#include <netinet/in.h>
+#endif
+#ifdef HAVE_TIME_H
+#include <time.h>
+#endif
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+
+#ifdef WITH_LWIP
+#include <lwip/ip_addr.h>
+#endif
+
+#include "option.h"
+#include "address.h"
+#include "prng.h"
+#include "pdu.h"
+#include "coap_time.h"
+
+struct coap_queue_t;
+
+typedef struct coap_queue_t {
+ struct coap_queue_t *next;
+
+ coap_tick_t t; /**< when to send PDU for the next time */
+ unsigned char retransmit_cnt; /**< retransmission counter, will be removed when zero */
+ unsigned int timeout; /**< the randomized timeout value */
+
+ coap_address_t local; /**< local address */
+ coap_address_t remote; /**< remote address */
+ coap_tid_t id; /**< unique transaction id */
+
+ coap_pdu_t *pdu; /**< the CoAP PDU to send */
+} coap_queue_t;
+
+/** Adds node to given queue, ordered by node->t. */
+int coap_insert_node(coap_queue_t **queue, coap_queue_t *node);
+
+/** Destroys specified node. */
+int coap_delete_node(coap_queue_t *node);
+
+/** Removes all items from given queue and frees the allocated storage. */
+void coap_delete_all(coap_queue_t *queue);
+
+/** Creates a new node suitable for adding to the CoAP sendqueue. */
+coap_queue_t *coap_new_node();
+
+struct coap_resource_t;
+struct coap_context_t;
+#ifndef WITHOUT_ASYNC
+struct coap_async_state_t;
+#endif
+
+/** Message handler that is used as call-back in coap_context_t */
+typedef void (*coap_request_handler_t)(struct coap_context_t *,
+ const coap_queue_t * rcvd);
+
+/** Message handler that is used as call-back in coap_context_t */
+typedef void (*coap_response_handler_t)(struct coap_context_t *,
+ const coap_queue_t * rcvd);
+
+#define COAP_MID_CACHE_SIZE 3
+typedef struct {
+ unsigned char flags[COAP_MID_CACHE_SIZE];
+ coap_key_t item[COAP_MID_CACHE_SIZE];
+} coap_mid_cache_t;
+
+/** The CoAP stack's global state is stored in a coap_context_t object */
+typedef struct coap_context_t {
+ coap_opt_filter_t known_options;
+#ifndef WITH_CONTIKI
+ struct coap_resource_t *resources; /**< hash table or list of known resources */
+#endif /* WITH_CONTIKI */
+#ifndef WITHOUT_ASYNC
+ /** list of asynchronous transactions */
+ struct coap_async_state_t *async_state;
+#endif /* WITHOUT_ASYNC */
+ /**
+ * The time stamp in the first element of the sendqeue is relative
+ * to sendqueue_basetime. */
+ coap_tick_t sendqueue_basetime;
+ coap_queue_t *sendqueue, *recvqueue;
+#if WITH_POSIX
+ int sockfd; /**< send/receive socket */
+ int sockfd_wellknown; /**< well-known discovery socket */
+#endif /* WITH_POSIX */
+#ifdef WITH_CONTIKI
+ struct uip_udp_conn *conn; /**< uIP connection object */
+
+ struct etimer retransmit_timer; /**< fires when the next packet must be sent */
+ struct etimer notify_timer; /**< used to check resources periodically */
+#endif /* WITH_CONTIKI */
+#ifdef WITH_LWIP
+ struct udp_pcb *pcb; /**< the underlying lwIP UDP PCB */
+ struct pbuf *pending_package; /**< pbuf containing the last received package if not handled yet. This is only used to pass the package from the udp_recv callback into the coap_read function, which frees the pbuf and clears this field. */
+ ip_addr_t pending_address; /**< the address associated with pending_package */
+ u16_t pending_port; /**< the port associated with pending_package */
+
+ uint8_t timer_configured; /**< Set to 1 when a retransmission is scheduled using lwIP timers for this context, otherwise 0. */
+#endif /* WITH_LWIP */
+
+ /**
+ * The last message id that was used is stored in this field. The
+ * initial value is set by coap_new_context() and is usually a
+ * random value. A new message id can be created with
+ * coap_new_message_id().
+ */
+ unsigned short message_id;
+
+ /**
+ * The next value to be used for Observe. This field is global for
+ * all resources and will be updated when notifications are created.
+ */
+ unsigned int observe;
+
+ coap_request_handler_t request_handler;
+ coap_response_handler_t response_handler;
+} coap_context_t;
+
+/**
+ * Registers a new message handler that is called whenever a request
+ * was received that matches an ongoing transaction.
+ *
+ * @param context The context to register the handler for.
+ * @param handler The response handler to register.
+ */
+static inline void
+coap_register_request_handler(coap_context_t *context,
+ coap_request_handler_t handler) {
+ context->request_handler = handler;
+}
+
+/**
+ * Registers a new message handler that is called whenever a response
+ * was received that matches an ongoing transaction.
+ *
+ * @param context The context to register the handler for.
+ * @param handler The response handler to register.
+ */
+static inline void
+coap_register_response_handler(coap_context_t *context,
+ coap_response_handler_t handler) {
+ context->response_handler = handler;
+}
+
+/**
+ * Registers the option type @p type with the given context object @p
+ * ctx.
+ *
+ * @param ctx The context to use.
+ * @param type The option type to register.
+ */
+inline static void
+coap_register_option(coap_context_t *ctx, unsigned char type) {
+ coap_option_setb(ctx->known_options, type);
+}
+
+
+/**
+ * Set sendqueue_basetime in the given context object @p ctx to @p
+ * now. This function returns the number of elements in the queue
+ * head that have timed out.
+ */
+unsigned int coap_adjust_basetime(coap_context_t *ctx, coap_tick_t now);
+
+/** Returns the next pdu to send without removing from sendqeue. */
+coap_queue_t *coap_peek_next( coap_context_t *context );
+
+/** Returns the next pdu to send and removes it from the sendqeue. */
+coap_queue_t *coap_pop_next( coap_context_t *context );
+
+/** Creates a new coap_context_t object that will hold the CoAP stack status. */
+coap_context_t *coap_new_context(const coap_address_t *listen_addr);
+
+/** Joins the CoAP stack to well-known multicast address. */
+int coap_join_wellknown_group(coap_context_t *context,
+ const coap_address_t *multicast_addr);
+
+/**
+ * Returns a new message id and updates @p context->message_id
+ * accordingly. The message id is returned in network byte order
+ * to make it easier to read in tracing tools.
+ *
+ * @param context the current coap_context_t object
+ * @return incremented message id in network byte order
+ */
+static inline unsigned short
+coap_new_message_id(coap_context_t *context) {
+#ifndef WITH_CONTIKI
+ return htons(++(context->message_id));
+#else /* WITH_CONTIKI */
+ return uip_htons(++context->message_id);
+#endif
+}
+
+/* CoAP stack context must be released with coap_free_context() */
+void coap_free_context( coap_context_t *context );
+
+
+/**
+ * Sends a confirmed CoAP message to given destination. The memory
+ * that is allocated by pdu will not be released by
+ * coap_send_confirmed(). The caller must release the memory.
+ *
+ * @param context The CoAP context to use.
+ * @param dst The address to send to.
+ * @param pdu The CoAP PDU to send.
+ * @return The message id of the sent message or @c COAP_INVALID_TID on error.
+ */
+coap_tid_t coap_send_confirmed(coap_context_t *context,
+ const coap_address_t *dst,
+ coap_pdu_t *pdu);
+
+/**
+ * Creates a new ACK PDU with specified error @p code. The options
+ * specified by the filter expression @p opts will be copied from the
+ * original request contained in @p request. Unless @c
+ * SHORT_ERROR_RESPONSE was defined at build time, the textual reason
+ * phrase for @p code will be added as payload, with Content-Type @c
+ * 0. This function returns a pointer to the new response message, or
+ * @c NULL on error. The storage allocated for the new message must be
+ * relased with coap_free().
+ *
+ * @param request Specification of the received (confirmable) request.
+ * @param code The error code to set.
+ * @param opts An option filter that specifies which options to copy
+ * from the original request in @p node.
+ *
+ * @return A pointer to the new message or @c NULL on error.
+ */
+coap_pdu_t *coap_new_error_response(coap_pdu_t *request,
+ unsigned char code,
+ coap_opt_filter_t opts);
+/**
+ * Sends a non-confirmed CoAP message to given destination. The memory
+ * that is allocated by pdu will not be released by coap_send().
+ * The caller must release the memory.
+ *
+ * @param context The CoAP context to use.
+ * @param dst The address to send to.
+ * @param pdu The CoAP PDU to send.
+ * @return The message id of the sent message or @c COAP_INVALID_TID on error.
+ */
+coap_tid_t coap_send(coap_context_t *context,
+ const coap_address_t *dst,
+ coap_pdu_t *pdu);
+
+/**
+ * Sends an error response with code @p code for request @p request to
+ * @p dst. @p opts will be passed to coap_new_error_response() to
+ * copy marked options from the request. This function returns the
+ * transaction id if the message was sent, or @c COAP_INVALID_TID
+ * otherwise.
+ *
+ * @param context The context to use.
+ * @param request The original request to respond to.
+ * @param dst The remote peer that sent the request.
+ * @param code The reponse code.
+ * @param opts A filter that specifies the options to copy from the
+ * @p request.
+ *
+ * @return The transaction id if the message was sent, or @c
+ * COAP_INVALID_TID otherwise.
+ */
+coap_tid_t coap_send_error(coap_context_t *context,
+ coap_pdu_t *request,
+ const coap_address_t *dst,
+ unsigned char code,
+ coap_opt_filter_t opts);
+
+/**
+ * Helper funktion to create and send a message with @p type (usually
+ * ACK or RST). This function returns @c COAP_INVALID_TID when the
+ * message was not sent, a valid transaction id otherwise.
+ *
+ * @param context The CoAP context.
+ * @param dst Where to send the context.
+ * @param request The request that should be responded to.
+ * @param type Which type to set
+ * @return transaction id on success or @c COAP_INVALID_TID otherwise.
+ */
+coap_tid_t
+coap_send_message_type(coap_context_t *context,
+ const coap_address_t *dst,
+ coap_pdu_t *request,
+ unsigned char type);
+/**
+ * Sends an ACK message with code @c 0 for the specified @p request to
+ * @p dst. This function returns the corresponding transaction id if
+ * the message was sent or @c COAP_INVALID_TID on error.
+ *
+ * @param context The context to use.
+ * @param dst The destination address.
+ * @param request The request to be acknowledged.
+ *
+ * @return The transaction id if ACK was sent or @c COAP_INVALID_TID
+ * on error.
+ */
+coap_tid_t coap_send_ack(coap_context_t *context,
+ const coap_address_t *dst,
+ coap_pdu_t *request);
+
+/**
+ * Sends an RST message with code @c 0 for the specified @p request to
+ * @p dst. This function returns the corresponding transaction id if
+ * the message was sent or @c COAP_INVALID_TID on error.
+ *
+ * @param context The context to use.
+ * @param dst The destination address.
+ * @param request The request to be reset.
+ *
+ * @return The transaction id if RST was sent or @c COAP_INVALID_TID
+ * on error.
+ */
+static inline coap_tid_t
+coap_send_rst(coap_context_t *context,
+ const coap_address_t *dst,
+ coap_pdu_t *request) {
+ return coap_send_message_type(context, dst, request, COAP_MESSAGE_RST);
+}
+
+/** Handles retransmissions of confirmable messages */
+coap_tid_t coap_retransmit( coap_context_t *context, coap_queue_t *node );
+
+/**
+ * Reads data from the network and tries to parse as CoAP PDU. On success, 0 is returned
+ * and a new node with the parsed PDU is added to the receive queue in the specified context
+ * object.
+ */
+int coap_read( coap_context_t *context, int sockfd );
+
+/**
+ * Calculates a unique transaction id from given arguments @p peer and
+ * @p pdu. The id is returned in @p id.
+ *
+ * @param peer The remote party who sent @p pdu.
+ * @param pdu The message that initiated the transaction.
+ * @param id Set to the new id.
+ */
+void coap_transaction_id(const coap_address_t *peer, const coap_pdu_t *pdu,
+ coap_tid_t *id);
+
+/**
+ * This function removes the element with given @p id from the list
+ * given list. If @p id was found, @p node is updated to point to the
+ * removed element. Note that the storage allocated by @p node is
+ * @b not released. The caller must do this manually using
+ * coap_delete_node(). This function returns @c 1 if the element with
+ * id @p id was found, @c 0 otherwise. For a return value of @c 0,
+ * the contents of @p node is undefined.
+ *
+ * @param queue The queue to search for @p id.
+ * @param id The node id to look for.
+ * @param node If found, @p node is updated to point to the
+ * removed node. You must release the storage pointed to by
+ * @p node manually.
+ *
+ * @return @c 1 if @p id was found, @c 0 otherwise.
+ */
+int coap_remove_from_queue(coap_queue_t **queue,
+ coap_tid_t id,
+ coap_queue_t **node);
+
+/**
+ * Removes the transaction identified by @p id from given @p queue.
+ * This is a convenience function for coap_remove_from_queue() with
+ * automatic deletion of the removed node.
+ *
+ * @param queue The queue to search for @p id.
+ * @param id The transaction id.
+ *
+ * @return @c 1 if node was found, removed and destroyed, @c 0 otherwise.
+ */
+inline static int
+coap_remove_transaction(coap_queue_t **queue, coap_tid_t id) {
+ coap_queue_t *node;
+ if (!coap_remove_from_queue(queue, id, &node))
+ return 0;
+
+ coap_delete_node(node);
+ return 1;
+}
+
+/**
+ * Retrieves transaction from queue.
+ * @queue The transaction queue to be searched
+ * @id Unique key of the transaction to find.
+ * @return A pointer to the transaction object or NULL if not found
+ */
+coap_queue_t *coap_find_transaction(coap_queue_t *queue, coap_tid_t id);
+
+/**
+ * Cancels all outstanding messages for peer @p dst that have the
+ * specified token.
+ *
+ * @param context The context in use
+ * @param dst Destination address of the messages to remove.
+ * @param token Message token
+ * @param token_length Actual length of @p token
+ */
+void coap_cancel_all_messages(coap_context_t *context,
+ const coap_address_t *dst,
+ const unsigned char *token,
+ size_t token_length);
+
+/** Dispatches the PDUs from the receive queue in given context. */
+void coap_dispatch( coap_context_t *context );
+
+/** Returns 1 if there are no messages to send or to dispatch in the context's queues. */
+int coap_can_exit( coap_context_t *context );
+
+/**
+ * Returns the current value of an internal tick counter. The counter
+ * counts \c COAP_TICKS_PER_SECOND ticks every second.
+ */
+void coap_ticks(coap_tick_t *);
+
+/**
+ * Verifies that @p pdu contains no unknown critical options. Options
+ * must be registered at @p ctx, using the function
+ * coap_register_option(). A basic set of options is registered
+ * automatically by coap_new_context(). This function returns @c 1 if
+ * @p pdu is ok, @c 0 otherwise. The given filter object @p unknown
+ * will be updated with the unknown options. As only @c COAP_MAX_OPT
+ * options can be signalled this way, remaining options must be
+ * examined manually.
+ *
+ * @code
+ coap_opt_filter_t f = COAP_OPT_NONE;
+ coap_opt_iterator_t opt_iter;
+
+ if (coap_option_check_critical(ctx, pdu, f) == 0) {
+ coap_option_iterator_init(pdu, &opt_iter, f);
+
+ while (coap_option_next(&opt_iter)) {
+ if (opt_iter.type & 0x01) {
+ ... handle unknown critical option in opt_iter ...
+ }
+ }
+ }
+ * @endcode
+ *
+ * @param ctx The context where all known options are registered.
+ * @param pdu The PDU to check.
+ * @param unknown The output filter that will be updated to indicate the
+ * unknown critical options found in @p pdu.
+ *
+ * @return @c 1 if everything was ok, @c 0 otherwise.
+ */
+int coap_option_check_critical(coap_context_t *ctx,
+ coap_pdu_t *pdu,
+ coap_opt_filter_t unknown);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _COAP_NET_H_ */
--- /dev/null
+/*
+ * option.c -- helpers for handling options in CoAP PDUs
+ *
+ * Copyright (C) 2010-2013 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+
+#include "config.h"
+
+#if defined(HAVE_ASSERT_H) && !defined(assert)
+# include <assert.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+
+#include "option.h"
+#include "debug.h"
+
+coap_opt_t *
+options_start(coap_pdu_t *pdu) {
+
+ if (pdu && pdu->hdr &&
+ (pdu->hdr->token + pdu->hdr->token_length
+ < (unsigned char *)pdu->hdr + pdu->length)) {
+
+ coap_opt_t *opt = pdu->hdr->token + pdu->hdr->token_length;
+ return (*opt == COAP_PAYLOAD_START) ? NULL : opt;
+
+ } else
+ return NULL;
+}
+
+size_t
+coap_opt_parse(const coap_opt_t *opt, size_t length, coap_option_t *result) {
+
+ const coap_opt_t *opt_start = opt; /* store where parsing starts */
+
+ assert(opt); assert(result);
+
+#define ADVANCE_OPT(o,e,step) if ((e) < step) { \
+ debug("cannot advance opt past end\n"); \
+ return 0; \
+ } else { \
+ (e) -= step; \
+ (o) = ((unsigned char *)(o)) + step; \
+ }
+
+ if (length < 1)
+ return 0;
+
+ result->delta = (*opt & 0xf0) >> 4;
+ result->length = *opt & 0x0f;
+
+ switch(result->delta) {
+ case 15:
+ if (*opt != COAP_PAYLOAD_START)
+ debug("ignored reserved option delta 15\n");
+ return 0;
+ case 14:
+ /* Handle two-byte value: First, the MSB + 269 is stored as delta value.
+ * After that, the option pointer is advanced to the LSB which is handled
+ * just like case delta == 13. */
+ ADVANCE_OPT(opt,length,1);
+ result->delta = ((*opt & 0xff) << 8) + 269;
+ if (result->delta < 269) {
+ debug("delta too large\n");
+ return 0;
+ }
+ /* fall through */
+ case 13:
+ ADVANCE_OPT(opt,length,1);
+ result->delta += *opt & 0xff;
+ break;
+
+ default:
+ ;
+ }
+
+ switch(result->length) {
+ case 15:
+ debug("found reserved option length 15\n");
+ return 0;
+ case 14:
+ /* Handle two-byte value: First, the MSB + 269 is stored as delta value.
+ * After that, the option pointer is advanced to the LSB which is handled
+ * just like case delta == 13. */
+ ADVANCE_OPT(opt,length,1);
+ result->length = ((*opt & 0xff) << 8) + 269;
+ /* fall through */
+ case 13:
+ ADVANCE_OPT(opt,length,1);
+ result->length += *opt & 0xff;
+ break;
+
+ default:
+ ;
+ }
+
+ ADVANCE_OPT(opt,length,1);
+ /* opt now points to value, if present */
+
+ result->value = (unsigned char *)opt;
+ if (length < result->length) {
+ debug("invalid option length\n");
+ return 0;
+ }
+
+#undef ADVANCE_OPT
+
+ return (opt + result->length) - opt_start;
+}
+
+coap_opt_iterator_t *
+coap_option_iterator_init(coap_pdu_t *pdu, coap_opt_iterator_t *oi,
+ const coap_opt_filter_t filter) {
+ assert(pdu);
+ assert(pdu->hdr);
+ assert(oi);
+
+ memset(oi, 0, sizeof(coap_opt_iterator_t));
+
+ oi->next_option = (unsigned char *)pdu->hdr + sizeof(coap_hdr_t)
+ + pdu->hdr->token_length;
+ if ((unsigned char *)pdu->hdr + pdu->length <= oi->next_option) {
+ oi->bad = 1;
+ return NULL;
+ }
+
+ assert((sizeof(coap_hdr_t) + pdu->hdr->token_length) <= pdu->length);
+
+ oi->length = pdu->length - (sizeof(coap_hdr_t) + pdu->hdr->token_length);
+
+ if (filter) {
+ memcpy(oi->filter, filter, sizeof(coap_opt_filter_t));
+ oi->filtered = 1;
+ }
+ return oi;
+}
+
+static inline int
+opt_finished(coap_opt_iterator_t *oi) {
+ assert(oi);
+
+ if (oi->bad || oi->length == 0 ||
+ !oi->next_option || *oi->next_option == COAP_PAYLOAD_START) {
+ oi->bad = 1;
+ }
+
+ return oi->bad;
+}
+
+coap_opt_t *
+coap_option_next(coap_opt_iterator_t *oi) {
+ coap_option_t option;
+ coap_opt_t *current_opt = NULL;
+ size_t optsize;
+ int b; /* to store result of coap_option_getb() */
+
+ assert(oi);
+
+ if (opt_finished(oi))
+ return NULL;
+
+ while (1) {
+ /* oi->option always points to the next option to deliver; as
+ * opt_finished() filters out any bad conditions, we can assume that
+ * oi->option is valid. */
+ current_opt = oi->next_option;
+
+ /* Advance internal pointer to next option, skipping any option that
+ * is not included in oi->filter. */
+ optsize = coap_opt_parse(oi->next_option, oi->length, &option);
+ if (optsize) {
+ assert(optsize <= oi->length);
+
+ oi->next_option += optsize;
+ oi->length -= optsize;
+
+ oi->type += option.delta;
+ } else { /* current option is malformed */
+ oi->bad = 1;
+ return NULL;
+ }
+
+ /* Exit the while loop when:
+ * - no filtering is done at all
+ * - the filter matches for the current option
+ * - the filter is too small for the current option number
+ */
+ if (!oi->filtered ||
+ (b = coap_option_getb(oi->filter, oi->type)) > 0)
+ break;
+ else if (b < 0) { /* filter too small, cannot proceed */
+ oi->bad = 1;
+ return NULL;
+ }
+ }
+
+ return current_opt;
+}
+
+coap_opt_t *
+coap_check_option(coap_pdu_t *pdu, unsigned char type,
+ coap_opt_iterator_t *oi) {
+ coap_opt_filter_t f;
+
+ coap_option_filter_clear(f);
+ coap_option_setb(f, type);
+
+ coap_option_iterator_init(pdu, oi, f);
+
+ return coap_option_next(oi);
+}
+
+unsigned short
+coap_opt_delta(const coap_opt_t *opt) {
+ unsigned short n;
+
+ n = (*opt++ & 0xf0) >> 4;
+
+ switch (n) {
+ case 15: /* error */
+ warn("coap_opt_delta: illegal option delta\n");
+
+ /* This case usually should not happen, hence we do not have a
+ * proper way to indicate an error. */
+ return 0;
+ case 14:
+ /* Handle two-byte value: First, the MSB + 269 is stored as delta value.
+ * After that, the option pointer is advanced to the LSB which is handled
+ * just like case delta == 13. */
+ n = ((*opt++ & 0xff) << 8) + 269;
+ /* fall through */
+ case 13:
+ n += *opt & 0xff;
+ break;
+ default: /* n already contains the actual delta value */
+ ;
+ }
+
+ return n;
+}
+
+unsigned short
+coap_opt_length(const coap_opt_t *opt) {
+ unsigned short length;
+
+ length = *opt & 0x0f;
+ switch (*opt & 0xf0) {
+ case 0xf0:
+ debug("illegal option delta\n");
+ return 0;
+ case 0xe0:
+ ++opt;
+ /* fall through to skip another byte */
+ case 0xd0:
+ ++opt;
+ /* fall through to skip another byte */
+ default:
+ ++opt;
+ }
+
+ switch (length) {
+ case 0x0f:
+ debug("illegal option length\n");
+ return 0;
+ case 0x0e:
+ length = (*opt++ << 8) + 269;
+ /* fall through */
+ case 0x0d:
+ length += *opt++;
+ break;
+ default:
+ ;
+ }
+ return length;
+}
+
+unsigned char *
+coap_opt_value(coap_opt_t *opt) {
+ size_t ofs = 1;
+
+ switch (*opt & 0xf0) {
+ case 0xf0:
+ debug("illegal option delta\n");
+ return 0;
+ case 0xe0:
+ ++ofs;
+ /* fall through */
+ case 0xd0:
+ ++ofs;
+ break;
+ default:
+ ;
+ }
+
+ switch (*opt & 0x0f) {
+ case 0x0f:
+ debug("illegal option length\n");
+ return 0;
+ case 0x0e:
+ ++ofs;
+ /* fall through */
+ case 0x0d:
+ ++ofs;
+ break;
+ default:
+ ;
+ }
+
+ return (unsigned char *)opt + ofs;
+}
+
+size_t
+coap_opt_size(const coap_opt_t *opt) {
+ coap_option_t option;
+
+ /* we must assume that opt is encoded correctly */
+ return coap_opt_parse(opt, (size_t)-1, &option);
+}
+
+size_t
+coap_opt_setheader(coap_opt_t *opt, size_t maxlen,
+ unsigned short delta, size_t length) {
+ size_t skip = 0;
+
+ assert(opt);
+
+ if (maxlen == 0) /* need at least one byte */
+ return 0;
+
+ if (delta < 13) {
+ opt[0] = delta << 4;
+ } else if (delta < 270) {
+ if (maxlen < 2) {
+ debug("insufficient space to encode option delta %d", delta);
+ return 0;
+ }
+
+ opt[0] = 0xd0;
+ opt[++skip] = delta - 13;
+ } else {
+ if (maxlen < 3) {
+ debug("insufficient space to encode option delta %d", delta);
+ return 0;
+ }
+
+ opt[0] = 0xe0;
+ opt[++skip] = ((delta - 269) >> 8) & 0xff;
+ opt[++skip] = (delta - 269) & 0xff;
+ }
+
+ if (length < 13) {
+ opt[0] |= length & 0x0f;
+ } else if (length < 270) {
+ if (maxlen < skip + 1) {
+ debug("insufficient space to encode option length %d", length);
+ return 0;
+ }
+
+ opt[0] |= 0x0d;
+ opt[++skip] = length - 13;
+ } else {
+ if (maxlen < skip + 2) {
+ debug("insufficient space to encode option delta %d", delta);
+ return 0;
+ }
+
+ opt[0] |= 0x0e;
+ opt[++skip] = ((length - 269) >> 8) & 0xff;
+ opt[++skip] = (length - 269) & 0xff;
+ }
+
+ return skip + 1;
+}
+
+size_t
+coap_opt_encode(coap_opt_t *opt, size_t maxlen, unsigned short delta,
+ const unsigned char *val, size_t length) {
+ size_t l = 1;
+
+ l = coap_opt_setheader(opt, maxlen, delta, length);
+ assert(l <= maxlen);
+
+ if (!l) {
+ debug("coap_opt_encode: cannot set option header\n");
+ return 0;
+ }
+
+ maxlen -= l;
+ opt += l;
+
+ if (maxlen < length) {
+ debug("coap_opt_encode: option too large for buffer\n");
+ return 0;
+ }
+
+ if (val) /* better be safe here */
+ memcpy(opt, val, length);
+
+ return l + length;
+}
+
--- /dev/null
+/*
+ * option.h -- helpers for handling options in CoAP PDUs
+ *
+ * Copyright (C) 2010-2013 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+/**
+ * @file option.h
+ * @brief helpers for handling options in CoAP PDUs
+ */
+
+#ifndef _OPTION_H_
+#define _OPTION_H_
+
+#include "bits.h"
+#include "pdu.h"
+
+/**
+ * Use byte-oriented access methods here because sliding a complex
+ * struct coap_opt_t over the data buffer may cause bus error on
+ * certain platforms.
+ */
+typedef unsigned char coap_opt_t;
+#define PCHAR(p) ((coap_opt_t *)(p))
+
+/** Representation of CoAP options. */
+typedef struct {
+ unsigned short delta;
+ size_t length;
+ unsigned char *value;
+} coap_option_t;
+
+/**
+ * Parses the option pointed to by @p opt into @p result. This
+ * function returns the number of bytes that have been parsed, or @c 0
+ * on error. An error is signaled when illegal delta or length values
+ * are encountered or when option parsing would result in reading past
+ * the option (i.e. beyond opt + length).
+ *
+ * @param opt The beginning of the option to parse.
+ * @param length The maximum length of @p opt.
+ * @param result A pointer to the coap_option_t structure that is
+ * filled with actual values iff coap_opt_parse() > 0.
+ * @return The number of bytes parsed or @c 0 on error.
+ */
+size_t coap_opt_parse(const coap_opt_t *opt, size_t length,
+ coap_option_t *result);
+
+/**
+ * Returns the size of the given option, taking into account a
+ * possible option jump.
+ *
+ * @param opt An option jump or the beginning of the option.
+ * @return The number of bytes between @p opt and the end of
+ * the option starting at @p opt. In case of an error,
+ * this function returns @c 0 as options need at least
+ * one byte storage space.
+ */
+size_t coap_opt_size(const coap_opt_t *opt);
+
+/** @deprecated { Use coap_opt_size() instead. } */
+#define COAP_OPT_SIZE(opt) coap_opt_size(opt)
+
+/**
+ * Calculates the beginning of the PDU's option section.
+ *
+ * @param pdu The PDU containing the options.
+ * @return A pointer to the first option if available, or @c NULL otherwise.
+ */
+coap_opt_t *options_start(coap_pdu_t *pdu);
+
+/**
+ * Interprets @p opt as pointer to a CoAP option and advances to
+ * the next byte past this option.
+ * @hideinitializer
+ */
+#define options_next(opt) \
+ ((coap_opt_t *)((unsigned char *)(opt) + COAP_OPT_SIZE(opt)))
+
+/**
+ * @defgroup opt_filter Option Filters
+ * @{
+ */
+
+/**
+ * Fixed-size bit-vector we use for option filtering. It is large
+ * enough to hold the highest option number known at build time (20 in
+ * the core spec).
+ */
+typedef unsigned char coap_opt_filter_t[(COAP_MAX_OPT >> 3) + 1];
+
+/** Pre-defined filter that includes all options. */
+#define COAP_OPT_ALL NULL
+
+/**
+ * Clears filter @p f.
+ *
+ * @param f The filter to clear.
+ */
+static inline void
+coap_option_filter_clear(coap_opt_filter_t f) {
+ memset(f, 0, sizeof(coap_opt_filter_t));
+}
+
+/**
+ * Sets the corresponding bit for @p type in @p filter. This function
+ * returns @c 1 if bit was set or @c -1 on error (i.e. when the given
+ * type does not fit in the filter).
+ *
+ * @param filter The filter object to change.
+ * @param type The type for which the bit should be set.
+ *
+ * @return @c 1 if bit was set, @c -1 otherwise.
+ */
+inline static int
+coap_option_setb(coap_opt_filter_t filter, unsigned short type) {
+ return bits_setb((uint8_t *)filter, sizeof(coap_opt_filter_t), type);
+}
+
+/**
+ * Clears the corresponding bit for @p type in @p filter. This function
+ * returns @c 1 if bit was cleared or @c -1 on error (i.e. when the given
+ * type does not fit in the filter).
+ *
+ * @param filter The filter object to change.
+ * @param type The type for which the bit should be cleared.
+ *
+ * @return @c 1 if bit was set, @c -1 otherwise.
+ */
+inline static int
+coap_option_clrb(coap_opt_filter_t filter, unsigned short type) {
+ return bits_clrb((uint8_t *)filter, sizeof(coap_opt_filter_t), type);
+}
+
+/**
+ * Gets the corresponding bit for @p type in @p filter. This function
+ * returns @c 1 if the bit is set @c 0 if not, or @c -1 on error (i.e.
+ * when the given type does not fit in the filter).
+ *
+ * @param filter The filter object to read bit from..
+ * @param type The type for which the bit should be read.
+ *
+ * @return @c 1 if bit was set, @c 0 if not, @c -1 on error.
+ */
+inline static int
+coap_option_getb(const coap_opt_filter_t filter, unsigned short type) {
+ return bits_getb((uint8_t *)filter, sizeof(coap_opt_filter_t), type);
+}
+
+/**
+ * Iterator to run through PDU options. This object must be
+ * initialized with coap_option_iterator_init(). Call
+ * coap_option_next() to walk through the list of options until
+ * coap_option_next() returns @c NULL.
+ *
+ * @code
+ * coap_opt_t *option;
+ * coap_opt_iterator_t opt_iter;
+ * coap_option_iterator_init(pdu, &opt_iter, COAP_OPT_ALL);
+ *
+ * while ((option = coap_option_next(&opt_iter))) {
+ * ... do something with option ...
+ * }
+ * @endcode
+ */
+typedef struct {
+ size_t length; /**< remaining length of PDU */
+ unsigned short type; /**< decoded option type */
+ unsigned int bad:1; /**< iterator object is ok if not set */
+ unsigned int filtered:1; /**< denotes whether or not filter is used */
+ coap_opt_t *next_option; /**< pointer to the unparsed next option */
+ coap_opt_filter_t filter; /**< option filter */
+} coap_opt_iterator_t;
+
+/**
+ * Initializes the given option iterator @p oi to point to the
+ * beginning of the @p pdu's option list. This function returns @p oi
+ * on success, @c NULL otherwise (i.e. when no options exist).
+ * Note that a length check on the option list must be performed before
+ * coap_option_iterator_init() is called.
+ *
+ * @param pdu The PDU the options of which should be walked through.
+ * @param oi An iterator object that will be initilized.
+ * @param filter An optional option type filter.
+ * With @p type != @c COAP_OPT_ALL, coap_option_next()
+ * will return only options matching this bitmask.
+ * Fence-post options @c 14, @c 28, @c 42, ... are always
+ * skipped.
+ *
+ * @return The iterator object @p oi on success, @c NULL otherwise.
+ */
+coap_opt_iterator_t *coap_option_iterator_init(coap_pdu_t *pdu,
+ coap_opt_iterator_t *oi, const coap_opt_filter_t filter);
+
+/**
+ * Updates the iterator @p oi to point to the next option. This
+ * function returns a pointer to that option or @c NULL if no more
+ * options exist. The contents of @p oi will be updated. In
+ * particular, @c oi->n specifies the current option's ordinal number
+ * (counted from @c 1), @c oi->type is the option's type code, and @c
+ * oi->option points to the beginning of the current option
+ * itself. When advanced past the last option, @c oi->option will be
+ * @c NULL.
+ *
+ * Note that options are skipped whose corresponding bits in the
+ * filter specified with coap_option_iterator_init() are @c 0. Options
+ * with type codes that do not fit in this filter hence will always be
+ * returned.
+ *
+ * @param oi The option iterator to update.
+ *
+ * @return The next option or @c NULL if no more options exist.
+ */
+coap_opt_t *coap_option_next(coap_opt_iterator_t *oi);
+
+/**
+ * Retrieves the first option of type @p type from @p pdu. @p oi must
+ * point to a coap_opt_iterator_t object that will be initialized by
+ * this function to filter only options with code @p type. This
+ * function returns the first option with this type, or @c NULL if not
+ * found.
+ *
+ * @param pdu The PDU to parse for options.
+ * @param type The option type code to search for.
+ * @param oi An iterator object to use.
+ *
+ * @return A pointer to the first option of type @p type, or @c NULL
+ * if not found.
+ */
+coap_opt_t *coap_check_option(coap_pdu_t *pdu,
+ unsigned char type,
+ coap_opt_iterator_t *oi);
+
+/**
+ * Encodes the given delta and length values into @p opt. This
+ * function returns the number of bytes that were required to encode
+ * @p delta and @p length or @c 0 on error. Note that the result
+ * indicates by how many bytes @p opt must be advanced to encode the
+ * option value.
+ *
+ * @param opt The option buffer space where @p delta and @p length are
+ * written
+ * @param maxlen The maximum length of @p opt
+ * @param delta The actual delta value to encode.
+ * @param length The actual length value to encode.
+ * @return The number of bytes used or @c 0 on error.
+ */
+size_t coap_opt_setheader(coap_opt_t *opt, size_t maxlen,
+ unsigned short delta, size_t length);
+
+/**
+ * Encodes option with given @p delta into @p opt. This function returns
+ * the number of bytes written to @p opt or @c 0 on error. This happens
+ * especially when @p opt does not provide sufficient space to store
+ * the option value, delta, and option jumps when required.
+ *
+ * @param opt The option buffer space where @p val is written
+ * @param n Maximum length of @p opt.
+ * @param delta The option delta.
+ * @param val The option value to copy into @p opt.
+ * @param len The actual length of @p val.
+ * @return The number of bytes that have been written to @p opt or
+ * @c 0 on error. The return value will always be less than @p n.
+ */
+size_t coap_opt_encode(coap_opt_t *opt, size_t n, unsigned short delta,
+ const unsigned char *val, size_t length);
+
+/**
+ * Decodes the delta value of the next option. This function returns
+ * the number of bytes read or @c 0 on error. The caller of this
+ * function must ensure that it does not read over the boundaries
+ * of @p opt (e.g. by calling coap_opt_check_delta().
+ *
+ * @param opt The option to examine
+ * @return The number of bytes read or @c 0 on error.
+ */
+unsigned short coap_opt_delta(const coap_opt_t *opt);
+
+/** @deprecated { Use coap_opt_delta() instead. } */
+#define COAP_OPT_DELTA(opt) coap_opt_delta(opt)
+
+/** @deprecated { Use coap_opt_encode() instead. } */
+#define COAP_OPT_SETDELTA(opt,val) \
+ coap_opt_encode((opt), COAP_MAX_PDU_SIZE, (val), NULL, 0)
+
+/**
+ * Returns the length of the given option. @p opt must point to an
+ * option jump or the beginning of the option. This function returns
+ * @c 0 when @p opt is not an option or the actual length of @p opt
+ * (which can be @c 0 as well).
+ *
+ * @note {The rationale for using @c 0 in case of an error is that in
+ * most contexts, the result of this function is used to skip the next
+ * coap_opt_length() bytes. }
+ *
+ * @param opt The option whose length should be returned.
+ * @return The option's length or @c 0 when undefined.
+ */
+unsigned short coap_opt_length(const coap_opt_t *opt);
+
+/** @deprecated { Use coap_opt_length() instead. } */
+#define COAP_OPT_LENGTH(opt) coap_opt_length(opt)
+
+/**
+ * Returns a pointer to the value of the given option. @p opt must
+ * point to an option jump or the beginning of the option. This
+ * function returns @c NULL if @p opt is not a valid option.
+ *
+ * @param opt The option whose value should be returned.
+ * @return A pointer to the option value or @c NULL on error.
+ */
+unsigned char *coap_opt_value(coap_opt_t *opt);
+
+/** @deprecated { Use coap_opt_value() instead. } */
+#define COAP_OPT_VALUE(opt) coap_opt_value((coap_opt_t *)opt)
+
+/** @} */
+
+#endif /* _OPTION_H_ */
--- /dev/null
+/* pdu.c -- CoAP message structure
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "config.h"
+
+#if defined(HAVE_ASSERT_H) && !defined(assert)
+# include <assert.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "debug.h"
+#include "pdu.h"
+#include "option.h"
+#include "encode.h"
+
+#ifdef WITH_CONTIKI
+#include "memb.h"
+
+typedef unsigned char _pdu[sizeof(coap_pdu_t) + COAP_MAX_PDU_SIZE];
+
+MEMB(pdu_storage, _pdu, COAP_PDU_MAXCNT);
+
+void
+coap_pdu_resources_init() {
+ memb_init(&pdu_storage);
+}
+#else /* WITH_CONTIKI */
+#include "mem.h"
+#endif /* WITH_CONTIKI */
+
+void
+coap_pdu_clear(coap_pdu_t *pdu, size_t size) {
+ assert(pdu);
+
+ memset(pdu, 0, sizeof(coap_pdu_t) + size);
+ pdu->max_size = size;
+ pdu->hdr = (coap_hdr_t *)((unsigned char *)pdu + sizeof(coap_pdu_t));
+ pdu->hdr->version = COAP_DEFAULT_VERSION;
+
+ /* data is NULL unless explicitly set by coap_add_data() */
+ pdu->length = sizeof(coap_hdr_t);
+}
+
+#ifdef WITH_LWIP
+coap_pdu_t *
+coap_pdu_from_pbuf(struct pbuf *pbuf)
+{
+ LWIP_ASSERT("Can only deal with contiguous PBUFs", pbuf->tot_len == pbuf->len);
+ LWIP_ASSERT("coap_read needs to receive an exclusive copy of the incoming pbuf", pbuf->ref == 1);
+
+ void *data = pbuf->payload;
+ coap_pdu_t *result;
+
+ u8_t header_error = pbuf_header(pbuf, sizeof(coap_pdu_t));
+ LWIP_ASSERT("CoAP PDU header does not fit in existing header space", header_error == 0);
+
+ result = (coap_pdu_t *)pbuf->payload;
+
+ memset(result, 0, sizeof(coap_pdu_t));
+
+ result->max_size = pbuf->tot_len - sizeof(coap_pdu_t);
+ result->length = pbuf->tot_len - sizeof(coap_pdu_t);
+ result->hdr = data;
+ result->pbuf = pbuf;
+
+ return result;
+}
+#endif
+
+coap_pdu_t *
+coap_pdu_init(unsigned char type, unsigned char code,
+ unsigned short id, size_t size) {
+ coap_pdu_t *pdu;
+#ifdef WITH_LWIP
+ struct pbuf *p;
+#endif
+
+ assert(size <= COAP_MAX_PDU_SIZE);
+ /* Size must be large enough to fit the header. */
+ if (size < sizeof(coap_hdr_t) || size > COAP_MAX_PDU_SIZE)
+ return NULL;
+
+ /* size must be large enough for hdr */
+#ifdef WITH_POSIX
+ pdu = (coap_pdu_t*)coap_malloc(sizeof(coap_pdu_t) + size);
+#endif
+#ifdef WITH_CONTIKI
+ pdu = (coap_pdu_t *)memb_alloc(&pdu_storage);
+#endif
+#ifdef WITH_LWIP
+ p = pbuf_alloc(PBUF_TRANSPORT, size, PBUF_RAM);
+ if (p != NULL) {
+ u8_t header_error = pbuf_header(p, sizeof(coap_pdu_t));
+ /* we could catch that case and allocate larger memory in advance, but then
+ * again, we'd run into greater trouble with incoming packages anyway */
+ LWIP_ASSERT("CoAP PDU header does not fit in transport header", header_error == 0);
+ pdu = p->payload;
+ } else {
+ pdu = NULL;
+ }
+#endif
+ if (pdu) {
+ coap_pdu_clear(pdu, size);
+ pdu->hdr->id = id;
+ pdu->hdr->type = type;
+ pdu->hdr->code = code;
+#ifdef WITH_LWIP
+ pdu->pbuf = p;
+#endif
+ }
+ return pdu;
+}
+
+coap_pdu_t *
+coap_new_pdu() {
+ coap_pdu_t *pdu;
+
+#ifndef WITH_CONTIKI
+ pdu = coap_pdu_init(0, 0, ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE);
+#else /* WITH_CONTIKI */
+ pdu = coap_pdu_init(0, 0, uip_ntohs(COAP_INVALID_TID), COAP_MAX_PDU_SIZE);
+#endif /* WITH_CONTIKI */
+
+#ifndef NDEBUG
+ if (!pdu)
+ coap_log(LOG_CRIT, "coap_new_pdu: cannot allocate memory for new PDU\n");
+#endif
+ return pdu;
+}
+
+void
+coap_delete_pdu(coap_pdu_t *pdu) {
+#ifdef WITH_POSIX
+ coap_free( pdu );
+#endif
+#ifdef WITH_LWIP
+ if (pdu != NULL) /* accepting double free as the other implementation accept that too */
+ pbuf_free(pdu->pbuf);
+#endif
+#ifdef WITH_CONTIKI
+ memb_free(&pdu_storage, pdu);
+#endif
+}
+
+int
+coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data) {
+ const size_t HEADERLENGTH = len + 4;
+ /* must allow for pdu == NULL as callers may rely on this */
+ if (!pdu || len > 8 || pdu->max_size < HEADERLENGTH)
+ return 0;
+
+ pdu->hdr->token_length = len;
+ if (len)
+ memcpy(pdu->hdr->token, data, len);
+ pdu->max_delta = 0;
+ pdu->length = HEADERLENGTH;
+ pdu->data = NULL;
+
+ return 1;
+}
+
+/** @FIXME de-duplicate code with coap_add_option_later */
+size_t
+coap_add_option(coap_pdu_t *pdu, unsigned short type, unsigned int len, const unsigned char *data) {
+ size_t optsize;
+ coap_opt_t *opt;
+
+ assert(pdu);
+ pdu->data = NULL;
+
+ if (type < pdu->max_delta) {
+ warn("coap_add_option: options are not in correct order\n");
+ return 0;
+ }
+
+ opt = (unsigned char *)pdu->hdr + pdu->length;
+
+ /* encode option and check length */
+ optsize = coap_opt_encode(opt, pdu->max_size - pdu->length,
+ type - pdu->max_delta, data, len);
+
+ if (!optsize) {
+ warn("coap_add_option: cannot add option\n");
+ /* error */
+ return 0;
+ } else {
+ pdu->max_delta = type;
+ pdu->length += optsize;
+ }
+
+ return optsize;
+}
+
+/** @FIXME de-duplicate code with coap_add_option */
+unsigned char*
+coap_add_option_later(coap_pdu_t *pdu, unsigned short type, unsigned int len) {
+ size_t optsize;
+ coap_opt_t *opt;
+
+ assert(pdu);
+ pdu->data = NULL;
+
+ if (type < pdu->max_delta) {
+ warn("coap_add_option: options are not in correct order\n");
+ return NULL;
+ }
+
+ opt = (unsigned char *)pdu->hdr + pdu->length;
+
+ /* encode option and check length */
+ optsize = coap_opt_encode(opt, pdu->max_size - pdu->length,
+ type - pdu->max_delta, NULL, len);
+
+ if (!optsize) {
+ warn("coap_add_option: cannot add option\n");
+ /* error */
+ return NULL;
+ } else {
+ pdu->max_delta = type;
+ pdu->length += optsize;
+ }
+
+ return ((unsigned char*)opt) + optsize - len;
+}
+
+int
+coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data) {
+ assert(pdu);
+ assert(pdu->data == NULL);
+
+ if (len == 0)
+ return 1;
+
+ if (pdu->length + len + 1 > pdu->max_size) {
+ warn("coap_add_data: cannot add: data too large for PDU\n");
+ assert(pdu->data == NULL);
+ return 0;
+ }
+
+ pdu->data = (unsigned char *)pdu->hdr + pdu->length;
+ *pdu->data = COAP_PAYLOAD_START;
+ pdu->data++;
+
+ memcpy(pdu->data, data, len);
+ pdu->length += len + 1;
+ return 1;
+}
+
+int
+coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data) {
+ assert(pdu);
+ assert(len);
+ assert(data);
+
+ if (pdu->data) {
+ *len = (unsigned char *)pdu->hdr + pdu->length - pdu->data;
+ *data = pdu->data;
+ } else { /* no data, clear everything */
+ *len = 0;
+ *data = NULL;
+ }
+
+ return *data != NULL;
+}
+
+#ifndef SHORT_ERROR_RESPONSE
+typedef struct {
+ unsigned char code;
+ char *phrase;
+} error_desc_t;
+
+/* if you change anything here, make sure, that the longest string does not
+ * exceed COAP_ERROR_PHRASE_LENGTH. */
+error_desc_t coap_error[] = {
+ { COAP_RESPONSE_CODE(65), "2.01 Created" },
+ { COAP_RESPONSE_CODE(66), "2.02 Deleted" },
+ { COAP_RESPONSE_CODE(67), "2.03 Valid" },
+ { COAP_RESPONSE_CODE(68), "2.04 Changed" },
+ { COAP_RESPONSE_CODE(69), "2.05 Content" },
+ { COAP_RESPONSE_CODE(400), "Bad Request" },
+ { COAP_RESPONSE_CODE(401), "Unauthorized" },
+ { COAP_RESPONSE_CODE(402), "Bad Option" },
+ { COAP_RESPONSE_CODE(403), "Forbidden" },
+ { COAP_RESPONSE_CODE(404), "Not Found" },
+ { COAP_RESPONSE_CODE(405), "Method Not Allowed" },
+ { COAP_RESPONSE_CODE(408), "Request Entity Incomplete" },
+ { COAP_RESPONSE_CODE(413), "Request Entity Too Large" },
+ { COAP_RESPONSE_CODE(415), "Unsupported Media Type" },
+ { COAP_RESPONSE_CODE(500), "Internal Server Error" },
+ { COAP_RESPONSE_CODE(501), "Not Implemented" },
+ { COAP_RESPONSE_CODE(502), "Bad Gateway" },
+ { COAP_RESPONSE_CODE(503), "Service Unavailable" },
+ { COAP_RESPONSE_CODE(504), "Gateway Timeout" },
+ { COAP_RESPONSE_CODE(505), "Proxying Not Supported" },
+ { 0, NULL } /* end marker */
+};
+
+char *
+coap_response_phrase(unsigned char code) {
+ int i;
+ for (i = 0; coap_error[i].code; ++i) {
+ if (coap_error[i].code == code)
+ return coap_error[i].phrase;
+ }
+ return NULL;
+}
+#endif
+
+/**
+ * Advances *optp to next option if still in PDU. This function
+ * returns the number of bytes opt has been advanced or @c 0
+ * on error.
+ */
+static size_t
+next_option_safe(coap_opt_t **optp, size_t *length) {
+ coap_option_t option;
+ size_t optsize;
+
+ assert(optp); assert(*optp);
+ assert(length);
+
+ optsize = coap_opt_parse(*optp, *length, &option);
+ if (optsize) {
+ assert(optsize <= *length);
+
+ *optp += optsize;
+ *length -= optsize;
+ }
+
+ return optsize;
+}
+
+int
+coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *pdu) {
+ coap_opt_t *opt;
+
+ assert(data);
+ assert(pdu);
+
+ if (pdu->max_size < length) {
+ debug("insufficient space to store parsed PDU\n");
+ return 0;
+ }
+
+ if (length < sizeof(coap_hdr_t)) {
+ debug("discarded invalid PDU\n");
+ }
+
+ pdu->hdr->version = data[0] >> 6;
+ pdu->hdr->type = (data[0] >> 4) & 0x03;
+ pdu->hdr->token_length = data[0] & 0x0f;
+ pdu->hdr->code = data[1];
+ pdu->data = NULL;
+
+ /* sanity checks */
+ if (pdu->hdr->code == 0) {
+ if (length != sizeof(coap_hdr_t) || pdu->hdr->token_length) {
+ debug("coap_pdu_parse: empty message is not empty\n");
+ goto discard;
+ }
+ }
+
+ if (length < sizeof(coap_hdr_t) + pdu->hdr->token_length
+ || pdu->hdr->token_length > 8) {
+ debug("coap_pdu_parse: invalid Token\n");
+ goto discard;
+ }
+
+ /* Copy message id in network byte order, so we can easily write the
+ * response back to the network. */
+ memcpy(&pdu->hdr->id, data + 2, 2);
+
+ /* append data (including the Token) to pdu structure */
+ memcpy(pdu->hdr + 1, data + sizeof(coap_hdr_t), length - sizeof(coap_hdr_t));
+ pdu->length = length;
+
+ /* Finally calculate beginning of data block and thereby check integrity
+ * of the PDU structure. */
+
+ /* skip header + token */
+ length -= (pdu->hdr->token_length + sizeof(coap_hdr_t));
+ opt = (unsigned char *)(pdu->hdr + 1) + pdu->hdr->token_length;
+
+ while (length && *opt != COAP_PAYLOAD_START) {
+
+ if (!next_option_safe(&opt, (size_t *)&length)) {
+ debug("coap_pdu_parse: drop\n");
+ goto discard;
+ }
+ }
+
+ /* end of packet or start marker */
+ if (length) {
+ assert(*opt == COAP_PAYLOAD_START);
+ opt++; length--;
+
+ if (!length) {
+ debug("coap_pdu_parse: message ending in payload start marker\n");
+ goto discard;
+ }
+
+ debug("set data to %p (pdu ends at %p)\n", (unsigned char *)opt,
+ (unsigned char *)pdu->hdr + pdu->length);
+ pdu->data = (unsigned char *)opt;
+ }
+
+ return 1;
+
+ discard:
+ return 0;
+}
--- /dev/null
+/* pdu.h -- CoAP message structure
+ *
+ * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef _PDU_H_
+#define _PDU_H_
+
+#include "config.h"
+#include "coap_list.h"
+#include "uri.h"
+
+#ifdef WITH_LWIP
+#include <lwip/pbuf.h>
+#endif
+
+/* pre-defined constants that reflect defaults for CoAP */
+
+#define COAP_DEFAULT_RESPONSE_TIMEOUT 2 /* response timeout in seconds */
+#define COAP_DEFAULT_MAX_RETRANSMIT 4 /* max number of retransmissions */
+#define COAP_DEFAULT_PORT 5683 /* CoAP default UDP port */
+#define COAP_DEFAULT_MAX_AGE 60 /* default maximum object lifetime in seconds */
+#ifndef COAP_MAX_PDU_SIZE
+#define COAP_MAX_PDU_SIZE 1400 /* maximum size of a CoAP PDU */
+#endif /* COAP_MAX_PDU_SIZE */
+
+#define COAP_DEFAULT_VERSION 1 /* version of CoAP supported */
+#define COAP_DEFAULT_SCHEME "coap" /* the default scheme for CoAP URIs */
+
+/** well-known resources URI */
+#define COAP_DEFAULT_URI_WELLKNOWN ".well-known/core"
+
+#ifdef __COAP_DEFAULT_HASH
+/* pre-calculated hash key for the default well-known URI */
+#define COAP_DEFAULT_WKC_HASHKEY "\345\130\144\245"
+#endif
+
+/* CoAP message types */
+
+#define COAP_MESSAGE_CON 0 /* confirmable message (requires ACK/RST) */
+#define COAP_MESSAGE_NON 1 /* non-confirmable message (one-shot message) */
+#define COAP_MESSAGE_ACK 2 /* used to acknowledge confirmable messages */
+#define COAP_MESSAGE_RST 3 /* indicates error in received messages */
+
+/* CoAP request methods */
+
+#define COAP_REQUEST_GET 1
+#define COAP_REQUEST_POST 2
+#define COAP_REQUEST_PUT 3
+#define COAP_REQUEST_DELETE 4
+
+/* CoAP option types (be sure to update check_critical when adding options */
+
+#define COAP_OPTION_IF_MATCH 1 /* C, opaque, 0-8 B, (none) */
+#define COAP_OPTION_URI_HOST 3 /* C, String, 1-255 B, destination address */
+#define COAP_OPTION_ETAG 4 /* E, opaque, 1-8 B, (none) */
+#define COAP_OPTION_IF_NONE_MATCH 5 /* empty, 0 B, (none) */
+#define COAP_OPTION_URI_PORT 7 /* C, uint, 0-2 B, destination port */
+#define COAP_OPTION_LOCATION_PATH 8 /* E, String, 0-255 B, - */
+#define COAP_OPTION_URI_PATH 11 /* C, String, 0-255 B, (none) */
+#define COAP_OPTION_CONTENT_FORMAT 12 /* E, uint, 0-2 B, (none) */
+#define COAP_OPTION_CONTENT_TYPE COAP_OPTION_CONTENT_FORMAT
+#define COAP_OPTION_MAXAGE 14 /* E, uint, 0--4 B, 60 Seconds */
+#define COAP_OPTION_URI_QUERY 15 /* C, String, 1-255 B, (none) */
+#define COAP_OPTION_ACCEPT 17 /* C, uint, 0-2 B, (none) */
+#define COAP_OPTION_LOCATION_QUERY 20 /* E, String, 0-255 B, (none) */
+#define COAP_OPTION_PROXY_URI 35 /* C, String, 1-1034 B, (none) */
+#define COAP_OPTION_PROXY_SCHEME 39 /* C, String, 1-255 B, (none) */
+#define COAP_OPTION_SIZE1 60 /* E, uint, 0-4 B, (none) */
+
+/* option types from draft-ietf-coap-observe-09 */
+
+#define COAP_OPTION_OBSERVE 6 /* E, empty/uint, 0 B/0-3 B, (none) */
+#define COAP_OPTION_SUBSCRIPTION COAP_OPTION_OBSERVE
+
+/* selected option types from draft-core-block-04 */
+
+#define COAP_OPTION_BLOCK2 23 /* C, uint, 0--3 B, (none) */
+#define COAP_OPTION_BLOCK1 27 /* C, uint, 0--3 B, (none) */
+
+#define COAP_MAX_OPT 63 /**< the highest option number we know */
+
+/* CoAP result codes (HTTP-Code / 100 * 40 + HTTP-Code % 100) */
+
+/* As of draft-ietf-core-coap-04, response codes are encoded to base
+ * 32, i.e. the three upper bits determine the response class while
+ * the remaining five fine-grained information specific to that class.
+ */
+#define COAP_RESPONSE_CODE(N) (((N)/100 << 5) | (N)%100)
+
+/* Determines the class of response code C */
+#define COAP_RESPONSE_CLASS(C) (((C) >> 5) & 0xFF)
+
+#ifndef SHORT_ERROR_RESPONSE
+/**
+ * Returns a human-readable response phrase for the specified CoAP
+ * response @p code. This function returns @c NULL if not found.
+ *
+ * @param code The response code for which the literal phrase should
+ * be retrieved.
+ *
+ * @return A zero-terminated string describing the error, or @c NULL
+ * if not found.
+ */
+char *coap_response_phrase(unsigned char code);
+
+#define COAP_ERROR_PHRASE_LENGTH 32 /**< maximum length of error phrase */
+
+#else
+#define coap_response_phrase(x) ((char *)NULL)
+
+#define COAP_ERROR_PHRASE_LENGTH 0 /**< maximum length of error phrase */
+#endif /* SHORT_ERROR_RESPONSE */
+
+/* The following definitions exist for backwards compatibility */
+#if 0 /* this does not exist any more */
+#define COAP_RESPONSE_100 40 /* 100 Continue */
+#endif
+#define COAP_RESPONSE_200 COAP_RESPONSE_CODE(200) /* 2.00 OK */
+#define COAP_RESPONSE_201 COAP_RESPONSE_CODE(201) /* 2.01 Created */
+#define COAP_RESPONSE_304 COAP_RESPONSE_CODE(203) /* 2.03 Valid */
+#define COAP_RESPONSE_400 COAP_RESPONSE_CODE(400) /* 4.00 Bad Request */
+#define COAP_RESPONSE_404 COAP_RESPONSE_CODE(404) /* 4.04 Not Found */
+#define COAP_RESPONSE_405 COAP_RESPONSE_CODE(405) /* 4.05 Method Not Allowed */
+#define COAP_RESPONSE_415 COAP_RESPONSE_CODE(415) /* 4.15 Unsupported Media Type */
+#define COAP_RESPONSE_500 COAP_RESPONSE_CODE(500) /* 5.00 Internal Server Error */
+#define COAP_RESPONSE_501 COAP_RESPONSE_CODE(501) /* 5.01 Not Implemented */
+#define COAP_RESPONSE_503 COAP_RESPONSE_CODE(503) /* 5.03 Service Unavailable */
+#define COAP_RESPONSE_504 COAP_RESPONSE_CODE(504) /* 5.04 Gateway Timeout */
+#if 0 /* these response codes do not have a valid code any more */
+# define COAP_RESPONSE_X_240 240 /* Token Option required by server */
+# define COAP_RESPONSE_X_241 241 /* Uri-Authority Option required by server */
+#endif
+#define COAP_RESPONSE_X_242 COAP_RESPONSE_CODE(402) /* Critical Option not supported */
+
+/* CoAP media type encoding */
+
+#define COAP_MEDIATYPE_TEXT_PLAIN 0 /* text/plain (UTF-8) */
+#define COAP_MEDIATYPE_APPLICATION_LINK_FORMAT 40 /* application/link-format */
+#define COAP_MEDIATYPE_APPLICATION_XML 41 /* application/xml */
+#define COAP_MEDIATYPE_APPLICATION_OCTET_STREAM 42 /* application/octet-stream */
+#define COAP_MEDIATYPE_APPLICATION_RDF_XML 43 /* application/rdf+xml */
+#define COAP_MEDIATYPE_APPLICATION_EXI 47 /* application/exi */
+#define COAP_MEDIATYPE_APPLICATION_JSON 50 /* application/json */
+
+/* Note that identifiers for registered media types are in the range 0-65535. We
+ * use an unallocated type here and hope for the best. */
+#define COAP_MEDIATYPE_ANY 0xff /* any media type */
+
+/* CoAP transaction id */
+/*typedef unsigned short coap_tid_t; */
+typedef int coap_tid_t;
+#define COAP_INVALID_TID -1
+
+#pragma GCC diagnostic ignored "-pedantic"
+#ifdef WORDS_BIGENDIAN
+typedef struct {
+ unsigned int version:2; /* protocol version */
+ unsigned int type:2; /* type flag */
+ unsigned int token_length:4; /* length of Token */
+ unsigned int code:8; /* request method (value 1--10) or response code (value 40-255) */
+ unsigned short id; /* message id */
+ unsigned char token[0]; /* the actual token, if any */
+} coap_hdr_t;
+#else
+typedef struct {
+ unsigned int token_length:4; /* length of Token */
+ unsigned int type:2; /* type flag */
+ unsigned int version:2; /* protocol version */
+ unsigned int code:8; /* request method (value 1--10) or response code (value 40-255) */
+ unsigned short id; /* transaction id (network byte order!) */
+ unsigned char token[0]; /* the actual token, if any */
+} coap_hdr_t;
+#endif
+#pragma GCC diagnostic warning "-pedantic"
+
+#define COAP_MESSAGE_IS_EMPTY(MSG) ((MSG)->code == 0)
+#define COAP_MESSAGE_IS_REQUEST(MSG) (!COAP_MESSAGE_IS_EMPTY(MSG) \
+ && ((MSG)->code < 32))
+#define COAP_MESSAGE_IS_RESPONSE(MSG) ((MSG)->code >= 64 && (MSG)->code <= 191)
+
+#define COAP_OPT_LONG 0x0F /* OC == 0b1111 indicates that the option list in a
+ * CoAP message is limited by 0b11110000 marker */
+
+#define COAP_OPT_END 0xF0 /* end marker */
+
+#define COAP_PAYLOAD_START 0xFF /* payload marker */
+
+/**
+ * Structures for more convenient handling of options. (To be used with ordered
+ * coap_list_t.) The option's data will be added to the end of the coap_option
+ * structure (see macro COAP_OPTION_DATA).
+ */
+typedef struct {
+ unsigned short key; /* the option key (no delta coding) */
+ unsigned int length;
+} coap_option;
+
+#define COAP_OPTION_KEY(option) (option).key
+#define COAP_OPTION_LENGTH(option) (option).length
+#define COAP_OPTION_DATA(option) ((unsigned char *)&(option) + sizeof(coap_option))
+
+/** Header structure for CoAP PDUs */
+
+typedef struct {
+ size_t max_size; /**< allocated storage for options and data */
+
+ coap_hdr_t *hdr;
+ unsigned short max_delta; /**< highest option number */
+ unsigned short length; /**< PDU length (including header, options, data) */
+ unsigned char *data; /**< payload */
+
+#ifdef WITH_LWIP
+ struct pbuf *pbuf; /**< lwIP PBUF. The allocated coap_pdu_t will always reside inside the pbuf's payload, but the pointer has to be kept because no exact offset can be given. This field must not be accessed from outside, because the pbuf's reference count is checked to be 1 when the pbuf is assigned to the pdu, and the pbuf stays exclusive to this pdu. */
+#endif
+
+} coap_pdu_t;
+
+/** Options in coap_pdu_t are accessed with the macro COAP_OPTION. */
+#define COAP_OPTION(node) ((coap_option *)(node)->options)
+
+#ifdef WITH_LWIP
+/**
+ * Creates a CoAP PDU from an lwIP @p pbuf, whose reference is passed on to
+ * this function.
+ *
+ * The pbuf is checked for being contiguous, for having enough head space for
+ * the PDU struct (which is located directly in front of the data, overwriting
+ * the old other headers), and for having only one reference. The reference is
+ * stored in the PDU and will be freed when the PDU is freed.
+ *
+ * (For now, these are errors; in future, a new pbuf might be allocated, the
+ * data copied and the passed pbuf freed).
+ *
+ * This behaves like coap_pdu_init(0, 0, 0, pbuf->tot_len), and afterwards
+ * copying the contents of the pbuf to the pdu.
+ *
+ * @return A pointer to the new PDU object or @c NULL on error.
+ */
+coap_pdu_t * coap_pdu_from_pbuf(struct pbuf *pbuf);
+#endif
+
+/**
+ * Creates a new CoAP PDU of given @p size (must be large enough to hold the
+ * basic CoAP message header (coap_hdr_t). The function returns a pointer to
+ * the node coap_pdu_t object on success, or @c NULL on error. The storage
+ * allocated for the result must be released with coap_delete_pdu().
+ *
+ * @param type The type of the PDU (one of COAP_MESSAGE_CON,
+ * COAP_MESSAGE_NON, COAP_MESSAGE_ACK, COAP_MESSAGE_RST).
+ * @param code The message code.
+ * @param id The message id to set or COAP_INVALID_TID if unknown.
+ * @param size The number of bytes to allocate for the actual message.
+ *
+ * @return A pointer to the new PDU object or @c NULL on error.
+ */
+coap_pdu_t *
+coap_pdu_init(unsigned char type, unsigned char code,
+ unsigned short id, size_t size);
+
+/**
+ * Clears any contents from @p pdu and resets @c version field, @c
+ * length and @c data pointers. @c max_size is set to @p size, any
+ * other field is set to @c 0. Note that @p pdu must be a valid
+ * pointer to a coap_pdu_t object created e.g. by coap_pdu_init().
+ */
+void coap_pdu_clear(coap_pdu_t *pdu, size_t size);
+
+/**
+ * Creates a new CoAP PDU. The object is created on the heap and must be released
+ * using coap_delete_pdu();
+ *
+ * @deprecated This function allocates the maximum storage for each
+ * PDU. Use coap_pdu_init() instead.
+ */
+coap_pdu_t *coap_new_pdu();
+
+void coap_delete_pdu(coap_pdu_t *);
+
+/**
+ * Parses @p data into the CoAP PDU structure given in @p result. This
+ * function returns @c 0 on error or a number greater than zero on
+ * success.
+ *
+ * @param data The raw data to parse as CoAP PDU
+ * @param length The actual size of @p data
+ * @param result The PDU structure to fill. Note that the structure must
+ * provide space for at least @p length bytes to hold the
+ * entire CoAP PDU.
+ * @return A value greater than zero on success or @c 0 on error.
+ */
+int coap_pdu_parse(unsigned char *data, size_t length, coap_pdu_t *result);
+
+/**
+ * Adds token of length @p len to @p pdu. Adding the token destroys
+ * any following contents of the pdu. Hence options and data must be
+ * added after coap_add_token() has been called. In @p pdu, length is
+ * set to @p len + @c 4, and max_delta is set to @c 0. This funtion
+ * returns @c 0 on error or a value greater than zero on success.
+ *
+ * @param pdu The PDU where the token is to be added.
+ * @param len The length of the new token.
+ * @param data The token to add.
+ * @return A value greater than zero on success, or @c 0 on error.
+ */
+int coap_add_token(coap_pdu_t *pdu, size_t len, const unsigned char *data);
+
+/**
+ * Adds option of given type to pdu that is passed as first
+ * parameter. coap_add_option() destroys the PDU's data, so
+ * coap_add_data() must be called after all options have been added.
+ * As coap_add_token() destroys the options following the token,
+ * the token must be added before coap_add_option() is called.
+ * This function returns the number of bytes written or @c 0 on error.
+ */
+size_t coap_add_option(coap_pdu_t *pdu, unsigned short type,
+ unsigned int len, const unsigned char *data);
+
+/**
+ * Adds option of given type to pdu that is passed as first
+ * parameter, but does not write a value. It works like coap_add_option with
+ * respect to calling sequence (i.e. after token and before data).
+ * This function returns a memory address to which the option data has to be
+ * written before the PDU can be sent, or @c NULL on error.
+ */
+unsigned char *coap_add_option_later(coap_pdu_t *pdu, unsigned short type,
+ unsigned int len);
+
+/**
+ * Adds given data to the pdu that is passed as first parameter. Note
+ * that the PDU's data is destroyed by coap_add_option(). coap_add_data()
+ * must be called only once per PDU, otherwise the result is undefined.
+ */
+int coap_add_data(coap_pdu_t *pdu, unsigned int len, const unsigned char *data);
+
+/**
+ * Retrieves the length and data pointer of specified PDU. Returns 0 on error
+ * or 1 if *len and *data have correct values. Note that these values are
+ * destroyed with the pdu.
+ */
+int coap_get_data(coap_pdu_t *pdu, size_t *len, unsigned char **data);
+
+#endif /* _PDU_H_ */
--- /dev/null
+/* prng.h -- Pseudo Random Numbers
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+/**
+ * @file prng.h
+ * @brief Pseudo Random Numbers
+ */
+
+#ifndef _COAP_PRNG_H_
+#define _COAP_PRNG_H_
+
+#include "config.h"
+#include <ocrandom.h>
+
+/**
+ * @defgroup prng Pseudo Random Numbers
+ * @{
+ */
+
+#ifndef WITH_CONTIKI
+#include <stdlib.h>
+
+/**
+ * Fills \p buf with \p len random bytes. This is the default
+ * implementation for prng(). You might want to change prng() to use
+ * a better PRNG on your specific platform.
+ */
+static inline int
+coap_prng_impl(unsigned char *buf, size_t len) {
+#if 0
+ while (len--)
+ *buf++ = rand() & 0xFF;
+#endif
+ OCFillRandomMem(buf, len);
+ return 1;
+}
+#else /* WITH_CONTIKI */
+#include <string.h>
+
+/**
+ * Fills \p buf with \p len random bytes. This is the default
+ * implementation for prng(). You might want to change prng() to use
+ * a better PRNG on your specific platform.
+ */
+static inline int
+contiki_prng_impl(unsigned char *buf, size_t len) {
+ unsigned short v = random_rand();
+ while (len > sizeof(v)) {
+ memcpy(buf, &v, sizeof(v));
+ len -= sizeof(v);
+ buf += sizeof(v);
+ v = random_rand();
+ }
+
+ memcpy(buf, &v, len);
+ return 1;
+}
+
+#define prng(Buf,Length) contiki_prng_impl((Buf), (Length))
+#define prng_init(Value) random_init((unsigned short)(Value))
+#endif /* WITH_CONTIKI */
+
+#ifndef prng
+/**
+ * Fills \p Buf with \p Length bytes of random data.
+ *
+ * @hideinitializer
+ */
+#define prng(Buf,Length) coap_prng_impl((Buf), (Length))
+#endif
+
+#ifndef prng_init
+/**
+ * Called to set the PRNG seed. You may want to re-define this to
+ * allow for a better PRNG.
+ *
+ * @hideinitializer
+ */
+#define prng_init(Value) OCSeedRandom()//srand((unsigned long)(Value))
+#endif
+
+/** @} */
+
+#endif /* _COAP_PRNG_H_ */
--- /dev/null
+/* resource.c -- generic resource handling
+ *
+ * Copyright (C) 2010--2014 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "config.h"
+#include "net.h"
+#include "debug.h"
+#include "resource.h"
+#include "subscribe.h"
+
+#ifdef WITH_LWIP
+#include "utlist.h"
+/* mem.h is only needed for the string free calls for
+ * COAP_ATTR_FLAGS_RELEASE_NAME / COAP_ATTR_FLAGS_RELEASE_VALUE /
+ * COAP_RESOURCE_FLAGS_RELEASE_URI. not sure what those lines should actually
+ * do on lwip. */
+#include "mem.h"
+
+#include <lwip/memp.h>
+
+#define COAP_MALLOC_TYPE(Type) \
+ ((coap_##Type##_t *)memp_malloc(MEMP_COAP_##Type))
+#define COAP_FREE_TYPE(Type, Object) memp_free(MEMP_COAP_##Type, Object)
+
+#endif
+#ifdef WITH_POSIX
+#include "utlist.h"
+#include "mem.h"
+
+#define COAP_MALLOC_TYPE(Type) \
+ ((coap_##Type##_t *)coap_malloc(sizeof(coap_##Type##_t)))
+#define COAP_FREE_TYPE(Type, Object) coap_free(Object)
+
+#endif /* WITH_POSIX */
+#ifdef WITH_CONTIKI
+#include "memb.h"
+
+MEMB(resource_storage, coap_resource_t, COAP_MAX_RESOURCES);
+MEMB(attribute_storage, coap_attr_t, COAP_MAX_ATTRIBUTES);
+MEMB(subscription_storage, coap_subscription_t, COAP_MAX_SUBSCRIBERS);
+
+void
+coap_resources_init() {
+ memb_init(&resource_storage);
+ memb_init(&attribute_storage);
+ memb_init(&subscription_storage);
+}
+
+static inline coap_subscription_t *
+coap_malloc_subscription() {
+ return memb_alloc(&subscription_storage);
+}
+
+static inline void
+coap_free_subscription(coap_subscription_t *subscription) {
+ memb_free(&subscription_storage, subscription);
+}
+#endif /* WITH_CONTIKI */
+
+#define min(a,b) ((a) < (b) ? (a) : (b))
+
+/* Helper functions for conditional output of character sequences into
+ * a given buffer. The first Offset characters are skipped.
+ */
+
+/**
+ * Adds Char to Buf if Offset is zero. Otherwise, Char is not written
+ * and Offset is decremented.
+ */
+#define PRINT_WITH_OFFSET(Buf,Offset,Char) \
+ if ((Offset) == 0) { \
+ (*(Buf)++) = (Char); \
+ } else { \
+ (Offset)--; \
+ } \
+
+/**
+ * Adds Char to Buf if Offset is zero and Buf is less than Bufend.
+ */
+#define PRINT_COND_WITH_OFFSET(Buf,Bufend,Offset,Char,Result) { \
+ if ((Buf) < (Bufend)) { \
+ PRINT_WITH_OFFSET(Buf,Offset,Char); \
+ } \
+ (Result)++; \
+ }
+
+/**
+ * Copies at most Length characters of Str to Buf. The first Offset
+ * characters are skipped. Output may be truncated to Bufend - Buf
+ * characters.
+ */
+#define COPY_COND_WITH_OFFSET(Buf,Bufend,Offset,Str,Length,Result) { \
+ size_t i; \
+ for (i = 0; i < (Length); i++) { \
+ PRINT_COND_WITH_OFFSET((Buf), (Bufend), (Offset), (Str)[i], (Result)); \
+ } \
+ }
+
+int
+match(const str *text, const str *pattern, int match_prefix, int match_substring) {
+ assert(text); assert(pattern);
+
+ if (text->length < pattern->length)
+ return 0;
+
+ if (match_substring) {
+ unsigned char *next_token = text->s;
+ size_t remaining_length = text->length;
+ while (remaining_length) {
+ size_t token_length;
+ unsigned char *token = next_token;
+ next_token = (unsigned char *)memchr(token, ' ', remaining_length);
+
+ if (next_token) {
+ token_length = next_token - token;
+ remaining_length -= (token_length + 1);
+ next_token++;
+ } else {
+ token_length = remaining_length;
+ remaining_length = 0;
+ }
+
+ if ((match_prefix || pattern->length == token_length) &&
+ memcmp(token, pattern->s, pattern->length) == 0)
+ return 1;
+ }
+ return 0;
+ }
+
+ return (match_prefix || pattern->length == text->length) &&
+ memcmp(text->s, pattern->s, pattern->length) == 0;
+}
+
+/**
+ * Prints the names of all known resources to @p buf. This function
+ * sets @p buflen to the number of bytes actually written and returns
+ * @c 1 on succes. On error, the value in @p buflen is undefined and
+ * the return value will be @c 0.
+ *
+ * @param context The context with the resource map.
+ * @param buf The buffer to write the result.
+ * @param buflen Must be initialized to the maximum length of @p buf and will be
+ * set to the length of the well-known response on return.
+ * @param offset The offset in bytes where the output shall start and is
+ * shifted accordingly with the characters that have been
+ * processed. This parameter is used to support the block
+ * option.
+ * @param query_filter A filter query according to <a href="http://tools.ietf.org/html/draft-ietf-core-link-format-11#section-4.1">Link Format</a>
+ *
+ * @return COAP_PRINT_STATUS_ERROR on error. Otherwise, the lower 28 bits are
+ * set to the number of bytes that have actually been written to
+ * @p buf. COAP_PRINT_STATUS_TRUNC is set when the output has been
+ * truncated.
+ */
+#if defined(__GNUC__) && defined(WITHOUT_QUERY_FILTER)
+coap_print_status_t
+print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen,
+ size_t offset,
+ coap_opt_t *query_filter __attribute__ ((unused))) {
+#else /* not a GCC */
+coap_print_status_t
+print_wellknown(coap_context_t *context, unsigned char *buf, size_t *buflen,
+ size_t offset, coap_opt_t *query_filter) {
+#endif /* GCC */
+ coap_resource_t *r;
+ unsigned char *p = buf;
+ const unsigned char *bufend = buf + *buflen;
+ size_t left, written = 0;
+ coap_print_status_t result;
+ const size_t old_offset = offset;
+ int subsequent_resource = 0;
+#ifndef COAP_RESOURCES_NOHASH
+ coap_resource_t *tmp;
+#endif
+#ifndef WITHOUT_QUERY_FILTER
+ str resource_param = { 0, NULL }, query_pattern = { 0, NULL };
+ int flags = 0; /* MATCH_SUBSTRING, MATCH_PREFIX, MATCH_URI */
+#define MATCH_URI 0x01
+#define MATCH_PREFIX 0x02
+#define MATCH_SUBSTRING 0x04
+ static const str _rt_attributes[] = {
+ {2, (unsigned char *)"rt"},
+ {2, (unsigned char *)"if"},
+ {3, (unsigned char *)"rel"},
+ {0, NULL}};
+#endif /* WITHOUT_QUERY_FILTER */
+
+#ifdef WITH_CONTIKI
+ int i;
+#endif /* WITH_CONTIKI */
+
+#ifndef WITHOUT_QUERY_FILTER
+ /* split query filter, if any */
+ if (query_filter) {
+ resource_param.s = COAP_OPT_VALUE(query_filter);
+ while (resource_param.length < COAP_OPT_LENGTH(query_filter)
+ && resource_param.s[resource_param.length] != '=')
+ resource_param.length++;
+
+ if (resource_param.length < COAP_OPT_LENGTH(query_filter)) {
+ const str *rt_attributes;
+ if (resource_param.length == 4 &&
+ memcmp(resource_param.s, "href", 4) == 0)
+ flags |= MATCH_URI;
+
+ for (rt_attributes = _rt_attributes; rt_attributes->s; rt_attributes++) {
+ if (resource_param.length == rt_attributes->length &&
+ memcmp(resource_param.s, rt_attributes->s, rt_attributes->length) == 0) {
+ flags |= MATCH_SUBSTRING;
+ break;
+ }
+ }
+
+ /* rest is query-pattern */
+ query_pattern.s =
+ COAP_OPT_VALUE(query_filter) + resource_param.length + 1;
+
+ assert((resource_param.length + 1) <= COAP_OPT_LENGTH(query_filter));
+ query_pattern.length =
+ COAP_OPT_LENGTH(query_filter) - (resource_param.length + 1);
+
+ if ((query_pattern.s[0] == '/') && ((flags & MATCH_URI) == MATCH_URI)) {
+ query_pattern.s++;
+ query_pattern.length--;
+ }
+
+ if (query_pattern.length &&
+ query_pattern.s[query_pattern.length-1] == '*') {
+ query_pattern.length--;
+ flags |= MATCH_PREFIX;
+ }
+ }
+ }
+#endif /* WITHOUT_QUERY_FILTER */
+
+#ifndef WITH_CONTIKI
+
+#ifdef COAP_RESOURCES_NOHASH
+ LL_FOREACH(context->resources, r) {
+#else
+ HASH_ITER(hh, context->resources, r, tmp) {
+#endif
+#else /* WITH_CONTIKI */
+ r = (coap_resource_t *)resource_storage.mem;
+ for (i = 0; i < resource_storage.num; ++i, ++r) {
+ if (!resource_storage.count[i])
+ continue;
+#endif /* WITH_CONTIKI */
+
+#ifndef WITHOUT_QUERY_FILTER
+ if (resource_param.length) { /* there is a query filter */
+
+ if (flags & MATCH_URI) { /* match resource URI */
+ if (!match(&r->uri, &query_pattern, (flags & MATCH_PREFIX) != 0, (flags & MATCH_SUBSTRING) != 0))
+ continue;
+ } else { /* match attribute */
+ coap_attr_t *attr;
+ str unquoted_val;
+ attr = coap_find_attr(r, resource_param.s, resource_param.length);
+ if (!attr) continue;
+ if (attr->value.s[0] == '"') { /* if attribute has a quoted value, remove double quotes */
+ unquoted_val.length = attr->value.length - 2;
+ unquoted_val.s = attr->value.s + 1;
+ } else {
+ unquoted_val = attr->value;
+ }
+ if (!(match(&unquoted_val, &query_pattern,
+ (flags & MATCH_PREFIX) != 0,
+ (flags & MATCH_SUBSTRING) != 0)))
+ continue;
+ }
+ }
+#endif /* WITHOUT_QUERY_FILTER */
+
+ if (!subsequent_resource) { /* this is the first resource */
+ subsequent_resource = 1;
+ } else {
+ PRINT_COND_WITH_OFFSET(p, bufend, offset, ',', written);
+ }
+
+ left = bufend - p; /* calculate available space */
+ result = coap_print_link(r, p, &left, &offset);
+
+ if (result & COAP_PRINT_STATUS_ERROR) {
+ break;
+ }
+
+ /* coap_print_link() returns the number of characters that
+ * where actually written to p. Now advance to its end. */
+ p += COAP_PRINT_OUTPUT_LENGTH(result);
+ written += left;
+ }
+
+ *buflen = written;
+ result = p - buf;
+ if (result + old_offset - offset < *buflen) {
+ result |= COAP_PRINT_STATUS_TRUNC;
+ }
+ return result;
+}
+
+coap_resource_t *
+coap_resource_init(const unsigned char *uri, size_t len, int flags) {
+ coap_resource_t *r;
+
+#ifdef WITH_POSIX
+ r = (coap_resource_t *)coap_malloc(sizeof(coap_resource_t));
+#endif
+#ifdef WITH_LWIP
+ r = (coap_resource_t *)memp_malloc(MEMP_COAP_RESOURCE);
+#endif
+#ifdef WITH_CONTIKI
+ r = (coap_resource_t *)memb_alloc(&resource_storage);
+#endif
+ if (r) {
+ memset(r, 0, sizeof(coap_resource_t));
+
+#ifdef WITH_CONTIKI
+ LIST_STRUCT_INIT(r, link_attr);
+#endif /* WITH_CONTIKI */
+ LIST_STRUCT_INIT(r, subscribers);
+
+ r->uri.s = (unsigned char *)uri;
+ r->uri.length = len;
+
+ coap_hash_path(r->uri.s, r->uri.length, r->key);
+
+ r->flags = flags;
+ } else {
+ debug("coap_resource_init: no memory left\n");
+ }
+
+ return r;
+}
+
+coap_attr_t *
+coap_add_attr(coap_resource_t *resource,
+ const unsigned char *name, size_t nlen,
+ const unsigned char *val, size_t vlen,
+ int flags) {
+ coap_attr_t *attr;
+
+ if (!resource || !name)
+ return NULL;
+
+#ifdef WITH_POSIX
+ attr = (coap_attr_t *)coap_malloc(sizeof(coap_attr_t));
+#endif
+#ifdef WITH_LWIP
+ attr = (coap_attr_t *)memp_malloc(MEMP_COAP_RESOURCEATTR);
+#endif
+#ifdef WITH_CONTIKI
+ attr = (coap_attr_t *)memb_alloc(&attribute_storage);
+#endif
+
+ if (attr) {
+ attr->name.length = nlen;
+ attr->value.length = val ? vlen : 0;
+
+ attr->name.s = (unsigned char *)name;
+ attr->value.s = (unsigned char *)val;
+
+ attr->flags = flags;
+
+ /* add attribute to resource list */
+#ifndef WITH_CONTIKI
+ LL_PREPEND(resource->link_attr, attr);
+#else /* WITH_CONTIKI */
+ list_add(resource->link_attr, attr);
+#endif /* WITH_CONTIKI */
+ } else {
+ debug("coap_add_attr: no memory left\n");
+ }
+
+ return attr;
+}
+
+coap_attr_t *
+coap_find_attr(coap_resource_t *resource,
+ const unsigned char *name, size_t nlen) {
+ coap_attr_t *attr;
+
+ if (!resource || !name)
+ return NULL;
+
+#ifndef WITH_CONTIKI
+ LL_FOREACH(resource->link_attr, attr) {
+#else /* WITH_CONTIKI */
+ for (attr = list_head(resource->link_attr); attr;
+ attr = list_item_next(attr)) {
+#endif /* WITH_CONTIKI */
+ if (attr->name.length == nlen &&
+ memcmp(attr->name.s, name, nlen) == 0)
+ return attr;
+ }
+
+ return NULL;
+}
+
+void
+coap_delete_attr(coap_attr_t *attr) {
+ if (!attr)
+ return;
+ if (attr->flags & COAP_ATTR_FLAGS_RELEASE_NAME)
+ coap_free(attr->name.s);
+ if (attr->flags & COAP_ATTR_FLAGS_RELEASE_VALUE)
+ coap_free(attr->value.s);
+#ifdef POSIX
+ coap_free(attr);
+#endif
+#ifdef WITH_LWIP
+ memp_free(MEMP_COAP_RESOURCEATTR, attr);
+#endif
+#ifdef WITH_CONTIKI
+ /* FIXME it looks like this was never implemented */
+#endif
+}
+
+void
+coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key) {
+ coap_opt_iterator_t opt_iter;
+ coap_opt_filter_t filter;
+ coap_opt_t *option;
+
+ memset(key, 0, sizeof(coap_key_t));
+
+ coap_option_filter_clear(filter);
+ coap_option_setb(filter, COAP_OPTION_URI_PATH);
+
+ coap_option_iterator_init((coap_pdu_t *)request, &opt_iter, filter);
+ while ((option = coap_option_next(&opt_iter)))
+ coap_hash(COAP_OPT_VALUE(option), COAP_OPT_LENGTH(option), key);
+}
+
+void
+coap_add_resource(coap_context_t *context, coap_resource_t *resource) {
+#ifndef WITH_CONTIKI
+#ifdef COAP_RESOURCES_NOHASH
+ LL_PREPEND(context->resources, resource);
+#else
+ HASH_ADD(hh, context->resources, key, sizeof(coap_key_t), resource);
+#endif
+#endif /* WITH_CONTIKI */
+}
+
+int
+coap_delete_resource(coap_context_t *context, coap_key_t key) {
+ coap_resource_t *resource;
+ coap_attr_t *attr, *tmp;
+#ifdef WITH_CONTIKI
+ coap_subscription_t *obs;
+#endif
+
+ if (!context)
+ return 0;
+
+ resource = coap_get_resource_from_key(context, key);
+
+ if (!resource)
+ return 0;
+
+#if defined(WITH_POSIX) || defined(WITH_LWIP)
+#ifdef COAP_RESOURCES_NOHASH
+ LL_DELETE(context->resources, resource);
+#else
+ HASH_DELETE(hh, context->resources, resource);
+#endif
+
+ /* delete registered attributes */
+ LL_FOREACH_SAFE(resource->link_attr, attr, tmp) coap_delete_attr(attr);
+
+ if (resource->flags & COAP_RESOURCE_FLAGS_RELEASE_URI)
+ coap_free(resource->uri.s);
+
+#ifdef WITH_POSIX
+ coap_free(resource);
+#endif
+#ifdef WITH_LWIP
+ memp_free(MEMP_COAP_RESOURCE, resource);
+#endif
+#else /* not (WITH_POSIX || WITH_LWIP) */
+ /* delete registered attributes */
+ while ( (attr = list_pop(resource->link_attr)) )
+ memb_free(&attribute_storage, attr);
+
+ /* delete subscribers */
+ while ( (obs = list_pop(resource->subscribers)) ) {
+ /* FIXME: notify observer that its subscription has been removed */
+ memb_free(&subscription_storage, obs);
+ }
+
+ memb_free(&resource_storage, resource);
+#endif /* WITH_CONTIKI */
+
+ return 1;
+}
+
+coap_resource_t *
+coap_get_resource_from_key(coap_context_t *context, coap_key_t key) {
+#ifndef WITH_CONTIKI
+ coap_resource_t *resource;
+#ifdef COAP_RESOURCES_NOHASH
+ resource = NULL;
+ LL_FOREACH(context->resources, resource) {
+ /* if you think you can outspart the compiler and speed things up by (eg by
+ * casting to uint32* and comparing alues), increment this counter: 1 */
+ if (memcmp(key, resource->key, sizeof(coap_key_t)) == 0)
+ return resource;
+ }
+ return NULL;
+#else
+ HASH_FIND(hh, context->resources, key, sizeof(coap_key_t), resource);
+
+ return resource;
+#endif
+#else /* WITH_CONTIKI */
+ int i;
+ coap_resource_t *ptr2;
+
+ /* the search function is basically taken from memb.c */
+ ptr2 = (coap_resource_t *)resource_storage.mem;
+ for (i = 0; i < resource_storage.num; ++i) {
+ if (resource_storage.count[i] &&
+ (memcmp(ptr2->key, key, sizeof(coap_key_t)) == 0))
+ return (coap_resource_t *)ptr2;
+ ++ptr2;
+ }
+
+ return NULL;
+#endif /* WITH_CONTIKI */
+}
+
+coap_print_status_t
+coap_print_link(const coap_resource_t *resource,
+ unsigned char *buf, size_t *len, size_t *offset) {
+ unsigned char *p = buf;
+ const unsigned char *bufend = buf + *len;
+ coap_attr_t *attr;
+ coap_print_status_t result = 0;
+ const size_t old_offset = *offset;
+
+ *len = 0;
+ PRINT_COND_WITH_OFFSET(p, bufend, *offset, '<', *len);
+ PRINT_COND_WITH_OFFSET(p, bufend, *offset, '/', *len);
+
+ COPY_COND_WITH_OFFSET(p, bufend, *offset,
+ resource->uri.s, resource->uri.length, *len);
+
+ PRINT_COND_WITH_OFFSET(p, bufend, *offset, '>', *len);
+
+#ifndef WITH_CONTIKI
+ LL_FOREACH(resource->link_attr, attr) {
+#else /* WITH_CONTIKI */
+ for (attr = list_head(resource->link_attr); attr;
+ attr = list_item_next(attr)) {
+#endif /* WITH_CONTIKI */
+
+ PRINT_COND_WITH_OFFSET(p, bufend, *offset, ';', *len);
+
+ COPY_COND_WITH_OFFSET(p, bufend, *offset,
+ attr->name.s, attr->name.length, *len);
+
+ if (attr->value.s) {
+ PRINT_COND_WITH_OFFSET(p, bufend, *offset, '=', *len);
+
+ COPY_COND_WITH_OFFSET(p, bufend, *offset,
+ attr->value.s, attr->value.length, *len);
+ }
+
+ }
+ if (resource->observable) {
+ COPY_COND_WITH_OFFSET(p, bufend, *offset, ";obs", 4, *len);
+ }
+
+ result = p - buf;
+ if (result + old_offset - *offset < *len) {
+ result |= COAP_PRINT_STATUS_TRUNC;
+ }
+
+ return result;
+}
+
+#ifndef WITHOUT_OBSERVE
+coap_subscription_t *
+coap_find_observer(coap_resource_t *resource, const coap_address_t *peer,
+ const str *token) {
+ coap_subscription_t *s;
+
+ assert(resource);
+ assert(peer);
+
+ for (s = (coap_subscription_t*)list_head(resource->subscribers); s;
+ s = (coap_subscription_t*)list_item_next(s)) {
+ if (coap_address_equals(&s->subscriber, peer)
+ && (!token || (token->length == s->token_length
+ && memcmp(token->s, s->token, token->length) == 0)))
+ return s;
+ }
+
+ return NULL;
+}
+
+coap_subscription_t *
+coap_add_observer(coap_resource_t *resource,
+ const coap_address_t *observer,
+ const str *token) {
+ coap_subscription_t *s;
+
+ assert(observer);
+
+ /* Check if there is already a subscription for this peer. */
+ s = coap_find_observer(resource, observer, token);
+
+ /* We are done if subscription was found. */
+ if (s)
+ return s;
+
+ /* s points to a different subscription, so we have to create
+ * another one. */
+ s = COAP_MALLOC_TYPE(subscription);
+
+ if (!s)
+ return NULL;
+
+ coap_subscription_init(s);
+ memcpy(&s->subscriber, observer, sizeof(coap_address_t));
+
+ if (token && token->length) {
+ s->token_length = token->length;
+ memcpy(s->token, token->s, min(s->token_length, 8));
+ }
+
+ /* add subscriber to resource */
+ list_add(resource->subscribers, s);
+
+ return s;
+}
+
+void
+coap_touch_observer(coap_context_t *context, const coap_address_t *observer,
+ const str *token) {
+ coap_resource_t *r;
+ coap_subscription_t *s;
+
+#ifndef WITH_CONTIKI
+#ifdef COAP_RESOURCES_NOHASH
+ LL_FOREACH(context->resources, r) {
+#else
+ coap_resource_t *tmp;
+ HASH_ITER(hh, context->resources, r, tmp) {
+#endif
+ s = coap_find_observer(r, observer, token);
+ if (s) {
+ s->fail_cnt = 0;
+ }
+ }
+#else /* WITH_CONTIKI */
+ r = (coap_resource_t *)resource_storage.mem;
+ for (i = 0; i < resource_storage.num; ++i, ++r) {
+ if (resource_storage.count[i]) {
+ s = coap_find_observer(r, observer, token);
+ if (s) {
+ s->fail_cnt = 0;
+ }
+ }
+ }
+#endif /* WITH_CONTIKI */
+}
+
+void
+coap_delete_observer(coap_resource_t *resource, const coap_address_t *observer,
+ const str *token) {
+ coap_subscription_t *s;
+
+ s = coap_find_observer(resource, observer, token);
+
+ if (s) {
+ list_remove(resource->subscribers, s);
+
+ COAP_FREE_TYPE(subscription,s);
+ }
+}
+
+static void
+coap_notify_observers(coap_context_t *context, coap_resource_t *r) {
+ coap_method_handler_t h;
+ coap_subscription_t *obs;
+ str token;
+ coap_pdu_t *response;
+
+ if (r->observable && (r->dirty || r->partiallydirty)) {
+ r->partiallydirty = 0;
+
+ /* retrieve GET handler, prepare response */
+ h = r->handler[COAP_REQUEST_GET - 1];
+ assert(h); /* we do not allow subscriptions if no
+ * GET handler is defined */
+
+ for (obs = (coap_subscription_t*)list_head(r->subscribers); obs;
+ obs = (coap_subscription_t*)list_item_next(obs)) {
+ if (r->dirty == 0 && obs->dirty == 0)
+ /* running this resource due to partiallydirty, but this observation's notification was already enqueued */
+ continue;
+
+ coap_tid_t tid = COAP_INVALID_TID;
+ obs->dirty = 0;
+ /* initialize response */
+ response = coap_pdu_init(COAP_MESSAGE_CON, 0, 0, COAP_MAX_PDU_SIZE);
+ if (!response) {
+ obs->dirty = 1;
+ r->partiallydirty = 1;
+ debug("coap_check_notify: pdu init failed, resource stays partially dirty\n");
+ continue;
+ }
+
+ if (!coap_add_token(response, obs->token_length, obs->token)) {
+ obs->dirty = 1;
+ r->partiallydirty = 1;
+ debug("coap_check_notify: cannot add token, resource stays partially dirty\n");
+ coap_delete_pdu(response);
+ continue;
+ }
+
+ token.length = obs->token_length;
+ token.s = obs->token;
+
+ response->hdr->id = coap_new_message_id(context);
+ if (obs->non && obs->non_cnt < COAP_OBS_MAX_NON) {
+ response->hdr->type = COAP_MESSAGE_NON;
+ } else {
+ response->hdr->type = COAP_MESSAGE_CON;
+ }
+ /* fill with observer-specific data */
+ h(context, r, &obs->subscriber, NULL, &token, response);
+
+ if (response->hdr->type == COAP_MESSAGE_CON) {
+ tid = coap_send_confirmed(context, &obs->subscriber, response);
+ obs->non_cnt = 0;
+ } else {
+ tid = coap_send(context, &obs->subscriber, response);
+ obs->non_cnt++;
+ }
+
+ if (COAP_INVALID_TID == tid || response->hdr->type != COAP_MESSAGE_CON)
+ coap_delete_pdu(response);
+ if (COAP_INVALID_TID == tid)
+ {
+ debug("coap_check_notify: sending failed, resource stays partially dirty\n");
+ obs->dirty = 1;
+ r->partiallydirty = 1;
+ }
+
+ }
+
+ /* Increment value for next Observe use. */
+ context->observe++;
+ }
+ r->dirty = 0;
+}
+
+void
+coap_check_notify(coap_context_t *context) {
+ coap_resource_t *r;
+#ifndef WITH_CONTIKI
+
+#ifdef COAP_RESOURCES_NOHASH
+ LL_FOREACH(context->resources, r) {
+#else
+ coap_resource_t *tmp;
+ HASH_ITER(hh, context->resources, r, tmp) {
+#endif
+ coap_notify_observers(context, r);
+ }
+#else /* WITH_CONTIKI */
+ int i;
+
+ r = (coap_resource_t *)resource_storage.mem;
+ for (i = 0; i < resource_storage.num; ++i, ++r) {
+ if (resource_storage.count[i]) {
+ coap_notify_observers(context, r);
+ }
+ }
+#endif /* WITH_CONTIKI */
+}
+
+/**
+ * Checks the failure counter for (peer, token) and removes peer from
+ * the list of observers for the given resource when COAP_OBS_MAX_FAIL
+ * is reached.
+ *
+ * @param context The CoAP context to use
+ * @param resource The resource to check for (peer, token)
+ * @param peer The observer's address
+ * @param token The token that has been used for subscription.
+ */
+static void
+coap_remove_failed_observers(coap_context_t *context,
+ coap_resource_t *resource,
+ const coap_address_t *peer,
+ const str *token) {
+ coap_subscription_t *obs;
+
+ for (obs = (coap_subscription_t*)list_head(resource->subscribers); obs;
+ obs = (coap_subscription_t*)list_item_next(obs)) {
+ if (coap_address_equals(peer, &obs->subscriber) &&
+ token->length == obs->token_length &&
+ memcmp(token->s, obs->token, token->length) == 0) {
+
+ /* count failed notifies and remove when
+ * COAP_MAX_FAILED_NOTIFY is reached */
+ if (obs->fail_cnt < COAP_OBS_MAX_FAIL)
+ obs->fail_cnt++;
+ else {
+ list_remove(resource->subscribers, obs);
+ obs->fail_cnt = 0;
+
+#ifndef NDEBUG
+ if (LOG_DEBUG <= coap_get_log_level()) {
+#ifndef INET6_ADDRSTRLEN
+#define INET6_ADDRSTRLEN 40
+#endif
+ unsigned char addr[INET6_ADDRSTRLEN+8];
+
+ if (coap_print_addr(&obs->subscriber, addr, INET6_ADDRSTRLEN+8))
+ debug("** removed observer %s\n", addr);
+ }
+#endif
+ coap_cancel_all_messages(context, &obs->subscriber,
+ obs->token, obs->token_length);
+
+ COAP_FREE_TYPE(subscription, obs);
+ }
+ }
+ break; /* break loop if observer was found */
+ }
+}
+
+void
+coap_handle_failed_notify(coap_context_t *context,
+ const coap_address_t *peer,
+ const str *token) {
+ coap_resource_t *r;
+
+#ifndef WITH_CONTIKI
+
+#ifdef COAP_RESOURCES_NOHASH
+ LL_FOREACH(context->resources, r) {
+#else
+ coap_resource_t *tmp;
+ HASH_ITER(hh, context->resources, r, tmp) {
+#endif
+ coap_remove_failed_observers(context, r, peer, token);
+ }
+#else /* WITH_CONTIKI */
+ int i;
+
+ r = (coap_resource_t *)resource_storage.mem;
+ for (i = 0; i < resource_storage.num; ++i, ++r) {
+ if (resource_storage.count[i]) {
+ coap_remove_failed_observers(context, r, peer, token);
+ }
+ }
+#endif /* WITH_CONTIKI */
+}
+#endif /* WITHOUT_NOTIFY */
--- /dev/null
+/* resource.h -- generic resource handling
+ *
+ * Copyright (C) 2010,2011,2014 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+/**
+ * @file resource.h
+ * @brief generic resource handling
+ */
+
+#ifndef _COAP_RESOURCE_H_
+#define _COAP_RESOURCE_H_
+
+#include "config.h"
+#include "t_list.h"
+
+#if defined(HAVE_ASSERT_H) && !defined(assert)
+# include <assert.h>
+#endif
+
+#ifndef COAP_RESOURCE_CHECK_TIME
+/** The interval in seconds to check if resources have changed. */
+#define COAP_RESOURCE_CHECK_TIME 2
+#endif /* COAP_RESOURCE_CHECK_TIME */
+
+#ifndef WITH_CONTIKI
+# ifdef COAP_RESOURCES_NOHASH
+# include "utlist.h"
+# else
+# include "uthash.h"
+# endif
+#else /* WITH_CONTIKI */
+#endif /* WITH_CONTIKI */
+#include "hashkey.h"
+#include "async.h"
+#include "str.h"
+#include "pdu.h"
+#include "net.h"
+#include "subscribe.h"
+
+/** Definition of message handler function (@sa coap_resource_t). */
+typedef void (*coap_method_handler_t)
+ (coap_context_t *, struct coap_resource_t *, coap_address_t *, coap_pdu_t *,
+ str * /* token */, coap_pdu_t * /* response */);
+
+#define COAP_ATTR_FLAGS_RELEASE_NAME 0x1
+#define COAP_ATTR_FLAGS_RELEASE_VALUE 0x2
+
+typedef struct coap_attr_t {
+ struct coap_attr_t *next;
+ str name;
+ str value;
+ int flags;
+} coap_attr_t;
+
+#define COAP_RESOURCE_FLAGS_RELEASE_URI 0x1
+
+typedef struct coap_resource_t {
+ unsigned int dirty:1; /**< set to 1 if resource has changed */
+ unsigned int partiallydirty:1; /**< set to 1 if some subscribers have not yet been notified of the last change */
+ unsigned int observable:1; /**< can be observed */
+ unsigned int cacheable:1; /**< can be cached */
+
+ /**
+ * Used to store handlers for the four coap methods @c GET, @c POST,
+ * @c PUT, and @c DELETE. coap_dispatch() will pass incoming
+ * requests to the handler that corresponds to its request method or
+ * generate a 4.05 response if no handler is available.
+ */
+ coap_method_handler_t handler[4];
+
+ coap_key_t key; /**< the actual key bytes for this resource */
+
+#ifndef WITH_CONTIKI
+#ifdef COAP_RESOURCES_NOHASH
+ struct coap_resource_t *next;
+#else
+ UT_hash_handle hh;
+#endif
+#endif /* WITH_CONTIKI */
+
+#ifndef WITH_CONTIKI
+ coap_attr_t *link_attr; /**< attributes to be included with the link format */
+#else /* WITH_CONTIKI */
+ LIST_STRUCT(link_attr); /**< attributes to be included with the link format */
+#endif /* WITH_CONTIKI */
+ LIST_STRUCT(subscribers); /**< list of observers for this resource */
+
+
+ /**
+ * Request URI for this resource. This field will point into the
+ * static memory. */
+ str uri;
+ int flags;
+
+} coap_resource_t;
+
+/**
+ * Creates a new resource object and initializes the link field to the
+ * string of length @p len. This function returns the
+ * new coap_resource_t object.
+ *
+ * @param uri The URI path of the new resource.
+ * @param len The length of @p uri.
+ * @param flags Flags for memory management (in particular release of memory)
+ *
+ * @return A pointer to the new object or @c NULL on error.
+ */
+coap_resource_t *coap_resource_init(const unsigned char *uri, size_t len, int flags);
+
+/**
+ * Registers the given @p resource for @p context. The resource must
+ * have been created by coap_resource_init(), the storage allocated
+ * for the resource will be released by coap_delete_resource().
+ *
+ * @param context The context to use.
+ * @param resource The resource to store.
+ */
+void coap_add_resource(coap_context_t *context, coap_resource_t *resource);
+
+/**
+ * Deletes a resource identified by @p key. The storage allocated for
+ * that resource is freed.
+ *
+ * @param context The context where the resources are stored.
+ * @param key The unique key for the resource to delete.
+ *
+ * @return @c 1 if the resource was found (and destroyed), @c 0 otherwise.
+ */
+int coap_delete_resource(coap_context_t *context, coap_key_t key);
+
+/**
+ * Registers a new attribute with the given @p resource. As the
+ * attributes str fields will point to @p name and @p val the
+ * caller must ensure that these pointers are valid during the
+ * attribute's lifetime.
+ *
+ * @param resource The resource to register the attribute with.
+ * @param name The attribute's name.
+ * @param nlen Length of @p name.
+ * @param val The attribute's value or @c NULL if none.
+ * @param vlen Length of @p val if specified.
+ * @param flags Flags for memory management (in particular release of memory)
+ *
+ * @return A pointer to the new attribute or @c NULL on error.
+ */
+coap_attr_t *coap_add_attr(coap_resource_t *resource,
+ const unsigned char *name, size_t nlen,
+ const unsigned char *val, size_t vlen,
+ int flags);
+
+/**
+ * Returns @p resource's coap_attr_t object with given @p name if
+ * found, @c NULL otherwise.
+ *
+ * @param resource The resource to search for attribute @p name.
+ * @param name Name of the requested attribute.
+ * @param nlen Actual length of @p name.
+ * @return The first attribute with specified @p name or @c NULL if
+ * none was found.
+ */
+coap_attr_t *coap_find_attr(coap_resource_t *resource,
+ const unsigned char *name, size_t nlen);
+
+/**
+ * Deletes an attribute
+ *
+ * @param attr Pointer to a previously created attribute
+ *
+ */
+void coap_delete_attr(coap_attr_t *attr);
+
+/**
+ * Status word to encode the result of conditional print or copy
+ * operations such as coap_print_link(). The lower 28 bits of
+ * coap_print_status_t are used to encode the number of characters
+ * that has actually been printed, bits 28 to 31 encode the status.
+ * When COAP_PRINT_STATUS_ERROR is set, an error occurred during
+ * output. In this case, the other bits are undefined.
+ * COAP_PRINT_STATUS_TRUNC indicates that the output is truncated,
+ * i.e. the printing would have exceeded the current buffer.
+ */
+typedef unsigned int coap_print_status_t;
+
+#define COAP_PRINT_STATUS_MASK 0xF0000000u
+#define COAP_PRINT_OUTPUT_LENGTH(v) ((v) & ~COAP_PRINT_STATUS_MASK)
+#define COAP_PRINT_STATUS_ERROR 0x80000000u
+#define COAP_PRINT_STATUS_TRUNC 0x40000000u
+
+/**
+ * Writes a description of this resource in link-format to given text
+ * buffer. @p len must be initialized to the maximum length of @p buf
+ * and will be set to the number of characters actually written if
+ * successful. This function returns @c 1 on success or @c 0 on
+ * error.
+ *
+ * @param resource The resource to describe.
+ * @param buf The output buffer to write the description to.
+ * @param len Must be initialized to the length of @p buf and
+ * will be set to the length of the printed link description.
+ * @param offset The offset within the resource description where to
+ * start writing into @p buf. This is useful for dealing
+ * with the Block2 option. @p offset is updated during
+ * output as it is consumed.
+ *
+ * @return If COAP_PRINT_STATUS_ERROR is set, an error occured. Otherwise,
+ * the lower 28 bits will indicate the number of characters that
+ * have actually been output into @p buffer. The flag
+ * COAP_PRINT_STATUS_TRUNC indicates that the output has been
+ * truncated.
+ */
+coap_print_status_t coap_print_link(const coap_resource_t *resource,
+ unsigned char *buf, size_t *len, size_t *offset);
+
+/**
+ * Registers the specified @p handler as message handler for the request type
+ * @p method
+ *
+ * @param resource The resource for which the handler shall be registered.
+ * @param method The CoAP request method to handle.
+ * @param handler The handler to register with @p resource.
+ */
+static inline void
+coap_register_handler(coap_resource_t *resource,
+ unsigned char method, coap_method_handler_t handler) {
+ assert(resource);
+ assert(method > 0 && (size_t)(method-1) < sizeof(resource->handler)/sizeof(coap_method_handler_t));
+ resource->handler[method-1] = handler;
+}
+
+/**
+ * Returns the resource identified by the unique string @p key. If no
+ * resource was found, this function returns @c NULL.
+ *
+ * @param context The context to look for this resource.
+ * @param key The unique key of the resource.
+ *
+ * @return A pointer to the resource or @c NULL if not found.
+ */
+coap_resource_t *coap_get_resource_from_key(coap_context_t *context,
+ coap_key_t key);
+
+/**
+ * Calculates the hash key for the resource requested by the
+ * Uri-Options of @p request. This function calls coap_hash() for
+ * every path segment.
+ *
+ * @param request The requesting pdu.
+ * @param key The resulting hash is stored in @p key
+ */
+void coap_hash_request_uri(const coap_pdu_t *request, coap_key_t key);
+
+/**
+ * @addtogroup observe
+ */
+
+/**
+ * Adds the specified peer as observer for @p resource. The
+ * subscription is identified by the given @p token. This function
+ * returns the registered subscription information if the @p observer
+ * has been added, or @c NULL on error.
+ *
+ * @param resource The observed resource.
+ * @param observer The remote peer that wants to received status updates.
+ * @param token The token that identifies this subscription.
+ * @param token_length The actual length of @p token. Must be @c 0 when
+ * @p token is @c NULL.
+ * @return A pointer to the added/updated subscription information or
+ * @c NULL on error.
+ */
+coap_subscription_t *coap_add_observer(coap_resource_t *resource,
+ const coap_address_t *observer,
+ const str *token);
+
+/**
+ * Returns a subscription object for given @p peer.
+ *
+ * @param resource The observed resource.
+ * @param peer The address to search for.
+ * @param token The token that identifies this subscription or @c NULL for any
+ * token.
+ * @return A valid subscription if exists or @c NULL otherwise.
+ */
+coap_subscription_t *coap_find_observer(coap_resource_t *resource,
+ const coap_address_t *peer,
+ const str *token);
+
+/**
+ * Marks an observer as alive.
+ *
+ * @param context The CoAP context to use
+ * @param observer The transport address of the observer
+ * @param token The corresponding token that has been used for
+ * the subscription
+ */
+void coap_touch_observer(coap_context_t *context,
+ const coap_address_t *observer,
+ const str *token);
+
+/**
+ * Removes any subscription for @p observer from @p resource and releases
+ * the allocated storage.
+ *
+ * @param resource The observed resource.
+ * @param observer The observer's address.
+ * @param token The token that identifies this subscription or @c NULL for any
+ * token.
+ */
+void coap_delete_observer(coap_resource_t *resource,
+ const coap_address_t *observer,
+ const str *token);
+
+/**
+ * Checks for all known resources, if they are dirty and notifies
+ * subscribed observers.
+ */
+void coap_check_notify(coap_context_t *context);
+
+/** @} */
+
+#endif /* _COAP_RESOURCE_H_ */
--- /dev/null
+/* str.c -- strings to be used in the CoAP library
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+
+#include "debug.h"
+#include "mem.h"
+#include "str.h"
+
+str *coap_new_string(size_t size) {
+ str *s = (str*)coap_malloc(sizeof(str) + size + 1);
+ if ( !s ) {
+#ifndef NDEBUG
+ coap_log(LOG_CRIT, "coap_new_string: malloc\n");
+#endif
+ return NULL;
+ }
+
+ memset(s, 0, sizeof(str));
+ s->s = ((unsigned char *)s) + sizeof(str);
+ return s;
+}
+
+void coap_delete_string(str *s) {
+ coap_free(s);
+}
+
--- /dev/null
+/* str.h -- strings to be used in the CoAP library
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef _COAP_STR_H_
+#define _COAP_STR_H_
+
+#include <string.h>
+
+typedef struct {
+ size_t length; /* length of string */
+ unsigned char *s; /* string data */
+} str;
+
+#define COAP_SET_STR(st,l,v) { (st)->length = (l), (st)->s = (v); }
+
+/**
+ * Returns a new string object with at least size bytes storage
+ * allocated. The string must be released using coap_delete_string();
+ */
+str *coap_new_string(size_t size);
+
+/** Deletes the given string and releases any memory allocated. */
+void coap_delete_string(str *);
+
+#endif /* _COAP_STR_H_ */
--- /dev/null
+/* subscribe.c -- subscription handling for CoAP
+ * see draft-ietf-coap-observe-09
+ *
+ * Copyright (C) 2010--2013 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "config.h"
+
+#if defined(HAVE_ASSERT_H) && !defined(assert)
+# include <assert.h>
+#endif
+
+#include <stdio.h>
+#include <limits.h>
+#ifdef HAVE_ARPA_INET_H
+# include <arpa/inet.h>
+#endif
+
+/* #include "resource.h" */
+
+#include "mem.h"
+#include "encode.h"
+#include "debug.h"
+#include "subscribe.h"
+
+void
+coap_subscription_init(coap_subscription_t *s) {
+ assert(s);
+ memset(s, 0, sizeof(coap_subscription_t));
+}
+
+#if 0
+#define HMASK (ULONG_MAX >> 1)
+
+void
+notify(coap_context_t *context, coap_resource_t *res,
+ coap_subscription_t *sub, unsigned int duration, int code) {
+#if 0
+ coap_pdu_t *pdu;
+ int ls, finished=0;
+ unsigned char ct, d;
+ unsigned int length;
+#ifndef NDEBUG
+ char addr[INET6_ADDRSTRLEN];
+#endif
+
+ if ( !context || !res || !sub || !(pdu = coap_new_pdu()) )
+ return;
+
+ pdu->hdr->type = COAP_MESSAGE_CON;
+ pdu->hdr->id = rand(); /* use a random transaction id */
+ pdu->hdr->code = code;
+
+ /* FIXME: content-type and data (how about block?) */
+ if (res->uri->host.length)
+ coap_add_option (pdu, COAP_OPTION_URI_HOST,
+ res->uri->host.length,
+ res->uri->host.s );
+
+ if (res->uri->path.length)
+ coap_add_option (pdu, COAP_OPTION_URI_PATH,
+ res->uri->path.length,
+ res->uri->path.s);
+
+ d = COAP_PSEUDOFP_ENCODE_8_4_DOWN(duration, ls);
+
+ coap_add_option ( pdu, COAP_OPTION_SUBSCRIPTION, 1, &d );
+
+ if (sub->token.length) {
+ coap_add_option (pdu, COAP_OPTION_TOKEN,
+ sub->token.length,
+ sub->token.s);
+ }
+
+ if (res->uri->query.length)
+ coap_add_option (pdu, COAP_OPTION_URI_QUERY,
+ res->uri->query.length,
+ res->uri->query.s );
+
+ if (res->data) {
+ length = (unsigned char *)pdu->hdr + COAP_MAX_PDU_SIZE - pdu->data;
+ ct = res->mediatype;
+ res->data(res->uri, &ct, 0, pdu->data, &length, &finished);
+ pdu->length += length;
+
+ /* TODO: add block option if not finished */
+ /* TODO: add mediatype */
+ }
+
+#ifndef NDEBUG
+ if ( inet_ntop(sub->subscriber.addr.sa.sa_family,
+ &sub->subscriber.addr, addr, sizeof(addr)) ) {
+ debug("*** notify for %s to [%s]\n", res->uri->path.s, addr);
+ }
+#endif
+ if (pdu && coap_send_confirmed(context,
+ &sub->subscriber.addr.sa,
+ sub->subscriber.size, pdu)
+ == COAP_INVALID_TID) {
+#ifndef NDEBUG
+ debug("coap_check_resource_list: error sending notification\n");
+#endif
+ coap_delete_pdu(pdu);
+ }
+#endif
+}
+
+void
+coap_check_resource_list(coap_context_t *context) {
+ coap_resource_t *res, *tmp;
+ coap_list_t *sub;
+ coap_key_t key;
+ time_t now;
+
+ if ( !context || !context->resources /* || !context->subscribers */)
+ return;
+
+ time(&now); /* FIXME: use coap_ticks() */
+
+ HASH_ITER(hh, context->resources, res, tmp) {
+ if (res->dirty) {
+ debug("FIXME: notify subscribers\n");
+#if 0
+ key = coap_uri_hash( COAP_RESOURCE(res)->uri ) ;
+
+ /* is subscribed? */
+ for (sub = context->subscriptions; sub; sub = sub->next) {
+ if ( COAP_SUBSCRIPTION(sub)->resource == key ) {
+ /* notify subscriber */
+ notify(context, COAP_RESOURCE(res), COAP_SUBSCRIPTION(sub),
+ COAP_SUBSCRIPTION(sub)->expires - now, COAP_RESPONSE_200);
+ }
+
+ }
+
+ COAP_RESOURCE(res)->dirty = 0;
+#endif
+ }
+ }
+}
+
+#if 0
+coap_resource_t *
+coap_get_resource_from_key(coap_context_t *ctx, coap_key_t key) {
+ coap_list_t *node;
+
+ if (ctx) {
+ /* TODO: use hash table for resources with key to access */
+ for (node = ctx->resources; node; node = node->next) {
+ printf("check %ux\n", coap_uri_hash(COAP_RESOURCE(node)->uri));
+ if ( key == coap_uri_hash(COAP_RESOURCE(node)->uri) ) {
+ printf("found\n");
+ return COAP_RESOURCE(node);
+ }
+ }
+ }
+
+ printf("not found\n");
+ return NULL;
+}
+
+coap_resource_t *
+coap_get_resource(coap_context_t *ctx, coap_uri_t *uri) {
+#ifndef NDEBUG
+ int i;
+ printf("search resource %ux", coap_uri_hash(uri));
+ for (i=0; i < uri->path.length; ++i) {
+ printf(" %02x", uri->path.s[i]);
+ }
+ printf("\n");
+#endif
+ return uri ? coap_get_resource_from_key(ctx, coap_uri_hash(uri)) : NULL;
+}
+#endif
+
+void
+coap_check_subscriptions(coap_context_t *context) {
+ time_t now;
+ coap_list_t *node;
+#ifndef NDEBUG
+ char addr[INET6_ADDRSTRLEN];
+#endif
+
+ if ( !context )
+ return;
+
+ time(&now);
+
+ node = context->subscriptions;
+ while ( node && COAP_SUBSCRIPTION(node)->expires < now ) {
+#ifndef NDEBUG
+ if (inet_ntop(COAP_SUBSCRIPTION(node)->subscriber.addr.sa.sa_family,
+ &COAP_SUBSCRIPTION(node)->subscriber.addr,
+ addr, sizeof(addr))) {
+
+ debug("** removed expired subscription from [%s]\n", addr);
+ }
+#endif
+#if 0
+ notify(context,
+ coap_get_resource_from_key(context, COAP_SUBSCRIPTION(node)->resource),
+ COAP_SUBSCRIPTION(node),
+ 0, COAP_RESPONSE_400);
+#endif
+ context->subscriptions = node->next;
+ coap_delete(node);
+ node = context->subscriptions;
+ }
+}
+
+void
+coap_free_resource(void *res) {
+ if ( res ) {
+#if 0
+ coap_free(((coap_resource_t *)res)->uri);
+ coap_delete_string(((coap_resource_t *)res)->name);
+#endif
+ }
+}
+
+#if 0
+/**
+ * Deletes the resource that is identified by key. Returns 1 if the resource was
+ * removed, 0 on error (e.g. if no such resource exists).
+ */
+int
+coap_delete_resource(coap_context_t *context, coap_key_t key) {
+ coap_list_t *prev, *node;
+
+ if (!context || key == COAP_INVALID_HASHKEY)
+ return 0;
+
+ for (prev = NULL, node = context->resources; node;
+ prev = node, node = node->next) {
+ if (coap_uri_hash(COAP_RESOURCE(node)->uri) == key) {
+#ifndef NDEBUG
+ debug("removed key %lu (%s)\n",key,COAP_RESOURCE(node)->uri->path.s);
+#endif
+ if (!prev)
+ context->resources = node->next;
+ else
+ prev->next = node->next;
+
+ coap_delete(node);
+ return 1;
+ }
+ }
+ return 0;
+}
+#endif
+
+coap_subscription_t *
+coap_new_subscription(coap_context_t *context, const coap_uri_t *resource,
+ const struct sockaddr *addr, socklen_t addrlen, time_t expiry) {
+ coap_subscription_t *result;
+
+ if ( !context || !resource || !addr
+ || !(result = coap_malloc(sizeof(coap_subscription_t))))
+ return NULL;
+
+ result->resource = coap_uri_hash(resource);
+ result->expires = expiry;
+ memcpy(&result->subscriber.addr.sa, addr, addrlen);
+
+ memset(&result->token, 0, sizeof(str));
+
+ return result;
+
+}
+
+coap_list_t *
+coap_list_push_first(coap_list_t **list, void *data, void (*delete_func)(void *) ) {
+ coap_list_t *node;
+ node = coap_new_listnode(data, delete_func);
+ if ( !node || !list )
+ return NULL;
+
+ if ( !*list ) {
+ *list = node;
+ } else {
+ node->next = *list;
+ *list = node;
+ }
+
+ return node;
+}
+
+int
+_order_subscription(void *a, void *b) {
+ if ( !a || !b )
+ return a < b ? -1 : 1;
+
+ return ((coap_subscription_t *)a)->expires < ((coap_subscription_t *)b)->expires ? -1 : 1;
+}
+
+coap_key_t
+coap_subscription_hash(coap_subscription_t *subscription) {
+ if ( !subscription )
+ return COAP_INVALID_HASHKEY;
+
+ return _hash2( subscription->resource, (unsigned char *)&subscription->subscriber,
+ sizeof(subscription->subscriber) );
+}
+
+coap_key_t
+coap_add_subscription(coap_context_t *context,
+ coap_subscription_t *subscription) {
+ coap_list_t *node;
+ if ( !context || !subscription )
+ return COAP_INVALID_HASHKEY;
+
+ if ( !(node = coap_new_listnode(subscription, NULL)) )
+ return COAP_INVALID_HASHKEY;
+
+ if ( !coap_insert(&context->subscriptions, node, _order_subscription ) ) {
+ coap_free( node ); /* do not call coap_delete(), so subscription object will survive */
+ return COAP_INVALID_HASHKEY;
+ }
+
+ return coap_subscription_hash(subscription);
+}
+
+coap_subscription_t *
+coap_find_subscription(coap_context_t *context,
+ coap_key_t hashkey,
+ struct sockaddr *addr,
+ str *token) {
+#if 0
+ coap_list_t *node;
+#endif
+
+ if (!context || !addr || hashkey == COAP_INVALID_HASHKEY)
+ return NULL;
+
+ /* FIXME: I do not like the way subscriptions work right now. To be fixed. */
+
+#if 0
+ for (node = context->subscriptions; node; node = node->next) {
+ if (COAP_SUBSCRIPTION(node)->resource == hashkey) {
+
+ if (token) { /* do not proceed if tokens do not match */
+ if (token->length != COAP_SUBSCRIPTION(node)->token.length ||
+ memcmp(token->s, COAP_SUBSCRIPTION(node)->token.s,
+ token->length) != 0)
+ continue;
+ }
+
+ if (subscriber->sin6_port == COAP_SUBSCRIPTION(node)->subscriber.sin6_port
+ && memcmp(&subscriber->sin6_addr,
+ &COAP_SUBSCRIPTION(node)->subscriber.sin6_addr,
+ sizeof(struct in6_addr)) == 0)
+ return COAP_SUBSCRIPTION(node);
+ }
+ }
+#endif
+ return NULL;
+}
+
+int
+coap_delete_subscription(coap_context_t *context,
+ coap_key_t key,
+ struct sockaddr *addr) {
+#if 0
+ coap_list_t *prev, *node;
+#endif
+
+ if (!context || !addr || key == COAP_INVALID_HASHKEY)
+ return 0;
+
+ /* FIXME: I do not like the way subscriptions work right now. To be fixed. */
+
+#if 0
+ for (prev = NULL, node = context->subscriptions; node;
+ prev = node, node = node->next) {
+ if (COAP_SUBSCRIPTION(node)->resource == key) {
+ if (subscriber->sin6_port == COAP_SUBSCRIPTION(node)->subscriber.sin6_port
+ && memcmp(&subscriber->sin6_addr,
+ &COAP_SUBSCRIPTION(node)->subscriber.sin6_addr,
+ sizeof(struct in6_addr)) == 0) {
+
+ if (!prev) {
+ context->subscriptions = node->next;
+ coap_free(COAP_SUBSCRIPTION(node)->token.s);
+ coap_delete(node);
+ } else {
+ prev->next = node->next;
+ coap_free(COAP_SUBSCRIPTION(node)->token.s);
+ coap_delete(node);
+ }
+ return 1;
+ }
+ }
+ }
+#endif
+
+ return 0;
+}
+#endif
--- /dev/null
+/* subscribe.h -- subscription handling for CoAP
+ * see draft-hartke-coap-observe-03
+ *
+ * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+
+#ifndef _COAP_SUBSCRIBE_H_
+#define _COAP_SUBSCRIBE_H_
+
+#include "config.h"
+#include "address.h"
+
+/**
+ * @defgroup observe Resource observation
+ * @{
+ */
+
+#ifndef COAP_OBS_MAX_NON
+/**
+ * Number of notifications that may be sent non-confirmable before a
+ * confirmable message is sent to detect if observers are alive. The
+ * maximum allowed value here is @c 15.
+ */
+#define COAP_OBS_MAX_NON 5
+#endif /* COAP_OBS_MAX_NON */
+
+#ifndef COAP_OBS_MAX_FAIL
+/**
+ * Number of confirmable notifications that may fail (i.e. time out
+ * without being ACKed) before an observer is removed. The maximum
+ * value for COAP_OBS_MAX_FAIL is @c 3.
+ */
+#define COAP_OBS_MAX_FAIL 3
+#endif /* COAP_OBS_MAX_FAIL */
+
+/** Subscriber information */
+typedef struct coap_subscription_t {
+ struct coap_subscription_t *next; /**< next element in linked list */
+ coap_address_t subscriber; /**< address and port of subscriber */
+
+ unsigned int non:1; /**< send non-confirmable notifies if @c 1 */
+ unsigned int non_cnt:4; /**< up to 15 non-confirmable notifies allowed */
+ unsigned int fail_cnt:2; /**< up to 3 confirmable notifies can fail */
+ unsigned int dirty:1; /**< set if the notification temporarily could not be sent (in that case, the resource's partiallydirty flag is set too) */
+
+ size_t token_length; /**< actual length of token */
+ unsigned char token[8]; /**< token used for subscription */
+ /* @todo CON/NON flag, block size */
+} coap_subscription_t;
+
+void coap_subscription_init(coap_subscription_t *);
+
+#if 0
+#include "uthash.h"
+#include "uri.h"
+#include "list.h"
+#include "pdu.h"
+#include "net.h"
+
+#if 0
+typedef unsigned long coap_key_t;
+
+/** Used to indicate that a hashkey is invalid. */
+#define COAP_INVALID_HASHKEY ((coap_key_t)-1)
+
+typedef struct {
+ coap_uri_t *uri; /* unique identifier; memory is released by coap_delete_resource() */
+ UT_hash_handle hh; /**< hash handle (for internal use only) */
+ str *name; /* display name of the resource */
+ unsigned char mediatype; /* media type for resource representation */
+ unsigned int dirty:1; /* set to 1 if resource has changed */
+ unsigned int writable:1; /* set to 1 if resource can be changed using PUT */
+
+ /* cache-control */
+ unsigned char etag[4]; /* version identifier for this resource
+ * (zero terminated, first byte is zero if not set). */
+ unsigned int maxage; /* maximum cache time (zero means no Max-age option) */
+
+ /**
+ * Callback function that copies the resource representation into the provided data
+ * buffer (PDU payload). finished is set to 1 to indicate that this was the last block
+ * of buflen data for this resource representation, 0 means that data is not finished
+ * and a subsequent call with offset updated by buflen would yield more data (i.e.
+ * the M-bit of CoAP's block option must be set if offset and buflen are selected
+ * accordingly.
+ * When called, buflen must be set to the maximum length of buf that is to be filled
+ * with the mediatype representation of the resource identified by uri.
+ * The mediatype must be set to the requested mediatype of COAP_MEDIATYPE_ANY if
+ * none was given. On return, the mediatype will be set to the type that is
+ * actually used.
+ * The return value indicates the result code that should be used in a response to
+ * this function.
+ */
+ int (*data)(coap_uri_t *uri, unsigned char *mediatype, unsigned int offset, unsigned char *buf, unsigned int *buflen, int *finished);
+} coap_resource_t;
+#endif
+
+typedef struct {
+ coap_key_t resource; /* hash key for subscribed resource */
+ time_t expires; /* expiry time of subscription */
+
+ coap_address_t subscriber; /**< subscriber's address */
+
+ str token; /**< subscription token */
+} coap_subscription_t;
+
+#define COAP_RESOURCE(node) ((coap_resource_t *)(node)->data)
+#define COAP_SUBSCRIPTION(node) ((coap_subscription_t *)(node)->data)
+
+/** Checks subscribed resources for updates and notifies subscribers of changes. */
+void coap_check_resource_list(coap_context_t *context);
+
+/** Removes expired subscriptions. */
+void coap_check_subscriptions(coap_context_t *context);
+
+#if 0
+/**
+ * Adds specified resource to the resource observation list. Returns a
+ * unique key for the resource. The alloceted memory is released when
+ * the resource is destroyed with coap_delete_resource().
+ */
+coap_key_t coap_add_resource(coap_context_t *context, coap_resource_t *);
+
+/**
+ * Deletes the resource that is identified by key. Returns 1 if the resource was
+ * removed, 0 on error (e.g. if no such resource exists).
+ */
+int coap_delete_resource(coap_context_t *context, coap_key_t key);
+#endif
+/**
+ * Creates a new subscription object filled with the given data. The storage
+ * allocated for this object must be released using coap_free(). */
+coap_subscription_t *coap_new_subscription(coap_context_t *context,
+ const coap_uri_t *resource,
+ const struct sockaddr *subscriber,
+ socklen_t addrlen,
+ time_t expiry);
+
+/**
+ * Adds the given subsription object to the observer list.
+ * @param context The CoAP context
+ * @param subscription A new subscription oobject created with coap_new_subscription()
+ * @return A unique hash key for this resource or COAP_INVALID_HASHKEY on error.
+ * The storage allocated for the subscription object is released when it is
+ * removed from the subscription list, unless the function has returned
+ * COAP_INVALID_HASHKEY. In this case, the storage must be released by the
+ * caller of this function.
+*/
+coap_key_t coap_add_subscription(coap_context_t *context,
+ coap_subscription_t *subscription);
+
+/**
+ * Returns the subscription from subscriber for the resource identified
+ * by hashkey. When token is not NULL the subscription must have the
+ * same token.
+ * @param context The CoAP context
+ * @param hashkey The unique key that identifies the subscription
+ * @param subscriber The subscriber's transport address
+ * @param token If not NULL, this specifies a token given by the
+ * subscriber to identify its subscription.
+ * @return The requested subscription object or NULL when not found.
+ */
+coap_subscription_t * coap_find_subscription(coap_context_t *context,
+ coap_key_t hashkey,
+ struct sockaddr *subscriber,
+ str *token);
+/**
+ * Removes a subscription from the subscription list stored in context and
+ * releases the storage that was allocated for this subscription.
+ * @param context The CoAP context.
+ * @param haskey The unique key that identifies the subscription to remove.
+ * @return 1 if a subscription was removed, 0 otherwise.
+ */
+int coap_delete_subscription(coap_context_t *context,
+ coap_key_t hashkey,
+ struct sockaddr *subscriber);
+
+/** Returns a unique hash for the specified URI or COAP_INVALID_HASHKEY on error. */
+coap_key_t coap_uri_hash(const coap_uri_t *uri);
+
+
+/** Returns a unique hash for the specified subscription or COAP_INVALID_HASHKEY on error. */
+coap_key_t coap_subscription_hash(coap_subscription_t *subscription);
+#if 0
+/** Returns the resource identified by key or NULL if not found. */
+coap_resource_t *coap_get_resource_from_key(coap_context_t *ctx, coap_key_t key);
+
+/** Returns the resource identified by uri or NULL if not found. */
+coap_resource_t *coap_get_resource(coap_context_t *ctx, coap_uri_t *uri);
+#endif
+
+#endif
+
+/** @} */
+
+#endif /* _COAP_SUBSCRIBE_H_ */
--- /dev/null
+/* t_list -- tinydtls lists
+ *
+ * Copyright (C) 2012 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * 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.
+ */
+
+/**
+ * @file t_list.h
+ * @brief Wrappers for list structures and functions
+ */
+
+#ifndef _DTLS_LIST_H_
+#define _DTLS_LIST_H_
+
+#ifndef WITH_CONTIKI
+#include "uthash.h"
+#include "utlist.h"
+
+/* We define list structures and utility functions to be compatible
+ * with Contiki list structures. The Contiki list API is part of the
+ * Contiki operating system, and therefore the following licensing
+ * terms apply (taken from contiki/core/lib/list.h):
+ *
+ * Copyright (c) 2004, Swedish Institute of Computer Science.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the Institute nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * This file is part of the Contiki operating system.
+ *
+ * Author: Adam Dunkels <adam@sics.se>
+ *
+ * $ Id: list.h,v 1.5 2010/09/13 13:31:00 adamdunkels Exp $
+ */
+
+typedef void **list_t;
+struct list {
+ struct list *next;
+};
+
+#define LIST_CONCAT(s1, s2) s1##s2
+
+#define LIST_STRUCT(name) \
+ void *LIST_CONCAT(name, _list); \
+ list_t name
+
+#define LIST_STRUCT_INIT(struct_ptr, name) { \
+ (struct_ptr)->name = &((struct_ptr)->LIST_CONCAT(name,_list)); \
+ (struct_ptr)->LIST_CONCAT(name,_list) = NULL; \
+ }
+
+static inline void *
+list_head(list_t the_list) {
+ return *the_list;
+}
+
+static inline void
+list_remove(list_t the_list, void *item) {
+ if (list_head(the_list))
+ LL_DELETE(*(struct list **)the_list, (struct list *)item);
+}
+
+static inline void
+list_add(list_t the_list, void *item) {
+ list_remove(the_list, item);
+ LL_APPEND(*(struct list **)the_list, (struct list *)item);
+}
+
+static inline void
+list_push(list_t the_list, void *item) {
+ LL_PREPEND(*(struct list **)the_list, (struct list *)item);
+}
+
+static inline void *
+list_pop(list_t the_list) {
+ struct list *l;
+ l = (struct list*)*the_list;
+ if(l)
+ list_remove(the_list, l);
+
+ return l;
+}
+
+static inline void
+list_insert(list_t the_list, void *previtem, void *newitem) {
+ if(previtem == NULL) {
+ list_push(the_list, newitem);
+ } else {
+ ((struct list *)newitem)->next = ((struct list *)previtem)->next;
+ ((struct list *)previtem)->next = (struct list*)newitem;
+ }
+}
+
+static inline void *
+list_item_next(void *item)
+{
+ return item == NULL? NULL: ((struct list *)item)->next;
+}
+
+#else /* WITH_CONTIKI */
+#include "list.h"
+#endif /* WITH_CONTIKI */
+
+#endif /* _DTLS_LIST_H_ */
+
--- /dev/null
+/* uri.c -- helper functions for URI treatment
+ *
+ * Copyright (C) 2010--2012 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#include "config.h"
+
+#if defined(HAVE_ASSERT_H) && !defined(assert)
+# include <assert.h>
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "mem.h"
+#include "debug.h"
+#include "pdu.h"
+#include "option.h"
+#include "uri.h"
+
+/**
+ * A length-safe version of strchr(). This function returns a pointer
+ * to the first occurrence of @p c in @p s, or @c NULL if not found.
+ *
+ * @param s The string to search for @p c.
+ * @param len The length of @p s.
+ * @param c The character to search.
+ *
+ * @return A pointer to the first occurence of @p c, or @c NULL
+ * if not found.
+ */
+static inline unsigned char *
+strnchr(unsigned char *s, size_t len, unsigned char c) {
+ while (len && *s++ != c)
+ --len;
+
+ return len ? s : NULL;
+}
+
+int
+coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri) {
+ unsigned char *p, *q;
+ int secure = 0, res = 0;
+
+ if (!str_var || !uri)
+ return -1;
+
+ memset(uri, 0, sizeof(coap_uri_t));
+ uri->port = COAP_DEFAULT_PORT;
+
+ /* search for scheme */
+ p = str_var;
+ if (*p == '/') {
+ q = p;
+ goto path;
+ }
+
+ q = (unsigned char *)COAP_DEFAULT_SCHEME;
+ while (len && *q && tolower(*p) == *q) {
+ ++p; ++q; --len;
+ }
+
+ /* If q does not point to the string end marker '\0', the schema
+ * identifier is wrong. */
+ if (*q) {
+ res = -1;
+ goto error;
+ }
+
+ /* There might be an additional 's', indicating the secure version: */
+ if (len && (secure = tolower(*p) == 's')) {
+ ++p; --len;
+ }
+
+ q = (unsigned char *)"://";
+ while (len && *q && tolower(*p) == *q) {
+ ++p; ++q; --len;
+ }
+
+ if (*q) {
+ res = -2;
+ goto error;
+ }
+
+ /* p points to beginning of Uri-Host */
+ q = p;
+ if (len && *p == '[') { /* IPv6 address reference */
+ ++p;
+
+ while (len && *q != ']') {
+ ++q; --len;
+ }
+
+ if (!len || *q != ']' || p == q) {
+ res = -3;
+ goto error;
+ }
+
+ COAP_SET_STR(&uri->host, q - p, p);
+ ++q; --len;
+ } else { /* IPv4 address or FQDN */
+ while (len && *q != ':' && *q != '/' && *q != '?') {
+ *q = tolower(*q);
+ ++q;
+ --len;
+ }
+
+ if (p == q) {
+ res = -3;
+ goto error;
+ }
+
+ COAP_SET_STR(&uri->host, q - p, p);
+ }
+
+ /* check for Uri-Port */
+ if (len && *q == ':') {
+ p = ++q;
+ --len;
+
+ while (len && isdigit(*q)) {
+ ++q;
+ --len;
+ }
+
+ if (p < q) { /* explicit port number given */
+ int uri_port = 0;
+
+ while (p < q)
+ uri_port = uri_port * 10 + (*p++ - '0');
+
+ uri->port = uri_port;
+ }
+ }
+
+ path: /* at this point, p must point to an absolute path */
+
+ if (!len)
+ goto end;
+
+ if (*q == '/') {
+ p = ++q;
+ --len;
+
+ while (len && *q != '?') {
+ ++q;
+ --len;
+ }
+
+ if (p < q) {
+ COAP_SET_STR(&uri->path, q - p, p);
+ p = q;
+ }
+ }
+
+ /* Uri_Query */
+ if (len && *p == '?') {
+ ++p;
+ --len;
+ COAP_SET_STR(&uri->query, len, p);
+ len = 0;
+ }
+
+ end:
+ return len ? -1 : 0;
+
+ error:
+ return res;
+}
+
+/**
+ * Calculates decimal value from hexadecimal ASCII character given in
+ * @p c. The caller must ensure that @p c actually represents a valid
+ * heaxdecimal character, e.g. with isxdigit(3).
+ *
+ * @hideinitializer
+ */
+#define hexchar_to_dec(c) ((c) & 0x40 ? ((c) & 0x0F) + 9 : ((c) & 0x0F))
+
+/**
+ * Decodes percent-encoded characters while copying the string @p seg
+ * of size @p length to @p buf. The caller of this function must
+ * ensure that the percent-encodings are correct (i.e. the character
+ * '%' is always followed by two hex digits. and that @p buf provides
+ * sufficient space to hold the result. This function is supposed to
+ * be called by make_decoded_option() only.
+ *
+ * @param seg The segment to decode and copy.
+ * @param length Length of @p seg.
+ * @param buf The result buffer.
+ */
+void
+decode_segment(const unsigned char *seg, size_t length, unsigned char *buf) {
+
+ while (length--) {
+
+ if (*seg == '%') {
+ *buf = (hexchar_to_dec(seg[1]) << 4) + hexchar_to_dec(seg[2]);
+
+ seg += 2; length -= 2;
+ } else {
+ *buf = *seg;
+ }
+
+ ++buf; ++seg;
+ }
+}
+
+/**
+ * Runs through the given path (or query) segment and checks if
+ * percent-encodings are correct. This function returns @c -1 on error
+ * or the length of @p s when decoded.
+ */
+int
+check_segment(const unsigned char *s, size_t length) {
+
+ size_t n = 0;
+
+ while (length) {
+ if (*s == '%') {
+ if (length < 2 || !(isxdigit(s[1]) && isxdigit(s[2])))
+ return -1;
+
+ s += 2;
+ length -= 2;
+ }
+
+ ++s; ++n; --length;
+ }
+
+ return n;
+}
+
+/**
+ * Writes a coap option from given string @p s to @p buf. @p s should
+ * point to a (percent-encoded) path or query segment of a coap_uri_t
+ * object. The created option will have type @c 0, and the length
+ * parameter will be set according to the size of the decoded string.
+ * On success, this function returns the option's size, or a value
+ * less than zero on error. This function must be called from
+ * coap_split_path_impl() only.
+ *
+ * @param s The string to decode.
+ * @param length The size of the percent-encoded string @p s.
+ * @param buf The buffer to store the new coap option.
+ * @param buflen The maximum size of @p buf.
+ *
+ * @return The option's size, or @c -1 on error.
+ *
+ * @bug This function does not split segments that are bigger than 270
+ * bytes.
+ */
+int
+make_decoded_option(const unsigned char *s, size_t length,
+ unsigned char *buf, size_t buflen) {
+ int res;
+ size_t written;
+
+ if (!buflen) {
+ debug("make_decoded_option(): buflen is 0!\n");
+ return -1;
+ }
+
+ res = check_segment(s, length);
+ if (res < 0)
+ return -1;
+
+ /* write option header using delta 0 and length res */
+ written = coap_opt_setheader(buf, buflen, 0, res);
+
+ assert(written <= buflen);
+
+ if (!written) /* encoding error */
+ return -1;
+
+ buf += written; /* advance past option type/length */
+ buflen -= written;
+
+ if (buflen < (size_t)res) {
+ debug("buffer too small for option\n");
+ return -1;
+ }
+
+ decode_segment(s, length, buf);
+
+ return written + res;
+}
+
+
+#ifndef min
+#define min(a,b) ((a) < (b) ? (a) : (b))
+#endif
+
+typedef void (*segment_handler_t)(unsigned char *, size_t, void *);
+
+/**
+ * Splits the given string into segments. You should call one of the
+ * macros coap_split_path() or coap_split_query() instead.
+ *
+ * @param parse_iter The iterator used for tokenizing.
+ * @param h A handler that is called with every token.
+ * @param data Opaque data that is passed to @p h when called.
+ *
+ * @return The number of characters that have been parsed from @p s.
+ */
+size_t
+coap_split_path_impl(coap_parse_iterator_t *parse_iter,
+ segment_handler_t h, void *data) {
+ unsigned char *seg;
+ size_t length;
+
+ assert(parse_iter);
+ assert(h);
+
+ length = parse_iter->n;
+
+ while ( (seg = coap_parse_next(parse_iter)) ) {
+
+ /* any valid path segment is handled here: */
+ h(seg, parse_iter->segment_length, data);
+ }
+
+ return length - (parse_iter->n - parse_iter->segment_length);
+}
+
+struct cnt_str {
+ str buf;
+ int n;
+};
+
+void
+write_option(unsigned char *s, size_t len, void *data) {
+ struct cnt_str *state = (struct cnt_str *)data;
+ int res;
+ assert(state);
+
+ /* skip empty segments and those that consist of only one or two dots */
+ if (memcmp(s, "..", min(len,2)) == 0)
+ return;
+
+ res = make_decoded_option(s, len, state->buf.s, state->buf.length);
+ if (res > 0) {
+ state->buf.s += res;
+ state->buf.length -= res;
+ state->n++;
+ }
+}
+
+int
+coap_split_path(const unsigned char *s, size_t length,
+ unsigned char *buf, size_t *buflen) {
+ struct cnt_str tmp = { { *buflen, buf }, 0 };
+ coap_parse_iterator_t pi;
+
+ coap_parse_iterator_init((unsigned char *)s, length,
+ '/', (unsigned char *)"?#", 2, &pi);
+ coap_split_path_impl(&pi, write_option, &tmp);
+
+ *buflen = *buflen - tmp.buf.length;
+ return tmp.n;
+}
+
+int
+coap_split_query(const unsigned char *s, size_t length,
+ unsigned char *buf, size_t *buflen) {
+ struct cnt_str tmp = { { *buflen, buf }, 0 };
+ coap_parse_iterator_t pi;
+
+ coap_parse_iterator_init((unsigned char *)s, length,
+ '&', (unsigned char *)"#", 1, &pi);
+
+ coap_split_path_impl(&pi, write_option, &tmp);
+
+ *buflen = tmp.buf.length;
+ return tmp.n;
+}
+
+#define URI_DATA(uriobj) ((unsigned char *)(uriobj) + sizeof(coap_uri_t))
+
+coap_uri_t *
+coap_new_uri(const unsigned char *uri, unsigned int length) {
+ unsigned char *result;
+
+ result = (unsigned char*)coap_malloc(length + 1 + sizeof(coap_uri_t));
+
+ if (!result)
+ return NULL;
+
+ memcpy(URI_DATA(result), uri, length);
+ URI_DATA(result)[length] = '\0'; /* make it zero-terminated */
+
+ if (coap_split_uri(URI_DATA(result), length, (coap_uri_t *)result) < 0) {
+ free(result);
+ return NULL;
+ }
+ return (coap_uri_t *)result;
+}
+
+coap_uri_t *
+coap_clone_uri(const coap_uri_t *uri) {
+ coap_uri_t *result;
+
+ if ( !uri )
+ return NULL;
+
+ result = (coap_uri_t *)coap_malloc( uri->query.length + uri->host.length +
+ uri->path.length + sizeof(coap_uri_t) + 1);
+
+ if ( !result )
+ return NULL;
+
+ memset( result, 0, sizeof(coap_uri_t) );
+
+ result->port = uri->port;
+
+ if ( uri->host.length ) {
+ result->host.s = URI_DATA(result);
+ result->host.length = uri->host.length;
+
+ memcpy(result->host.s, uri->host.s, uri->host.length);
+ }
+
+ if ( uri->path.length ) {
+ result->path.s = URI_DATA(result) + uri->host.length;
+ result->path.length = uri->path.length;
+
+ memcpy(result->path.s, uri->path.s, uri->path.length);
+ }
+
+ if ( uri->query.length ) {
+ result->query.s = URI_DATA(result) + uri->host.length + uri->path.length;
+ result->query.length = uri->query.length;
+
+ memcpy(result->query.s, uri->query.s, uri->query.length);
+ }
+
+ return result;
+}
+
+/* hash URI path segments */
+
+/* The function signature of coap_hash() is different from
+ * segment_handler_t hence we use this wrapper as safe typecast. */
+static inline void
+hash_segment(unsigned char *s, size_t len, void *data) {
+ coap_hash(s, len, (unsigned char*)data);
+}
+
+int
+coap_hash_path(const unsigned char *path, size_t len, coap_key_t key) {
+ coap_parse_iterator_t pi;
+
+ if (!path)
+ return 0;
+
+ memset(key, 0, sizeof(coap_key_t));
+
+ coap_parse_iterator_init((unsigned char *)path, len,
+ '/', (unsigned char *)"?#", 2, &pi);
+ coap_split_path_impl(&pi, hash_segment, key);
+
+ return 1;
+}
+
+/* iterator functions */
+
+coap_parse_iterator_t *
+coap_parse_iterator_init(unsigned char *s, size_t n,
+ unsigned char separator,
+ unsigned char *delim, size_t dlen,
+ coap_parse_iterator_t *pi) {
+ assert(pi);
+ assert(separator);
+
+ pi->separator = separator;
+ pi->delim = delim;
+ pi->dlen = dlen;
+ pi->pos = s;
+ pi->n = n;
+ pi->segment_length = 0;
+
+ return pi;
+}
+
+unsigned char *
+coap_parse_next(coap_parse_iterator_t *pi) {
+ unsigned char *p;
+
+ if (!pi)
+ return NULL;
+
+ /* proceed to the next segment */
+ pi->n -= pi->segment_length;
+ pi->pos += pi->segment_length;
+ pi->segment_length = 0;
+
+ /* last segment? */
+ if (!pi->n || strnchr(pi->delim, pi->dlen, *pi->pos)) {
+ pi->pos = NULL;
+ return NULL;
+ }
+
+ /* skip following separator (the first segment might not have one) */
+ if (*pi->pos == pi->separator) {
+ ++pi->pos;
+ --pi->n;
+ }
+
+ p = pi->pos;
+
+ while (pi->segment_length < pi->n && *p != pi->separator &&
+ !strnchr(pi->delim, pi->dlen, *p)) {
+ ++p;
+ ++pi->segment_length;
+ }
+
+ if (!pi->n) {
+ pi->pos = NULL;
+ pi->segment_length = 0;
+ }
+
+ return pi->pos;
+}
+
--- /dev/null
+/* uri.h -- helper functions for URI treatment
+ *
+ * Copyright (C) 2010,2011 Olaf Bergmann <bergmann@tzi.org>
+ *
+ * This file is part of the CoAP library libcoap. Please see
+ * README for terms of use.
+ */
+
+#ifndef _COAP_URI_H_
+#define _COAP_URI_H_
+
+#include "hashkey.h"
+#include "str.h"
+
+/** Representation of parsed URI. Components may be filled from a
+ * string with coap_split_uri() and can be used as input for
+ * option-creation functions. */
+typedef struct {
+ str host; /**< host part of the URI */
+ unsigned short port; /**< The port in host byte order */
+ str path; /**< Beginning of the first path segment.
+ Use coap_split_path() to create Uri-Path options */
+ str query; /**< The query part if present */
+} coap_uri_t;
+
+/**
+ * Creates a new coap_uri_t object from the specified URI. Returns the new
+ * object or NULL on error. The memory allocated by the new coap_uri_t
+ * must be released using coap_free().
+ * @param uri The URI path to copy.
+ * @para length The length of uri.
+ *
+ * @return New URI object or NULL on error.
+ */
+coap_uri_t *coap_new_uri(const unsigned char *uri, unsigned int length);
+
+/**
+ * Clones the specified coap_uri_t object. Thie function allocates sufficient
+ * memory to hold the coap_uri_t structure and its contents. The object must
+ * be released with coap_free(). */
+coap_uri_t *coap_clone_uri(const coap_uri_t *uri);
+
+/**
+ * Calculates a hash over the given path and stores the result in
+ * @p key. This function returns @c 0 on error or @c 1 on success.
+ *
+ * @param path The URI path to generate hash for.
+ * @param len The length of @p path.
+ * @param key The output buffer.
+ *
+ * @return @c 1 if @p key was set, @c 0 otherwise.
+ */
+int coap_hash_path(const unsigned char *path, size_t len, coap_key_t key);
+
+/**
+ * @defgroup uri_parse URI Parsing Functions
+ *
+ * CoAP PDUs contain normalized URIs with their path and query split into
+ * multiple segments. The functions in this module help splitting strings.
+ * @{
+ */
+
+/**
+ * Iterator to for tokenizing a URI path or query. This structure must
+ * be initialized with coap_parse_iterator_init(). Call
+ * coap_parse_next() to walk through the tokens.
+ *
+ * @code
+ * unsigned char *token;
+ * coap_parse_iterator_t pi;
+ * coap_parse_iterator_init(uri.path.s, uri.path.length, '/', "?#", 2, &pi);
+ *
+ * while ((token = coap_parse_next(&pi))) {
+ * ... do something with token ...
+ * }
+ * @endcode
+ */
+typedef struct {
+ size_t n; /**< number of remaining characters in buffer */
+ unsigned char separator; /**< segment separators */
+ unsigned char *delim; /**< delimiters where to split the string */
+ size_t dlen; /**< length of separator */
+ unsigned char *pos; /**< current position in buffer */
+ size_t segment_length; /**< length of current segment */
+} coap_parse_iterator_t;
+
+/**
+ * Initializes the given iterator @p pi.
+ *
+ * @param s The string to tokenize.
+ * @param n The length of @p s.
+ * @param separator The separator character that delimits tokens.
+ * @param delim A set of characters that delimit @s.
+ * @param dlen The length of @p delim.
+ * @param pi The iterator object to initialize.
+ *
+ * @return The initialized iterator object @p pi.
+ */
+coap_parse_iterator_t *
+coap_parse_iterator_init(unsigned char *s, size_t n,
+ unsigned char separator,
+ unsigned char *delim, size_t dlen,
+ coap_parse_iterator_t *pi);
+
+/**
+ * Updates the iterator @p pi to point to the next token. This
+ * function returns a pointer to that token or @c NULL if no more
+ * tokens exist. The contents of @p pi will be updated. In particular,
+ * @c pi->segment_length specifies the length of the current token, @c
+ * pi->pos points to its beginning.
+ *
+ * @param pi The iterator to update.
+ *
+ * @return The next token or @c NULL if no more tokens exist.
+ */
+unsigned char *coap_parse_next(coap_parse_iterator_t *pi);
+
+/**
+ * Parses a given string into URI components. The identified syntactic
+ * components are stored in the result parameter @p uri. Optional URI
+ * components that are not specified will be set to { 0, 0 }, except
+ * for the port which is set to @c COAP_DEFAULT_PORT. This function
+ * returns @p 0 if parsing succeeded, a value less than zero
+ * otherwise.
+ *
+ * @param str_var The string to split up.
+ * @param len The actual length of @p str_var
+ * @param uri The coap_uri_t object to store the result.
+ * @return @c 0 on success, or < 0 on error.
+ *
+ * @note The host name part will be converted to lower case by this
+ * function.
+ */
+int
+coap_split_uri(unsigned char *str_var, size_t len, coap_uri_t *uri);
+
+/**
+ * Splits the given URI path into segments. Each segment is preceded
+ * by an option pseudo-header with delta-value 0 and the actual length
+ * of the respective segment after percent-decoding.
+ *
+ * @param s The path string to split.
+ * @param length The actual length of @p s.
+ * @param buf Result buffer for parsed segments.
+ * @param buflen Maximum length of @p buf. Will be set to the actual number
+ * of bytes written into buf on success.
+ *
+ * @return The number of segments created or @c -1 on error.
+ */
+int coap_split_path(const unsigned char *s, size_t length,
+ unsigned char *buf, size_t *buflen);
+
+/**
+ * Splits the given URI query into segments. Each segment is preceded
+ * by an option pseudo-header with delta-value 0 and the actual length
+ * of the respective query term.
+ *
+ * @param s The query string to split.
+ * @param length The actual length of @p s.
+ * @param buf Result buffer for parsed segments.
+ * @param buflen Maximum length of @p buf. Will be set to the actual number
+ * of bytes written into buf on success.
+ *
+ * @return The number of segments created or @c -1 on error.
+ *
+ * @bug This function does not reserve additional space for delta > 12.
+ */
+int coap_split_query(const unsigned char *s, size_t length,
+ unsigned char *buf, size_t *buflen);
+
+/** @} */
+
+#endif /* _COAP_URI_H_ */
--- /dev/null
+/*
+Copyright (c) 2003-2010, Troy D. Hanson http://uthash.sourceforge.net
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef UTHASH_H
+#define UTHASH_H
+
+#include <string.h> /* memcmp,strlen */
+#include <stddef.h> /* ptrdiff_t */
+
+/* These macros use decltype or the earlier __typeof GNU extension.
+ As decltype is only available in newer compilers (VS2010 or gcc 4.3+
+ when compiling c++ source) this code uses whatever method is needed
+ or, for VS2008 where neither is available, uses casting workarounds. */
+#ifdef _MSC_VER /* MS compiler */
+#if _MSC_VER >= 1600 && defined(__cplusplus) /* VS2010 or newer in C++ mode */
+#define DECLTYPE(x) (decltype(x))
+#else /* VS2008 or older (or VS2010 in C mode) */
+#define NO_DECLTYPE
+#define DECLTYPE(x)
+#endif
+#else /* GNU, Sun and other compilers */
+#define DECLTYPE(x) (__typeof(x))
+#endif
+
+#ifdef NO_DECLTYPE
+#define DECLTYPE_ASSIGN(dst,src) \
+do { \
+ char **_da_dst = (char**)(&(dst)); \
+ *_da_dst = (char*)(src); \
+} while(0)
+#else
+#define DECLTYPE_ASSIGN(dst,src) \
+do { \
+ (dst) = DECLTYPE(dst)(src); \
+} while(0)
+#endif
+
+/* a number of the hash function use uint32_t which isn't defined on win32 */
+#ifdef _MSC_VER
+typedef unsigned int uint32_t;
+#else
+#include <inttypes.h> /* uint32_t */
+#endif
+
+#define UTHASH_VERSION 1.9.3
+
+#ifndef uthash_fatal
+#define uthash_fatal(msg) exit(-1) /* fatal error (out of memory,etc) */
+#endif
+#define uthash_malloc(sz) malloc(sz) /* malloc fcn */
+#define uthash_free(ptr,sz) free(ptr) /* free fcn */
+
+#define uthash_noexpand_fyi(tbl) /* can be defined to log noexpand */
+#define uthash_expand_fyi(tbl) /* can be defined to log expands */
+
+/* initial number of buckets */
+#define HASH_INITIAL_NUM_BUCKETS 32 /* initial number of buckets */
+#define HASH_INITIAL_NUM_BUCKETS_LOG2 5 /* lg2 of initial number of buckets */
+#define HASH_BKT_CAPACITY_THRESH 10 /* expand when bucket count reaches */
+
+/* calculate the element whose hash handle address is hhe */
+#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
+
+#define HASH_FIND(hh,head,keyptr,keylen,out) \
+do { \
+ unsigned _hf_bkt,_hf_hashv; \
+ out=NULL; \
+ if (head) { \
+ HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt); \
+ if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) { \
+ HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ], \
+ keyptr,keylen,out); \
+ } \
+ } \
+} while (0)
+
+#ifdef HASH_BLOOM
+#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
+#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
+#define HASH_BLOOM_MAKE(tbl) \
+do { \
+ (tbl)->bloom_nbits = HASH_BLOOM; \
+ (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN); \
+ if (!((tbl)->bloom_bv)) { uthash_fatal( "out of memory"); } \
+ memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN); \
+ (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE; \
+} while (0);
+
+#define HASH_BLOOM_FREE(tbl) \
+do { \
+ uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN); \
+} while (0);
+
+#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
+#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
+
+#define HASH_BLOOM_ADD(tbl,hashv) \
+ HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
+
+#define HASH_BLOOM_TEST(tbl,hashv) \
+ HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
+
+#else
+#define HASH_BLOOM_MAKE(tbl)
+#define HASH_BLOOM_FREE(tbl)
+#define HASH_BLOOM_ADD(tbl,hashv)
+#define HASH_BLOOM_TEST(tbl,hashv) (1)
+#endif
+
+#define HASH_MAKE_TABLE(hh,head) \
+do { \
+ (head)->hh.tbl = (UT_hash_table*)uthash_malloc( \
+ sizeof(UT_hash_table)); \
+ if (!((head)->hh.tbl)) { uthash_fatal( "out of memory"); } \
+ memset((head)->hh.tbl, 0, sizeof(UT_hash_table)); \
+ (head)->hh.tbl->tail = &((head)->hh); \
+ (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS; \
+ (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2; \
+ (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head); \
+ (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc( \
+ HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
+ if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); } \
+ memset((head)->hh.tbl->buckets, 0, \
+ HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket)); \
+ HASH_BLOOM_MAKE((head)->hh.tbl); \
+ (head)->hh.tbl->signature = HASH_SIGNATURE; \
+} while(0)
+
+#define HASH_ADD(hh,head,fieldname,keylen_in,add) \
+ HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
+
+#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add) \
+do { \
+ unsigned _ha_bkt; \
+ (add)->hh.next = NULL; \
+ (add)->hh.key = (char*)keyptr; \
+ (add)->hh.keylen = keylen_in; \
+ if (!(head)) { \
+ head = (add); \
+ (head)->hh.prev = NULL; \
+ HASH_MAKE_TABLE(hh,head); \
+ } else { \
+ (head)->hh.tbl->tail->next = (add); \
+ (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail); \
+ (head)->hh.tbl->tail = &((add)->hh); \
+ } \
+ (head)->hh.tbl->num_items++; \
+ (add)->hh.tbl = (head)->hh.tbl; \
+ HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets, \
+ (add)->hh.hashv, _ha_bkt); \
+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh); \
+ HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv); \
+ HASH_EMIT_KEY(hh,head,keyptr,keylen_in); \
+ HASH_FSCK(hh,head); \
+} while(0)
+
+#define HASH_TO_BKT( hashv, num_bkts, bkt ) \
+do { \
+ bkt = ((hashv) & ((num_bkts) - 1)); \
+} while(0)
+
+/* delete "delptr" from the hash table.
+ * "the usual" patch-up process for the app-order doubly-linked-list.
+ * The use of _hd_hh_del below deserves special explanation.
+ * These used to be expressed using (delptr) but that led to a bug
+ * if someone used the same symbol for the head and deletee, like
+ * HASH_DELETE(hh,users,users);
+ * We want that to work, but by changing the head (users) below
+ * we were forfeiting our ability to further refer to the deletee (users)
+ * in the patch-up process. Solution: use scratch space to
+ * copy the deletee pointer, then the latter references are via that
+ * scratch pointer rather than through the repointed (users) symbol.
+ */
+#define HASH_DELETE(hh,head,delptr) \
+do { \
+ unsigned _hd_bkt; \
+ struct UT_hash_handle *_hd_hh_del; \
+ if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) ) { \
+ uthash_free((head)->hh.tbl->buckets, \
+ (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
+ HASH_BLOOM_FREE((head)->hh.tbl); \
+ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
+ head = NULL; \
+ } else { \
+ _hd_hh_del = &((delptr)->hh); \
+ if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) { \
+ (head)->hh.tbl->tail = \
+ (UT_hash_handle*)((char*)((delptr)->hh.prev) + \
+ (head)->hh.tbl->hho); \
+ } \
+ if ((delptr)->hh.prev) { \
+ ((UT_hash_handle*)((char*)((delptr)->hh.prev) + \
+ (head)->hh.tbl->hho))->next = (delptr)->hh.next; \
+ } else { \
+ DECLTYPE_ASSIGN(head,(delptr)->hh.next); \
+ } \
+ if (_hd_hh_del->next) { \
+ ((UT_hash_handle*)((char*)_hd_hh_del->next + \
+ (head)->hh.tbl->hho))->prev = \
+ _hd_hh_del->prev; \
+ } \
+ HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt); \
+ HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del); \
+ (head)->hh.tbl->num_items--; \
+ } \
+ HASH_FSCK(hh,head); \
+} while (0)
+
+
+/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
+#define HASH_FIND_STR(head,findstr,out) \
+ HASH_FIND(hh,head,findstr,strlen(findstr),out)
+#define HASH_ADD_STR(head,strfield,add) \
+ HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
+#define HASH_FIND_INT(head,findint,out) \
+ HASH_FIND(hh,head,findint,sizeof(int),out)
+#define HASH_ADD_INT(head,intfield,add) \
+ HASH_ADD(hh,head,intfield,sizeof(int),add)
+#define HASH_FIND_PTR(head,findptr,out) \
+ HASH_FIND(hh,head,findptr,sizeof(void *),out)
+#define HASH_ADD_PTR(head,ptrfield,add) \
+ HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
+#define HASH_DEL(head,delptr) \
+ HASH_DELETE(hh,head,delptr)
+
+/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
+ * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
+ */
+#ifdef HASH_DEBUG
+#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
+#define HASH_FSCK(hh,head) \
+do { \
+ unsigned _bkt_i; \
+ unsigned _count, _bkt_count; \
+ char *_prev; \
+ struct UT_hash_handle *_thh; \
+ if (head) { \
+ _count = 0; \
+ for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) { \
+ _bkt_count = 0; \
+ _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head; \
+ _prev = NULL; \
+ while (_thh) { \
+ if (_prev != (char*)(_thh->hh_prev)) { \
+ HASH_OOPS("invalid hh_prev %p, actual %p\n", \
+ _thh->hh_prev, _prev ); \
+ } \
+ _bkt_count++; \
+ _prev = (char*)(_thh); \
+ _thh = _thh->hh_next; \
+ } \
+ _count += _bkt_count; \
+ if ((head)->hh.tbl->buckets[_bkt_i].count != _bkt_count) { \
+ HASH_OOPS("invalid bucket count %d, actual %d\n", \
+ (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count); \
+ } \
+ } \
+ if (_count != (head)->hh.tbl->num_items) { \
+ HASH_OOPS("invalid hh item count %d, actual %d\n", \
+ (head)->hh.tbl->num_items, _count ); \
+ } \
+ /* traverse hh in app order; check next/prev integrity, count */ \
+ _count = 0; \
+ _prev = NULL; \
+ _thh = &(head)->hh; \
+ while (_thh) { \
+ _count++; \
+ if (_prev !=(char*)(_thh->prev)) { \
+ HASH_OOPS("invalid prev %p, actual %p\n", \
+ _thh->prev, _prev ); \
+ } \
+ _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh); \
+ _thh = ( _thh->next ? (UT_hash_handle*)((char*)(_thh->next) + \
+ (head)->hh.tbl->hho) : NULL ); \
+ } \
+ if (_count != (head)->hh.tbl->num_items) { \
+ HASH_OOPS("invalid app item count %d, actual %d\n", \
+ (head)->hh.tbl->num_items, _count ); \
+ } \
+ } \
+} while (0)
+#else
+#define HASH_FSCK(hh,head)
+#endif
+
+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
+ * the descriptor to which this macro is defined for tuning the hash function.
+ * The app can #include <unistd.h> to get the prototype for write(2). */
+#ifdef HASH_EMIT_KEYS
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen) \
+do { \
+ unsigned _klen = fieldlen; \
+ write(HASH_EMIT_KEYS, &_klen, sizeof(_klen)); \
+ write(HASH_EMIT_KEYS, keyptr, fieldlen); \
+} while (0)
+#else
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
+#endif
+
+/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
+#ifdef HASH_FUNCTION
+#define HASH_FCN HASH_FUNCTION
+#else
+#define HASH_FCN HASH_JEN
+#endif
+
+/* The Bernstein hash function, used in Perl prior to v5.6 */
+#define HASH_BER(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ unsigned _hb_keylen=keylen; \
+ char *_hb_key=(char*)(key); \
+ (hashv) = 0; \
+ while (_hb_keylen--) { (hashv) = ((hashv) * 33) + *_hb_key++; } \
+ bkt = (hashv) & (num_bkts-1); \
+} while (0)
+
+
+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
+ * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
+#define HASH_SAX(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ unsigned _sx_i; \
+ char *_hs_key=(char*)(key); \
+ hashv = 0; \
+ for(_sx_i=0; _sx_i < keylen; _sx_i++) \
+ hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i]; \
+ bkt = hashv & (num_bkts-1); \
+} while (0)
+
+#define HASH_FNV(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ unsigned _fn_i; \
+ char *_hf_key=(char*)(key); \
+ hashv = 2166136261UL; \
+ for(_fn_i=0; _fn_i < keylen; _fn_i++) \
+ hashv = (hashv * 16777619) ^ _hf_key[_fn_i]; \
+ bkt = hashv & (num_bkts-1); \
+} while(0);
+
+#define HASH_OAT(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ unsigned _ho_i; \
+ char *_ho_key=(char*)(key); \
+ hashv = 0; \
+ for(_ho_i=0; _ho_i < keylen; _ho_i++) { \
+ hashv += _ho_key[_ho_i]; \
+ hashv += (hashv << 10); \
+ hashv ^= (hashv >> 6); \
+ } \
+ hashv += (hashv << 3); \
+ hashv ^= (hashv >> 11); \
+ hashv += (hashv << 15); \
+ bkt = hashv & (num_bkts-1); \
+} while(0)
+
+#define HASH_JEN_MIX(a,b,c) \
+do { \
+ a -= b; a -= c; a ^= ( c >> 13 ); \
+ b -= c; b -= a; b ^= ( a << 8 ); \
+ c -= a; c -= b; c ^= ( b >> 13 ); \
+ a -= b; a -= c; a ^= ( c >> 12 ); \
+ b -= c; b -= a; b ^= ( a << 16 ); \
+ c -= a; c -= b; c ^= ( b >> 5 ); \
+ a -= b; a -= c; a ^= ( c >> 3 ); \
+ b -= c; b -= a; b ^= ( a << 10 ); \
+ c -= a; c -= b; c ^= ( b >> 15 ); \
+} while (0)
+
+#define HASH_JEN(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ unsigned _hj_i,_hj_j,_hj_k; \
+ char *_hj_key=(char*)(key); \
+ hashv = 0xfeedbeef; \
+ _hj_i = _hj_j = 0x9e3779b9; \
+ _hj_k = keylen; \
+ while (_hj_k >= 12) { \
+ _hj_i += (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 ) \
+ + ( (unsigned)_hj_key[2] << 16 ) \
+ + ( (unsigned)_hj_key[3] << 24 ) ); \
+ _hj_j += (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 ) \
+ + ( (unsigned)_hj_key[6] << 16 ) \
+ + ( (unsigned)_hj_key[7] << 24 ) ); \
+ hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 ) \
+ + ( (unsigned)_hj_key[10] << 16 ) \
+ + ( (unsigned)_hj_key[11] << 24 ) ); \
+ \
+ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
+ \
+ _hj_key += 12; \
+ _hj_k -= 12; \
+ } \
+ hashv += keylen; \
+ switch ( _hj_k ) { \
+ case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \
+ case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \
+ case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \
+ case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \
+ case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \
+ case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \
+ case 5: _hj_j += _hj_key[4]; \
+ case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \
+ case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \
+ case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \
+ case 1: _hj_i += _hj_key[0]; \
+ } \
+ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \
+ bkt = hashv & (num_bkts-1); \
+} while(0)
+
+/* The Paul Hsieh hash function */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \
+ || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8) \
+ +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+#define HASH_SFH(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ char *_sfh_key=(char*)(key); \
+ uint32_t _sfh_tmp, _sfh_len = keylen; \
+ \
+ int _sfh_rem = _sfh_len & 3; \
+ _sfh_len >>= 2; \
+ hashv = 0xcafebabe; \
+ \
+ /* Main loop */ \
+ for (;_sfh_len > 0; _sfh_len--) { \
+ hashv += get16bits (_sfh_key); \
+ _sfh_tmp = (get16bits (_sfh_key+2) << 11) ^ hashv; \
+ hashv = (hashv << 16) ^ _sfh_tmp; \
+ _sfh_key += 2*sizeof (uint16_t); \
+ hashv += hashv >> 11; \
+ } \
+ \
+ /* Handle end cases */ \
+ switch (_sfh_rem) { \
+ case 3: hashv += get16bits (_sfh_key); \
+ hashv ^= hashv << 16; \
+ hashv ^= _sfh_key[sizeof (uint16_t)] << 18; \
+ hashv += hashv >> 11; \
+ break; \
+ case 2: hashv += get16bits (_sfh_key); \
+ hashv ^= hashv << 11; \
+ hashv += hashv >> 17; \
+ break; \
+ case 1: hashv += *_sfh_key; \
+ hashv ^= hashv << 10; \
+ hashv += hashv >> 1; \
+ } \
+ \
+ /* Force "avalanching" of final 127 bits */ \
+ hashv ^= hashv << 3; \
+ hashv += hashv >> 5; \
+ hashv ^= hashv << 4; \
+ hashv += hashv >> 17; \
+ hashv ^= hashv << 25; \
+ hashv += hashv >> 6; \
+ bkt = hashv & (num_bkts-1); \
+} while(0);
+
+#ifdef HASH_USING_NO_STRICT_ALIASING
+/* The MurmurHash exploits some CPU's (e.g. x86) tolerance for unaligned reads.
+ * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
+ * So MurmurHash comes in two versions, the faster unaligned one and the slower
+ * aligned one. We only use the faster one on CPU's where we know it's safe.
+ *
+ * Note the preprocessor built-in defines can be emitted using:
+ *
+ * gcc -m64 -dM -E - < /dev/null (on gcc)
+ * cc -## a.c (where a.c is a simple test file) (Sun Studio)
+ */
+#if (defined(__i386__) || defined(__x86_64__))
+#define HASH_MUR HASH_MUR_UNALIGNED
+#else
+#define HASH_MUR HASH_MUR_ALIGNED
+#endif
+
+/* Appleby's MurmurHash fast version for unaligned-tolerant archs like i386 */
+#define HASH_MUR_UNALIGNED(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ const unsigned int _mur_m = 0x5bd1e995; \
+ const int _mur_r = 24; \
+ hashv = 0xcafebabe ^ keylen; \
+ char *_mur_key = (char *)(key); \
+ uint32_t _mur_tmp, _mur_len = keylen; \
+ \
+ for (;_mur_len >= 4; _mur_len-=4) { \
+ _mur_tmp = *(uint32_t *)_mur_key; \
+ _mur_tmp *= _mur_m; \
+ _mur_tmp ^= _mur_tmp >> _mur_r; \
+ _mur_tmp *= _mur_m; \
+ hashv *= _mur_m; \
+ hashv ^= _mur_tmp; \
+ _mur_key += 4; \
+ } \
+ \
+ switch(_mur_len) \
+ { \
+ case 3: hashv ^= _mur_key[2] << 16; \
+ case 2: hashv ^= _mur_key[1] << 8; \
+ case 1: hashv ^= _mur_key[0]; \
+ hashv *= _mur_m; \
+ }; \
+ \
+ hashv ^= hashv >> 13; \
+ hashv *= _mur_m; \
+ hashv ^= hashv >> 15; \
+ \
+ bkt = hashv & (num_bkts-1); \
+} while(0)
+
+/* Appleby's MurmurHash version for alignment-sensitive archs like Sparc */
+#define HASH_MUR_ALIGNED(key,keylen,num_bkts,hashv,bkt) \
+do { \
+ const unsigned int _mur_m = 0x5bd1e995; \
+ const int _mur_r = 24; \
+ hashv = 0xcafebabe ^ (keylen); \
+ char *_mur_key = (char *)(key); \
+ uint32_t _mur_len = keylen; \
+ int _mur_align = (int)_mur_key & 3; \
+ \
+ if (_mur_align && (_mur_len >= 4)) { \
+ unsigned _mur_t = 0, _mur_d = 0; \
+ switch(_mur_align) { \
+ case 1: _mur_t |= _mur_key[2] << 16; \
+ case 2: _mur_t |= _mur_key[1] << 8; \
+ case 3: _mur_t |= _mur_key[0]; \
+ } \
+ _mur_t <<= (8 * _mur_align); \
+ _mur_key += 4-_mur_align; \
+ _mur_len -= 4-_mur_align; \
+ int _mur_sl = 8 * (4-_mur_align); \
+ int _mur_sr = 8 * _mur_align; \
+ \
+ for (;_mur_len >= 4; _mur_len-=4) { \
+ _mur_d = *(unsigned *)_mur_key; \
+ _mur_t = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
+ unsigned _mur_k = _mur_t; \
+ _mur_k *= _mur_m; \
+ _mur_k ^= _mur_k >> _mur_r; \
+ _mur_k *= _mur_m; \
+ hashv *= _mur_m; \
+ hashv ^= _mur_k; \
+ _mur_t = _mur_d; \
+ _mur_key += 4; \
+ } \
+ _mur_d = 0; \
+ if(_mur_len >= _mur_align) { \
+ switch(_mur_align) { \
+ case 3: _mur_d |= _mur_key[2] << 16; \
+ case 2: _mur_d |= _mur_key[1] << 8; \
+ case 1: _mur_d |= _mur_key[0]; \
+ } \
+ unsigned _mur_k = (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
+ _mur_k *= _mur_m; \
+ _mur_k ^= _mur_k >> _mur_r; \
+ _mur_k *= _mur_m; \
+ hashv *= _mur_m; \
+ hashv ^= _mur_k; \
+ _mur_k += _mur_align; \
+ _mur_len -= _mur_align; \
+ \
+ switch(_mur_len) \
+ { \
+ case 3: hashv ^= _mur_key[2] << 16; \
+ case 2: hashv ^= _mur_key[1] << 8; \
+ case 1: hashv ^= _mur_key[0]; \
+ hashv *= _mur_m; \
+ } \
+ } else { \
+ switch(_mur_len) \
+ { \
+ case 3: _mur_d ^= _mur_key[2] << 16; \
+ case 2: _mur_d ^= _mur_key[1] << 8; \
+ case 1: _mur_d ^= _mur_key[0]; \
+ case 0: hashv ^= (_mur_t >> _mur_sr) | (_mur_d << _mur_sl); \
+ hashv *= _mur_m; \
+ } \
+ } \
+ \
+ hashv ^= hashv >> 13; \
+ hashv *= _mur_m; \
+ hashv ^= hashv >> 15; \
+ } else { \
+ for (;_mur_len >= 4; _mur_len-=4) { \
+ unsigned _mur_k = *(unsigned*)_mur_key; \
+ _mur_k *= _mur_m; \
+ _mur_k ^= _mur_k >> _mur_r; \
+ _mur_k *= _mur_m; \
+ hashv *= _mur_m; \
+ hashv ^= _mur_k; \
+ _mur_key += 4; \
+ } \
+ switch(_mur_len) \
+ { \
+ case 3: hashv ^= _mur_key[2] << 16; \
+ case 2: hashv ^= _mur_key[1] << 8; \
+ case 1: hashv ^= _mur_key[0]; \
+ hashv *= _mur_m; \
+ } \
+ \
+ hashv ^= hashv >> 13; \
+ hashv *= _mur_m; \
+ hashv ^= hashv >> 15; \
+ } \
+ bkt = hashv & (num_bkts-1); \
+} while(0)
+#endif /* HASH_USING_NO_STRICT_ALIASING */
+
+/* key comparison function; return 0 if keys equal */
+#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
+
+/* iterate over items in a known bucket to find desired item */
+#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out) \
+do { \
+ if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head)); \
+ else out=NULL; \
+ while (out) { \
+ if (out->hh.keylen == keylen_in) { \
+ if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break; \
+ } \
+ if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \
+ else out = NULL; \
+ } \
+} while(0)
+
+/* add an item to a bucket */
+#define HASH_ADD_TO_BKT(head,addhh) \
+do { \
+ head.count++; \
+ (addhh)->hh_next = head.hh_head; \
+ (addhh)->hh_prev = NULL; \
+ if (head.hh_head) { (head).hh_head->hh_prev = (addhh); } \
+ (head).hh_head=addhh; \
+ if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH) \
+ && (addhh)->tbl->noexpand != 1) { \
+ HASH_EXPAND_BUCKETS((addhh)->tbl); \
+ } \
+} while(0)
+
+/* remove an item from a given bucket */
+#define HASH_DEL_IN_BKT(hh,head,hh_del) \
+ (head).count--; \
+ if ((head).hh_head == hh_del) { \
+ (head).hh_head = hh_del->hh_next; \
+ } \
+ if (hh_del->hh_prev) { \
+ hh_del->hh_prev->hh_next = hh_del->hh_next; \
+ } \
+ if (hh_del->hh_next) { \
+ hh_del->hh_next->hh_prev = hh_del->hh_prev; \
+ }
+
+/* Bucket expansion has the effect of doubling the number of buckets
+ * and redistributing the items into the new buckets. Ideally the
+ * items will distribute more or less evenly into the new buckets
+ * (the extent to which this is true is a measure of the quality of
+ * the hash function as it applies to the key domain).
+ *
+ * With the items distributed into more buckets, the chain length
+ * (item count) in each bucket is reduced. Thus by expanding buckets
+ * the hash keeps a bound on the chain length. This bounded chain
+ * length is the essence of how a hash provides constant time lookup.
+ *
+ * The calculation of tbl->ideal_chain_maxlen below deserves some
+ * explanation. First, keep in mind that we're calculating the ideal
+ * maximum chain length based on the *new* (doubled) bucket count.
+ * In fractions this is just n/b (n=number of items,b=new num buckets).
+ * Since the ideal chain length is an integer, we want to calculate
+ * ceil(n/b). We don't depend on floating point arithmetic in this
+ * hash, so to calculate ceil(n/b) with integers we could write
+ *
+ * ceil(n/b) = (n/b) + ((n%b)?1:0)
+ *
+ * and in fact a previous version of this hash did just that.
+ * But now we have improved things a bit by recognizing that b is
+ * always a power of two. We keep its base 2 log handy (call it lb),
+ * so now we can write this with a bit shift and logical AND:
+ *
+ * ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
+ *
+ */
+#define HASH_EXPAND_BUCKETS(tbl) \
+do { \
+ unsigned _he_bkt; \
+ unsigned _he_bkt_i; \
+ struct UT_hash_handle *_he_thh, *_he_hh_nxt; \
+ UT_hash_bucket *_he_new_buckets, *_he_newbkt; \
+ _he_new_buckets = (UT_hash_bucket*)uthash_malloc( \
+ 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
+ if (!_he_new_buckets) { uthash_fatal( "out of memory"); } \
+ memset(_he_new_buckets, 0, \
+ 2 * tbl->num_buckets * sizeof(struct UT_hash_bucket)); \
+ tbl->ideal_chain_maxlen = \
+ (tbl->num_items >> (tbl->log2_num_buckets+1)) + \
+ ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0); \
+ tbl->nonideal_items = 0; \
+ for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++) \
+ { \
+ _he_thh = tbl->buckets[ _he_bkt_i ].hh_head; \
+ while (_he_thh) { \
+ _he_hh_nxt = _he_thh->hh_next; \
+ HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt); \
+ _he_newbkt = &(_he_new_buckets[ _he_bkt ]); \
+ if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) { \
+ tbl->nonideal_items++; \
+ _he_newbkt->expand_mult = _he_newbkt->count / \
+ tbl->ideal_chain_maxlen; \
+ } \
+ _he_thh->hh_prev = NULL; \
+ _he_thh->hh_next = _he_newbkt->hh_head; \
+ if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev = \
+ _he_thh; \
+ _he_newbkt->hh_head = _he_thh; \
+ _he_thh = _he_hh_nxt; \
+ } \
+ } \
+ uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
+ tbl->num_buckets *= 2; \
+ tbl->log2_num_buckets++; \
+ tbl->buckets = _he_new_buckets; \
+ tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ? \
+ (tbl->ineff_expands+1) : 0; \
+ if (tbl->ineff_expands > 1) { \
+ tbl->noexpand=1; \
+ uthash_noexpand_fyi(tbl); \
+ } \
+ uthash_expand_fyi(tbl); \
+} while(0)
+
+
+/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
+/* Note that HASH_SORT assumes the hash handle name to be hh.
+ * HASH_SRT was added to allow the hash handle name to be passed in. */
+#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
+#define HASH_SRT(hh,head,cmpfcn) \
+do { \
+ unsigned _hs_i; \
+ unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize; \
+ struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail; \
+ if (head) { \
+ _hs_insize = 1; \
+ _hs_looping = 1; \
+ _hs_list = &((head)->hh); \
+ while (_hs_looping) { \
+ _hs_p = _hs_list; \
+ _hs_list = NULL; \
+ _hs_tail = NULL; \
+ _hs_nmerges = 0; \
+ while (_hs_p) { \
+ _hs_nmerges++; \
+ _hs_q = _hs_p; \
+ _hs_psize = 0; \
+ for ( _hs_i = 0; _hs_i < _hs_insize; _hs_i++ ) { \
+ _hs_psize++; \
+ _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
+ ((void*)((char*)(_hs_q->next) + \
+ (head)->hh.tbl->hho)) : NULL); \
+ if (! (_hs_q) ) break; \
+ } \
+ _hs_qsize = _hs_insize; \
+ while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) { \
+ if (_hs_psize == 0) { \
+ _hs_e = _hs_q; \
+ _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
+ ((void*)((char*)(_hs_q->next) + \
+ (head)->hh.tbl->hho)) : NULL); \
+ _hs_qsize--; \
+ } else if ( (_hs_qsize == 0) || !(_hs_q) ) { \
+ _hs_e = _hs_p; \
+ _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
+ ((void*)((char*)(_hs_p->next) + \
+ (head)->hh.tbl->hho)) : NULL); \
+ _hs_psize--; \
+ } else if (( \
+ cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
+ DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
+ ) <= 0) { \
+ _hs_e = _hs_p; \
+ _hs_p = (UT_hash_handle*)((_hs_p->next) ? \
+ ((void*)((char*)(_hs_p->next) + \
+ (head)->hh.tbl->hho)) : NULL); \
+ _hs_psize--; \
+ } else { \
+ _hs_e = _hs_q; \
+ _hs_q = (UT_hash_handle*)((_hs_q->next) ? \
+ ((void*)((char*)(_hs_q->next) + \
+ (head)->hh.tbl->hho)) : NULL); \
+ _hs_qsize--; \
+ } \
+ if ( _hs_tail ) { \
+ _hs_tail->next = ((_hs_e) ? \
+ ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL); \
+ } else { \
+ _hs_list = _hs_e; \
+ } \
+ _hs_e->prev = ((_hs_tail) ? \
+ ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL); \
+ _hs_tail = _hs_e; \
+ } \
+ _hs_p = _hs_q; \
+ } \
+ _hs_tail->next = NULL; \
+ if ( _hs_nmerges <= 1 ) { \
+ _hs_looping=0; \
+ (head)->hh.tbl->tail = _hs_tail; \
+ DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list)); \
+ } \
+ _hs_insize *= 2; \
+ } \
+ HASH_FSCK(hh,head); \
+ } \
+} while (0)
+
+/* This function selects items from one hash into another hash.
+ * The end result is that the selected items have dual presence
+ * in both hashes. There is no copy of the items made; rather
+ * they are added into the new hash through a secondary hash
+ * hash handle that must be present in the structure. */
+#define HASH_SELECT(hh_dst, dst, hh_src, src, cond) \
+do { \
+ unsigned _src_bkt, _dst_bkt; \
+ void *_last_elt=NULL, *_elt; \
+ UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL; \
+ ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst)); \
+ if (src) { \
+ for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) { \
+ for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head; \
+ _src_hh; \
+ _src_hh = _src_hh->hh_next) { \
+ _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh); \
+ if (cond(_elt)) { \
+ _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho); \
+ _dst_hh->key = _src_hh->key; \
+ _dst_hh->keylen = _src_hh->keylen; \
+ _dst_hh->hashv = _src_hh->hashv; \
+ _dst_hh->prev = _last_elt; \
+ _dst_hh->next = NULL; \
+ if (_last_elt_hh) { _last_elt_hh->next = _elt; } \
+ if (!dst) { \
+ DECLTYPE_ASSIGN(dst,_elt); \
+ HASH_MAKE_TABLE(hh_dst,dst); \
+ } else { \
+ _dst_hh->tbl = (dst)->hh_dst.tbl; \
+ } \
+ HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt); \
+ HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh); \
+ (dst)->hh_dst.tbl->num_items++; \
+ _last_elt = _elt; \
+ _last_elt_hh = _dst_hh; \
+ } \
+ } \
+ } \
+ } \
+ HASH_FSCK(hh_dst,dst); \
+} while (0)
+
+#define HASH_CLEAR(hh,head) \
+do { \
+ if (head) { \
+ uthash_free((head)->hh.tbl->buckets, \
+ (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket)); \
+ uthash_free((head)->hh.tbl, sizeof(UT_hash_table)); \
+ (head)=NULL; \
+ } \
+} while(0)
+
+#ifdef NO_DECLTYPE
+#define HASH_ITER(hh,head,el,tmp) \
+for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL); \
+ el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
+#else
+#define HASH_ITER(hh,head,el,tmp) \
+for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL); \
+ el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
+#endif
+
+/* obtain a count of items in the hash */
+#define HASH_COUNT(head) HASH_CNT(hh,head)
+#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
+
+typedef struct UT_hash_bucket {
+ struct UT_hash_handle *hh_head;
+ unsigned count;
+
+ /* expand_mult is normally set to 0. In this situation, the max chain length
+ * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
+ * the bucket's chain exceeds this length, bucket expansion is triggered).
+ * However, setting expand_mult to a non-zero value delays bucket expansion
+ * (that would be triggered by additions to this particular bucket)
+ * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
+ * (The multiplier is simply expand_mult+1). The whole idea of this
+ * multiplier is to reduce bucket expansions, since they are expensive, in
+ * situations where we know that a particular bucket tends to be overused.
+ * It is better to let its chain length grow to a longer yet-still-bounded
+ * value, than to do an O(n) bucket expansion too often.
+ */
+ unsigned expand_mult;
+
+} UT_hash_bucket;
+
+/* random signature used only to find hash tables in external analysis */
+#define HASH_SIGNATURE 0xa0111fe1
+#define HASH_BLOOM_SIGNATURE 0xb12220f2
+
+typedef struct UT_hash_table {
+ UT_hash_bucket *buckets;
+ unsigned num_buckets, log2_num_buckets;
+ unsigned num_items;
+ struct UT_hash_handle *tail; /* tail hh in app order, for fast append */
+ ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
+
+ /* in an ideal situation (all buckets used equally), no bucket would have
+ * more than ceil(#items/#buckets) items. that's the ideal chain length. */
+ unsigned ideal_chain_maxlen;
+
+ /* nonideal_items is the number of items in the hash whose chain position
+ * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
+ * hash distribution; reaching them in a chain traversal takes >ideal steps */
+ unsigned nonideal_items;
+
+ /* ineffective expands occur when a bucket doubling was performed, but
+ * afterward, more than half the items in the hash had nonideal chain
+ * positions. If this happens on two consecutive expansions we inhibit any
+ * further expansion, as it's not helping; this happens when the hash
+ * function isn't a good fit for the key domain. When expansion is inhibited
+ * the hash will still work, albeit no longer in constant time. */
+ unsigned ineff_expands, noexpand;
+
+ uint32_t signature; /* used only to find hash tables in external analysis */
+#ifdef HASH_BLOOM
+ uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
+ uint8_t *bloom_bv;
+ char bloom_nbits;
+#endif
+
+} UT_hash_table;
+
+typedef struct UT_hash_handle {
+ struct UT_hash_table *tbl;
+ void *prev; /* prev element in app order */
+ void *next; /* next element in app order */
+ struct UT_hash_handle *hh_prev; /* previous hh in bucket order */
+ struct UT_hash_handle *hh_next; /* next hh in bucket order */
+ void *key; /* ptr to enclosing struct's key */
+ unsigned keylen; /* enclosing struct's key len */
+ unsigned hashv; /* result of hash-fcn(key) */
+} UT_hash_handle;
+
+#endif /* UTHASH_H */
--- /dev/null
+/*
+Copyright (c) 2007-2010, Troy D. Hanson http://uthash.sourceforge.net
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
+IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
+TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
+PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER
+OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef UTLIST_H
+#define UTLIST_H
+
+#define UTLIST_VERSION 1.9.1
+
+/*
+ * This file contains macros to manipulate singly and doubly-linked lists.
+ *
+ * 1. LL_ macros: singly-linked lists.
+ * 2. DL_ macros: doubly-linked lists.
+ * 3. CDL_ macros: circular doubly-linked lists.
+ *
+ * To use singly-linked lists, your structure must have a "next" pointer.
+ * To use doubly-linked lists, your structure must "prev" and "next" pointers.
+ * Either way, the pointer to the head of the list must be initialized to NULL.
+ *
+ * ----------------.EXAMPLE -------------------------
+ * struct item {
+ * int id;
+ * struct item *prev, *next;
+ * }
+ *
+ * struct item *list = NULL:
+ *
+ * int main() {
+ * struct item *item;
+ * ... allocate and populate item ...
+ * DL_APPEND(list, item);
+ * }
+ * --------------------------------------------------
+ *
+ * For doubly-linked lists, the append and delete macros are O(1)
+ * For singly-linked lists, append and delete are O(n) but prepend is O(1)
+ * The sort macro is O(n log(n)) for all types of single/double/circular lists.
+ */
+
+/* These macros use decltype or the earlier __typeof GNU extension.
+ As decltype is only available in newer compilers (VS2010 or gcc 4.3+
+ when compiling c++ code), this code uses whatever method is needed
+ or, for VS2008 where neither is available, uses casting workarounds. */
+#ifdef _MSC_VER /* MS compiler */
+#if _MSC_VER >= 1600 && __cplusplus /* VS2010 and newer in C++ mode */
+#define LDECLTYPE(x) decltype(x)
+#else /* VS2008 or older (or VS2010 in C mode) */
+#define NO_DECLTYPE
+#define LDECLTYPE(x) char*
+#endif
+#else /* GNU, Sun and other compilers */
+#define LDECLTYPE(x) __typeof(x)
+#endif
+
+/* for VS2008 we use some workarounds to get around the lack of decltype,
+ * namely, we always reassign our tmp variable to the list head if we need
+ * to dereference its prev/next pointers, and save/restore the real head.*/
+#ifdef NO_DECLTYPE
+#define _SV(elt,list) _tmp = (char*)(list); {char **_alias = (char**)&(list); *_alias = (elt); }
+#define _NEXT(elt,list) ((char*)((list)->next))
+#define _NEXTASGN(elt,list,to) { char **_alias = (char**)&((list)->next); *_alias=(char*)(to); }
+#define _PREV(elt,list) ((char*)((list)->prev))
+#define _PREVASGN(elt,list,to) { char **_alias = (char**)&((list)->prev); *_alias=(char*)(to); }
+#define _RS(list) { char **_alias = (char**)&(list); *_alias=_tmp; }
+#define _CASTASGN(a,b) { char **_alias = (char**)&(a); *_alias=(char*)(b); }
+#else
+#define _SV(elt,list)
+#define _NEXT(elt,list) ((elt)->next)
+#define _NEXTASGN(elt,list,to) ((elt)->next)=(to)
+#define _PREV(elt,list) ((elt)->prev)
+#define _PREVASGN(elt,list,to) ((elt)->prev)=(to)
+#define _RS(list)
+#define _CASTASGN(a,b) (a)=(b)
+#endif
+
+/******************************************************************************
+ * The sort macro is an adaptation of Simon Tatham's O(n log(n)) mergesort *
+ * Unwieldy variable names used here to avoid shadowing passed-in variables. *
+ *****************************************************************************/
+#define LL_SORT(list, cmp) \
+do { \
+ LDECLTYPE(list) _ls_p; \
+ LDECLTYPE(list) _ls_q; \
+ LDECLTYPE(list) _ls_e; \
+ LDECLTYPE(list) _ls_tail; \
+ LDECLTYPE(list) _ls_oldhead; \
+ LDECLTYPE(list) _tmp; \
+ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
+ if (list) { \
+ _ls_insize = 1; \
+ _ls_looping = 1; \
+ while (_ls_looping) { \
+ _CASTASGN(_ls_p,list); \
+ _CASTASGN(_ls_oldhead,list); \
+ list = NULL; \
+ _ls_tail = NULL; \
+ _ls_nmerges = 0; \
+ while (_ls_p) { \
+ _ls_nmerges++; \
+ _ls_q = _ls_p; \
+ _ls_psize = 0; \
+ for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
+ _ls_psize++; \
+ _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
+ if (!_ls_q) break; \
+ } \
+ _ls_qsize = _ls_insize; \
+ while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
+ if (_ls_psize == 0) { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ } else if (_ls_qsize == 0 || !_ls_q) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ } else if (cmp(_ls_p,_ls_q) <= 0) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ } else { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ } \
+ if (_ls_tail) { \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
+ } else { \
+ _CASTASGN(list,_ls_e); \
+ } \
+ _ls_tail = _ls_e; \
+ } \
+ _ls_p = _ls_q; \
+ } \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
+ if (_ls_nmerges <= 1) { \
+ _ls_looping=0; \
+ } \
+ _ls_insize *= 2; \
+ } \
+ } else _tmp=NULL; /* quiet gcc unused variable warning */ \
+} while (0)
+
+#define DL_SORT(list, cmp) \
+do { \
+ LDECLTYPE(list) _ls_p; \
+ LDECLTYPE(list) _ls_q; \
+ LDECLTYPE(list) _ls_e; \
+ LDECLTYPE(list) _ls_tail; \
+ LDECLTYPE(list) _ls_oldhead; \
+ LDECLTYPE(list) _tmp; \
+ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
+ if (list) { \
+ _ls_insize = 1; \
+ _ls_looping = 1; \
+ while (_ls_looping) { \
+ _CASTASGN(_ls_p,list); \
+ _CASTASGN(_ls_oldhead,list); \
+ list = NULL; \
+ _ls_tail = NULL; \
+ _ls_nmerges = 0; \
+ while (_ls_p) { \
+ _ls_nmerges++; \
+ _ls_q = _ls_p; \
+ _ls_psize = 0; \
+ for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
+ _ls_psize++; \
+ _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); \
+ if (!_ls_q) break; \
+ } \
+ _ls_qsize = _ls_insize; \
+ while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
+ if (_ls_psize == 0) { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ } else if (_ls_qsize == 0 || !_ls_q) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ } else if (cmp(_ls_p,_ls_q) <= 0) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ } else { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ } \
+ if (_ls_tail) { \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
+ } else { \
+ _CASTASGN(list,_ls_e); \
+ } \
+ _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
+ _ls_tail = _ls_e; \
+ } \
+ _ls_p = _ls_q; \
+ } \
+ _CASTASGN(list->prev, _ls_tail); \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,NULL); _RS(list); \
+ if (_ls_nmerges <= 1) { \
+ _ls_looping=0; \
+ } \
+ _ls_insize *= 2; \
+ } \
+ } else _tmp=NULL; /* quiet gcc unused variable warning */ \
+} while (0)
+
+#define CDL_SORT(list, cmp) \
+do { \
+ LDECLTYPE(list) _ls_p; \
+ LDECLTYPE(list) _ls_q; \
+ LDECLTYPE(list) _ls_e; \
+ LDECLTYPE(list) _ls_tail; \
+ LDECLTYPE(list) _ls_oldhead; \
+ LDECLTYPE(list) _tmp; \
+ LDECLTYPE(list) _tmp2; \
+ int _ls_insize, _ls_nmerges, _ls_psize, _ls_qsize, _ls_i, _ls_looping; \
+ if (list) { \
+ _ls_insize = 1; \
+ _ls_looping = 1; \
+ while (_ls_looping) { \
+ _CASTASGN(_ls_p,list); \
+ _CASTASGN(_ls_oldhead,list); \
+ list = NULL; \
+ _ls_tail = NULL; \
+ _ls_nmerges = 0; \
+ while (_ls_p) { \
+ _ls_nmerges++; \
+ _ls_q = _ls_p; \
+ _ls_psize = 0; \
+ for (_ls_i = 0; _ls_i < _ls_insize; _ls_i++) { \
+ _ls_psize++; \
+ _SV(_ls_q,list); \
+ if (_NEXT(_ls_q,list) == _ls_oldhead) { \
+ _ls_q = NULL; \
+ } else { \
+ _ls_q = _NEXT(_ls_q,list); \
+ } \
+ _RS(list); \
+ if (!_ls_q) break; \
+ } \
+ _ls_qsize = _ls_insize; \
+ while (_ls_psize > 0 || (_ls_qsize > 0 && _ls_q)) { \
+ if (_ls_psize == 0) { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
+ } else if (_ls_qsize == 0 || !_ls_q) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
+ } else if (cmp(_ls_p,_ls_q) <= 0) { \
+ _ls_e = _ls_p; _SV(_ls_p,list); _ls_p = _NEXT(_ls_p,list); _RS(list); _ls_psize--; \
+ if (_ls_p == _ls_oldhead) { _ls_p = NULL; } \
+ } else { \
+ _ls_e = _ls_q; _SV(_ls_q,list); _ls_q = _NEXT(_ls_q,list); _RS(list); _ls_qsize--; \
+ if (_ls_q == _ls_oldhead) { _ls_q = NULL; } \
+ } \
+ if (_ls_tail) { \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_ls_e); _RS(list); \
+ } else { \
+ _CASTASGN(list,_ls_e); \
+ } \
+ _SV(_ls_e,list); _PREVASGN(_ls_e,list,_ls_tail); _RS(list); \
+ _ls_tail = _ls_e; \
+ } \
+ _ls_p = _ls_q; \
+ } \
+ _CASTASGN(list->prev,_ls_tail); \
+ _CASTASGN(_tmp2,list); \
+ _SV(_ls_tail,list); _NEXTASGN(_ls_tail,list,_tmp2); _RS(list); \
+ if (_ls_nmerges <= 1) { \
+ _ls_looping=0; \
+ } \
+ _ls_insize *= 2; \
+ } \
+ } else _tmp=NULL; /* quiet gcc unused variable warning */ \
+} while (0)
+
+/******************************************************************************
+ * singly linked list macros (non-circular) *
+ *****************************************************************************/
+#define LL_PREPEND(head,add) \
+do { \
+ (add)->next = head; \
+ head = add; \
+} while (0)
+
+#define LL_APPEND(head,add) \
+do { \
+ LDECLTYPE(head) _tmp; \
+ (add)->next=NULL; \
+ if (head) { \
+ _tmp = head; \
+ while (_tmp->next) { _tmp = _tmp->next; } \
+ _tmp->next=(add); \
+ } else { \
+ (head)=(add); \
+ } \
+} while (0)
+
+#define LL_DELETE(head,del) \
+do { \
+ LDECLTYPE(head) _tmp; \
+ if ((head) == (del)) { \
+ (head)=(head)->next; \
+ } else { \
+ _tmp = head; \
+ while (_tmp->next && (_tmp->next != (del))) { \
+ _tmp = _tmp->next; \
+ } \
+ if (_tmp->next) { \
+ _tmp->next = ((del)->next); \
+ } \
+ } \
+} while (0)
+
+/* Here are VS2008 replacements for LL_APPEND and LL_DELETE */
+#define LL_APPEND_VS2008(head,add) \
+do { \
+ if (head) { \
+ (add)->next = head; /* use add->next as a temp variable */ \
+ while ((add)->next->next) { (add)->next = (add)->next->next; } \
+ (add)->next->next=(add); \
+ } else { \
+ (head)=(add); \
+ } \
+ (add)->next=NULL; \
+} while (0)
+
+#define LL_DELETE_VS2008(head,del) \
+do { \
+ if ((head) == (del)) { \
+ (head)=(head)->next; \
+ } else { \
+ char *_tmp = (char*)(head); \
+ while (head->next && (head->next != (del))) { \
+ head = head->next; \
+ } \
+ if (head->next) { \
+ head->next = ((del)->next); \
+ } \
+ { \
+ char **_head_alias = (char**)&(head); \
+ *_head_alias = _tmp; \
+ } \
+ } \
+} while (0)
+#ifdef NO_DECLTYPE
+#undef LL_APPEND
+#define LL_APPEND LL_APPEND_VS2008
+#undef LL_DELETE
+#define LL_DELETE LL_DELETE_VS2008
+#endif
+/* end VS2008 replacements */
+
+#define LL_FOREACH(head,el) \
+ for(el=head;el;el=el->next)
+
+#define LL_FOREACH_SAFE(head,el,tmp) \
+ for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
+
+#define LL_SEARCH_SCALAR(head,out,field,val) \
+do { \
+ LL_FOREACH(head,out) { \
+ if ((out)->field == (val)) break; \
+ } \
+} while(0)
+
+#define LL_SEARCH(head,out,elt,cmp) \
+do { \
+ LL_FOREACH(head,out) { \
+ if ((cmp(out,elt))==0) break; \
+ } \
+} while(0)
+
+/******************************************************************************
+ * doubly linked list macros (non-circular) *
+ *****************************************************************************/
+#define DL_PREPEND(head,add) \
+do { \
+ (add)->next = head; \
+ if (head) { \
+ (add)->prev = (head)->prev; \
+ (head)->prev = (add); \
+ } else { \
+ (add)->prev = (add); \
+ } \
+ (head) = (add); \
+} while (0)
+
+#define DL_APPEND(head,add) \
+do { \
+ if (head) { \
+ (add)->prev = (head)->prev; \
+ (head)->prev->next = (add); \
+ (head)->prev = (add); \
+ (add)->next = NULL; \
+ } else { \
+ (head)=(add); \
+ (head)->prev = (head); \
+ (head)->next = NULL; \
+ } \
+} while (0);
+
+#define DL_DELETE(head,del) \
+do { \
+ if ((del)->prev == (del)) { \
+ (head)=NULL; \
+ } else if ((del)==(head)) { \
+ (del)->next->prev = (del)->prev; \
+ (head) = (del)->next; \
+ } else { \
+ (del)->prev->next = (del)->next; \
+ if ((del)->next) { \
+ (del)->next->prev = (del)->prev; \
+ } else { \
+ (head)->prev = (del)->prev; \
+ } \
+ } \
+} while (0);
+
+
+#define DL_FOREACH(head,el) \
+ for(el=head;el;el=el->next)
+
+/* this version is safe for deleting the elements during iteration */
+#define DL_FOREACH_SAFE(head,el,tmp) \
+ for((el)=(head);(el) && (tmp = (el)->next, 1); (el) = tmp)
+
+/* these are identical to their singly-linked list counterparts */
+#define DL_SEARCH_SCALAR LL_SEARCH_SCALAR
+#define DL_SEARCH LL_SEARCH
+
+/******************************************************************************
+ * circular doubly linked list macros *
+ *****************************************************************************/
+#define CDL_PREPEND(head,add) \
+do { \
+ if (head) { \
+ (add)->prev = (head)->prev; \
+ (add)->next = (head); \
+ (head)->prev = (add); \
+ (add)->prev->next = (add); \
+ } else { \
+ (add)->prev = (add); \
+ (add)->next = (add); \
+ } \
+(head)=(add); \
+} while (0)
+
+#define CDL_DELETE(head,del) \
+do { \
+ if ( ((head)==(del)) && ((head)->next == (head))) { \
+ (head) = 0L; \
+ } else { \
+ (del)->next->prev = (del)->prev; \
+ (del)->prev->next = (del)->next; \
+ if ((del) == (head)) (head)=(del)->next; \
+ } \
+} while (0);
+
+#define CDL_FOREACH(head,el) \
+ for(el=head;el;el=(el->next==head ? 0L : el->next))
+
+#define CDL_FOREACH_SAFE(head,el,tmp1,tmp2) \
+ for((el)=(head), ((tmp1)=(head)?((head)->prev):NULL); \
+ (el) && ((tmp2)=(el)->next, 1); \
+ ((el) = (((el)==(tmp1)) ? 0L : (tmp2))))
+
+#define CDL_SEARCH_SCALAR(head,out,field,val) \
+do { \
+ CDL_FOREACH(head,out) { \
+ if ((out)->field == (val)) break; \
+ } \
+} while(0)
+
+#define CDL_SEARCH(head,out,elt,cmp) \
+do { \
+ CDL_FOREACH(head,out) { \
+ if ((cmp(out,elt))==0) break; \
+ } \
+} while(0)
+
+#endif /* UTLIST_H */
+
--- /dev/null
+Build notes
+
+//-------------------------------------------------
+// Linux
+//-------------------------------------------------
+To enable logging, ensure that
+ -D TB_LOG
+is set in the compiler flags
+
+//-------------------------------------------------
+// Android
+//-------------------------------------------------
+To enable logging for Android, TB_LOG should be defined in the ./jni/Android.mk file as
+
+LOCAL_CFLAGS := -DTB_LOG
+
+//-------------------------------------------------
+// Arduino
+//-------------------------------------------------
+To enable the logger for Arduino, TB_LOG should be defined in
+Properties|C/C++ Build|Settings|Tool Settings|AVR Compiler|Symbols
+and
+Properties|C/C++ Build|Settings|Tool Settings|AVR C++ Compiler|Symbols
+
+Note: when building for Arduino, force the compiler to use avr-g++ to build logger.c. Or rename logger.c to logger.cpp.
+
+Note: when building for Arduino, several warnings are generated when trying to place strings in
+PROGMEM
+"warning: only initialized variables can be placed into program memory area"
+This appears to be a known gcc bug - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef LOGGER_H_
+#define LOGGER_H_
+
+#include <stdint.h>
+#include <stdio.h>
+#include <stdarg.h>
+
+#ifdef __ANDROID__
+ #include <android/log.h>
+#elif defined ARDUINO
+ #include "Arduino.h"
+ #include <avr/pgmspace.h>
+#endif
+
+// Use the PCF macro to wrap strings stored in FLASH on the Arduino
+// Example: OC_LOG(INFO, TAG, PCF("Entering function"));
+#ifdef ARDUINO
+ #define PCF(str) ((const prog_char*)(F(str)))
+#else
+ #define PCF(str) str
+#endif
+
+// Max buffer size used in variable argument log function
+#define MAX_LOG_V_BUFFER_SIZE (256)
+
+// Log levels
+typedef enum {
+ DEBUG = 0,
+ INFO,
+ WARNING,
+ ERROR,
+ FATAL
+} LogLevel;
+
+
+#if defined(__ANDROID__) || defined(__linux__)
+ /**
+ * Output a variable argument list log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param format - variadic log string
+ */
+ void OCLogv(LogLevel level, const char * tag, const char * format, ...);
+
+ /**
+ * Output a log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param logStr - log string
+ */
+ void OCLog(LogLevel level, const char * tag, const char * logStr);
+
+ /**
+ * Output the contents of the specified buffer (in hex) with the specified priority level.
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param buffer - pointer to buffer of bytes
+ * @param bufferSize - max number of byte in buffer
+ */
+ void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize);
+#endif
+
+#ifdef ARDUINO
+ /**
+ * Initialize the serial logger for Arduino
+ * Only defined for Arduino
+ */
+ void OCLogInit();
+
+ /**
+ * Output a log string with the specified priority level.
+ * Only defined for Arduino. Uses PROGMEM strings
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param logStr - log string
+ */
+ void OCLog(LogLevel level, const prog_char * tag, const prog_char * logStr);
+
+ /**
+ * Output the contents of the specified buffer (in hex) with the specified priority level.
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param buffer - pointer to buffer of bytes
+ * @param bufferSize - max number of byte in buffer
+ */
+ void OCLogBuffer(LogLevel level, const prog_char * tag, const uint8_t * buffer, uint16_t bufferSize);
+#endif
+
+#ifdef TB_LOG
+ // These macros are defined for Linux, Android, and Arduino
+ #define OC_LOG(level, tag, logStr) OCLog((level), (tag), (logStr))
+ #define OC_LOG_BUFFER(level, tag, buffer, bufferSize) OCLogBuffer((level), (tag), (buffer), (bufferSize))
+
+ #ifdef ARDUINO
+ // Use full namespace for logInit to avoid function name collision
+ #define OC_LOG_INIT() OCLogInit()
+ // Don't define variable argument log function for Arduino
+ #define OC_LOG_V(level, tag, ...)
+ #else
+ // Don't define LOG_INIT for Linux and Android
+ #define OC_LOG_INIT()
+ // Define variable argument log function for Linux and Android
+ #define OC_LOG_V(level, tag, ...) OCLogv((level), (tag), __VA_ARGS__)
+ #endif
+
+#else
+ #define OC_LOG(level, tag, logStr)
+ #define OC_LOG_V(level, tag, ...)
+ #define OC_LOG_BUFFER(level, tag, buffer, bufferSize)
+ #define OC_LOG_INIT()
+#endif
+
+#endif /* LOGGER_H_ */
--- /dev/null
+# override with `make BUILD=release`
+# default to debug build
+BUILD := debug
+
+# You must create the file "local.properties" on your local machine which contains any local paths, etc
+# local_settings.mk should NOT be committed to repo
+include ./local.properties
+# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties
+# Example:
+# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0
+
+# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable
+# contains $(GTEST_DIR)/lib/.libs
+
+CC := gcc
+CXX := g++
+
+PROG := loggertest
+
+SRC_DIR := ./src
+TEST_DIR:= ./test
+INC_DIR := ./include
+
+CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -D TB_LOG
+CC_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -fpic
+CC_FLAGS := $(CC_FLAGS.$(BUILD))
+
+CXX_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c++0x -fpic -D TB_LOG
+CXX_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fpic
+CXX_FLAGS := $(CXX_FLAGS.$(BUILD))
+
+INC := -I$(SRC_DIR)
+INC += -I$(TEST_DIR)
+INC += -I$(INC_DIR)
+INC += -I$(GTEST_DIR)/include
+
+
+# using make's computed variables to select object and bin folders
+# depending on the build type
+OBJ_DIR.debug := ./obj/debug
+OBJ_DIR.release := ./obj/release
+OBJ_DIR := $(OBJ_DIR.$(BUILD))
+
+BIN_DIR.debug := ./bin/debug
+BIN_DIR.release := ./bin/release
+BIN_DIR := $(BIN_DIR.$(BUILD))
+
+C_FILES := $(wildcard $(SRC_DIR)/*.c)
+#CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp)
+CPP_FILES := $(wildcard $(TEST_DIR)/*.cpp)
+OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o)))
+H_FILES := $(wildcard $(TEST_DIR)/*.h)
+H_FILES += $(wildcard $(INC_DIR)/*.h)
+LD_FLAGS := -L/usr/lib
+LD_FLAGS += -L$(GTEST_DIR)/lib/.libs
+
+
+LIBS := -lpthread
+LIBS += -lgtest
+LIBS += -lgtest_main
+
+
+all: $(PROG)
+
+$(PROG): $(OBJ_FILES)
+ $(CXX) -o $@ $^ $(LD_FLAGS) $(LIBS)
+ mv ./$(PROG) ./$(BIN_DIR)
+
+#$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h $(H_FILES)
+# $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC_DIR)/%.h $(H_FILES)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES)
+ $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+
+.PHONY: clean
+clean :
+ rm -rf ./obj/debug/*
+ rm -rf ./obj/release/*
+ rm -rf ./lib/debug/*
+ rm -rf ./lib/release/*
+ rm -rf ./bin/debug/*
+ rm -rf ./bin/release/*
+ rm -rf ./test/tst_*.txt
+
+
+.PHONY: print_vars
+
+print_vars:
+ @echo ""
+ @echo 'BUILD = '$(value BUILD)
+ @echo 'INC = '$(value INC)
+ @echo 'CPP_FILES = '$(value CPP_FILES)
+ @echo 'LIBS = '$(value LIBS)
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include "logger.h"
+#include "string.h"
+
+
+
+static const uint16_t LINE_BUFFER_SIZE = (16 * 2) + 16 + 1; // Show 16 bytes, 2 chars/byte, spaces between bytes, null termination
+
+// Convert LogLevel to platform-specific severity level. Store in PROGMEM on Arduino
+#ifdef __ANDROID__
+ static android_LogPriority LEVEL[] = {ANDROID_LOG_DEBUG, ANDROID_LOG_INFO, ANDROID_LOG_WARN, ANDROID_LOG_ERROR, ANDROID_LOG_FATAL};
+#elif defined __linux__
+ //static const char * LEVEL[] = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
+ static const char * LEVEL[] __attribute__ ((unused)) = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
+#elif defined ARDUINO
+
+ #define MAX_ARDUINO_LEVEL_STR_SIZE (8)
+
+ prog_char level0[] PROGMEM = "DEBUG";
+ prog_char level1[] PROGMEM = "INFO";
+ prog_char level2[] PROGMEM = "WARNING";
+ prog_char level3[] PROGMEM = "ERROR";
+ prog_char level4[] PROGMEM = "FATAL";
+
+ PROGMEM const prog_char * LEVEL[] = {level0, level1, level2, level3, level4};
+
+ static void OCLogString(LogLevel level, const prog_char * tag, const char * logStr);
+#endif
+
+
+#if defined(__ANDROID__) || defined(__linux__)
+/**
+ * Output a variable argument list log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param format - variadic log string
+ */
+void OCLogv(LogLevel level, const char * tag, const char * format, ...) {
+#ifdef TB_LOG
+ if (!format || !tag) {
+ return;
+ }
+ char buffer[MAX_LOG_V_BUFFER_SIZE];
+ memset(buffer, 0, sizeof buffer);
+ va_list args;
+ va_start(args, format);
+ vsnprintf(buffer, sizeof buffer - 1, format, args);
+ va_end(args);
+ OCLog(level, tag, buffer);
+#endif
+}
+
+/**
+ * Output a log string with the specified priority level.
+ * Only defined for Linux and Android
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param logStr - log string
+ */
+void OCLog(LogLevel level, const char * tag, const char * logStr) {
+#ifdef TB_LOG
+ if (!logStr || !tag) {
+ return;
+ }
+
+ #ifdef __ANDROID__
+ __android_log_write(LEVEL[level], tag, logStr);
+ #elif defined __linux__
+ printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
+ #endif
+#endif
+}
+
+/**
+ * Output the contents of the specified buffer (in hex) with the specified priority level.
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param buffer - pointer to buffer of bytes
+ * @param bufferSize - max number of byte in buffer
+ */
+void OCLogBuffer(LogLevel level, const char * tag, const uint8_t * buffer, uint16_t bufferSize) {
+#ifdef TB_LOG
+ if (!buffer || !tag || (bufferSize == 0)) {
+ return;
+ }
+
+ char lineBuffer[LINE_BUFFER_SIZE];
+ memset(lineBuffer, 0, sizeof lineBuffer);
+ int lineIndex = 0;
+ int i;
+ for (i = 0; i < bufferSize; i++) {
+ // Format the buffer data into a line
+ sprintf(&lineBuffer[lineIndex++ * 3], "%02X ", buffer[i]);
+ // Output 16 values per line
+ if (((i+1)%16) == 0) {
+ OCLog(level, tag, lineBuffer);
+ memset(lineBuffer, 0, sizeof lineBuffer);
+ lineIndex = 0;
+ }
+ }
+ // Output last values in the line, if any
+ if (bufferSize % 16) {
+ OCLog(level, tag, lineBuffer);
+ }
+#endif
+}
+
+#endif
+
+
+
+#ifdef ARDUINO
+ /**
+ * Initialize the serial logger for Arduino
+ * Only defined for Arduino
+ */
+ void OCLogInit() {
+ #ifdef TB_LOG
+ Serial.begin(115200);
+ #endif
+ }
+
+ /**
+ * Output a log string with the specified priority level.
+ * Only defined for Arduino. Only uses PROGMEM strings
+ * for the tag parameter
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param logStr - log string
+ */
+ void OCLogString(LogLevel level, const prog_char * tag, const char * logStr) {
+ #ifdef TB_LOG
+ if (!logStr || !tag) {
+ return;
+ }
+
+ char buffer[MAX_ARDUINO_LEVEL_STR_SIZE] = {0};
+ strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
+ Serial.print(buffer);
+
+ char c;
+ Serial.print(F(": "));
+ while ((c = pgm_read_byte(tag))) {
+ Serial.write(c);
+ tag++;
+ }
+ Serial.print(F(": "));
+
+ Serial.println(logStr);
+ #endif
+ }
+
+ /**
+ * Output the contents of the specified buffer (in hex) with the specified priority level.
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param buffer - pointer to buffer of bytes
+ * @param bufferSize - max number of byte in buffer
+ */
+ void OCLogBuffer(LogLevel level, const prog_char * tag, const uint8_t * buffer, uint16_t bufferSize) {
+ #ifdef TB_LOG
+ if (!buffer || !tag || (bufferSize == 0)) {
+ return;
+ }
+
+ char lineBuffer[LINE_BUFFER_SIZE] = {0};
+ uint8_t lineIndex = 0;
+ for (uint8_t i = 0; i < bufferSize; i++) {
+ // Format the buffer data into a line
+ sprintf(&lineBuffer[lineIndex++ * 3], "%02X ", buffer[i]);
+ // Output 16 values per line
+ if (((i+1)%16) == 0) {
+ OCLogString(level, tag, lineBuffer);
+ memset(lineBuffer, 0, sizeof lineBuffer);
+ lineIndex = 0;
+ }
+ }
+ // Output last values in the line, if any
+ if (bufferSize % 16) {
+ OCLogString(level, tag, lineBuffer);
+ }
+ #endif
+ }
+
+ /**
+ * Output a log string with the specified priority level.
+ * Only defined for Arduino. Uses PROGMEM strings
+ *
+ * @param level - DEBUG, INFO, WARNING, ERROR, FATAL
+ * @param tag - Module name
+ * @param logStr - log string
+ */
+ void OCLog(LogLevel level, const prog_char * tag, const prog_char * logStr) {
+ #ifdef TB_LOG
+ if (!logStr || !tag) {
+ return;
+ }
+
+ char buffer[MAX_ARDUINO_LEVEL_STR_SIZE] = {0};
+ strcpy_P(buffer, (char*)pgm_read_word(&(LEVEL[level])));
+ Serial.print(buffer);
+
+ char c;
+ Serial.print(F(": "));
+ while ((c = pgm_read_byte(tag))) {
+ Serial.write(c);
+ tag++;
+ }
+ Serial.print(F(": "));
+
+ while ((c = pgm_read_byte(logStr))) {
+ Serial.write(c);
+ logStr++;
+ }
+ Serial.println();
+ #endif
+ }
+#endif
+
+
--- /dev/null
+loggertests.cpp contain several logger tests that can be used in an Android JNI app.
+
+androidloggertestoutput.txt is a file capture from running loggertests.cpp in an Android JNI app.
+
+Note: to enable the logger for Android, TB_LOG should be defined in the ./jni/Android.mk file as
+
+LOCAL_CFLAGS := -DTB_LOG
+
+
--- /dev/null
+05-30 12:56:28.136: I/Android(8314): Starting logger test
+05-30 12:56:28.136: I/Android(8314): Android Logger Test
+05-30 12:56:28.136: D/Android(8314): this is a DEBUG message
+05-30 12:56:28.136: I/Android(8314): this is a INFO message
+05-30 12:56:28.136: W/Android(8314): this is a WARNING message
+05-30 12:56:28.136: E/Android(8314): this is a ERROR message
+05-30 12:56:28.136: A/Android(8314): this is a FATAL message
+05-30 12:56:28.136: D/Android(8314): this is a DEBUG message
+05-30 12:56:28.136: D/Android(8314): on multiple
+05-30 12:56:28.136: D/Android(8314): lines
+05-30 12:56:28.136: D/Android(8314): 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+05-30 12:56:28.136: D/Android(8314): 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+05-30 12:56:28.136: D/Android(8314): 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+05-30 12:56:28.136: D/Android(8314): 30 31
+05-30 12:56:28.136: D/Android(8314): 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+05-30 12:56:28.136: D/Android(8314): 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+05-30 12:56:28.136: D/Android(8314): 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+05-30 12:56:28.136: D/Android(8314): 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+05-30 12:56:28.136: D/Android(8314): 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+05-30 12:56:28.136: D/Android(8314): 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+05-30 12:56:28.136: D/Android(8314): 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+05-30 12:56:28.136: D/Android(8314): 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+05-30 12:56:28.136: D/Android(8314): 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+05-30 12:56:28.136: D/Android(8314): 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+05-30 12:56:28.136: D/Android(8314): 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+05-30 12:56:28.136: D/Android(8314): 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+05-30 12:56:28.136: D/Android(8314): 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+05-30 12:56:28.136: D/Android(8314): 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+05-30 12:56:28.136: D/Android(8314): 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+05-30 12:56:28.136: D/Android(8314): 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E
+05-30 12:56:28.136: D/Android(8314): 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+05-30 12:56:28.136: D/Android(8314): 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+05-30 12:56:28.136: D/Android(8314): 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+05-30 12:56:28.136: D/Android(8314): 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+05-30 12:56:28.136: D/Android(8314): 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+05-30 12:56:28.136: D/Android(8314): 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+05-30 12:56:28.136: D/Android(8314): 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+05-30 12:56:28.136: D/Android(8314): 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+05-30 12:56:28.136: D/Android(8314): 80
+05-30 12:56:28.136: D/Android(8314): this is a char: A
+05-30 12:56:28.136: D/Android(8314): this is an integer: 123
+05-30 12:56:28.136: D/Android(8314): this is a string: hello
+05-30 12:56:28.136: D/Android(8314): this is a float: 123.45
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+extern "C" {
+ #include "logger.h"
+}
+
+static const char tag[] = "Android";
+static const char msg[] = "Android Logger Test";
+
+static const char debugMsg[] = "this is a DEBUG message";
+static const char infoMsg[] = "this is a INFO message";
+static const char warningMsg[] = "this is a WARNING message";
+static const char errorMsg[] = "this is a ERROR message";
+static const char fatalMsg[] = "this is a FATAL message";
+
+static const char multiLineMsg[] = "this is a DEBUG message\non multiple\nlines";
+
+
+//-----------------------------------------------------------------------------
+// Tests
+//-----------------------------------------------------------------------------
+static void test0() {
+ OC_LOG(INFO, tag, msg);
+}
+
+static void test1() {
+ OC_LOG(INFO, 0, msg);
+}
+
+static void test2() {
+ OC_LOG(INFO, tag, 0);
+}
+
+static void test3() {
+ OC_LOG(INFO, 0, 0);
+}
+
+static void test4() {
+ OC_LOG(DEBUG, tag, debugMsg);
+ OC_LOG(INFO, tag, infoMsg);
+ OC_LOG(WARNING, tag, warningMsg);
+ OC_LOG(ERROR, tag, errorMsg);
+ OC_LOG(FATAL, tag, fatalMsg);
+}
+
+static void test5() {
+ OC_LOG(DEBUG, tag, multiLineMsg);
+}
+
+
+static void test6() {
+ // Log buffer
+ uint8_t buffer[50];
+ for (int i = 0; i < (int)(sizeof buffer); i++) {
+ buffer[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer, sizeof buffer);
+
+ // Log buffer, 128 bytes is a good boundary (8 rows of 16 values)
+ uint8_t buffer1[128];
+ for (int i = 0; i < (int)(sizeof buffer1); i++) {
+ buffer1[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer1, sizeof buffer1);
+
+ // 1 below 128 byte boundary
+ uint8_t buffer2[127];
+ for (int i = 0; i < (int)(sizeof buffer2); i++) {
+ buffer2[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer2, sizeof buffer2);
+
+ // 1 above 128 byte boundary
+ uint8_t buffer3[129];
+ for (int i = 0; i < (int)(sizeof buffer3); i++) {
+ buffer3[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer3, sizeof buffer3);
+}
+
+static void test7() {
+ OC_LOG_V(DEBUG, tag, "this is a char: %c", 'A');
+ OC_LOG_V(DEBUG, tag, "this is an integer: %d", 123);
+ OC_LOG_V(DEBUG, tag, "this is a string: %s", "hello");
+ OC_LOG_V(DEBUG, tag, "this is a float: %5.2f", 123.45);
+}
+
+//-----------------------------------------------------------------------------
+// loggertests
+//-----------------------------------------------------------------------------
+void loggertests() {
+ OC_LOG(INFO, tag, "Starting logger test");
+
+ test0();
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+ test7();
+}
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+// Do not remove the include below
+#include "ArduinoLoggerTest.h"
+#include "logger.h"
+
+const prog_char tag[] PROGMEM = "Arduino";
+const prog_char msg[] PROGMEM = "Arduino Logger Test";
+
+const prog_char debugMsg[] PROGMEM = "this is a DEBUG message";
+const prog_char infoMsg[] PROGMEM = "this is a INFO message";
+const prog_char warningMsg[] PROGMEM = "this is a WARNING message";
+const prog_char errorMsg[] PROGMEM = "this is a ERROR message";
+const prog_char fatalMsg[] PROGMEM = "this is a FATAL message";
+
+const prog_char multiLineMsg[] PROGMEM = "this is a DEBUG message\non multiple\nlines";
+
+
+//-----------------------------------------------------------------------------
+// Tests
+//-----------------------------------------------------------------------------
+void test0() {
+ OC_LOG(INFO, tag, msg);
+}
+
+void test1() {
+ OC_LOG(INFO, 0, msg);
+}
+
+void test2() {
+ OC_LOG(INFO, tag, 0);
+}
+
+void test3() {
+ OC_LOG(INFO, 0, 0);
+}
+
+void test4() {
+ OC_LOG(DEBUG, tag, debugMsg);
+ OC_LOG(INFO, tag, infoMsg);
+ OC_LOG(WARNING, tag, warningMsg);
+ OC_LOG(ERROR, tag, errorMsg);
+ OC_LOG(FATAL, tag, fatalMsg);
+}
+
+void test5() {
+ OC_LOG(DEBUG, tag, multiLineMsg);
+}
+
+
+void test6() {
+ // Log buffer
+ uint8_t buffer[50];
+ for (int i = 0; i < (int)(sizeof buffer); i++) {
+ buffer[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer, sizeof buffer);
+
+ // Log buffer, 128 bytes is a good boundary (8 rows of 16 values)
+ uint8_t buffer1[128];
+ for (int i = 0; i < (int)(sizeof buffer1); i++) {
+ buffer1[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer1, sizeof buffer1);
+
+ // 1 below 128 byte boundary
+ uint8_t buffer2[127];
+ for (int i = 0; i < (int)(sizeof buffer2); i++) {
+ buffer2[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer2, sizeof buffer2);
+
+ // 1 above 128 byte boundary
+ uint8_t buffer3[129];
+ for (int i = 0; i < (int)(sizeof buffer3); i++) {
+ buffer3[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer3, sizeof buffer3);
+}
+
+//The setup function is called once at startup of the sketch
+void setup()
+{
+ // Add your initialization code here
+ OC_LOG_INIT();
+
+ test0();
+ delay(2000);
+ test1();
+ delay(2000);
+ test2();
+ delay(2000);
+ test3();
+ delay(2000);
+ test4();
+ delay(2000);
+ test5();
+ delay(2000);
+ test6();
+ delay(2000);
+}
+
+// The loop function is called in an endless loop
+void loop()
+{
+ delay(2000);
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+// Only modify this file to include
+// - function definitions (prototypes)
+// - include files
+// - extern variable definitions
+// In the appropriate section
+
+#ifndef ArduinoLoggerTest_H_
+#define ArduinoLoggerTest_H_
+#include "Arduino.h"
+//add your includes for the project ArduinoDummyTestFramework here
+
+
+//end of add your includes here
+#ifdef __cplusplus
+extern "C" {
+#endif
+void loop();
+void setup();
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+//add your function definitions for the project ArduinoDummyTestFramework here
+
+
+
+
+//Do not add code below this line
+#endif /* LoggerTest_H_ */
--- /dev/null
+ArduinoLoggerTest.cpp contains several logger tests and can be used in an
+Arduino sketch.
+
+On Arduino, the logger outputs to the serial port using Serial.print.
+
+Run a serial terminal program such as CuteCom at 115200,8,N,1 to view the
+log outputs.
+
+arduinologgertestoutput.txt contains the output captured after running ArduinoLoggerTest.cpp
+
+Note: to enable the logger for Arduino, TB_LOG should be defined in
+Properties|C/C++ Build|Settings|Tool Settings|AVR Compiler|Symbols
+and
+Properties|C/C++ Build|Settings|Tool Settings|AVR C++ Compiler|Symbols
+
+Note: when building for Arduino, force the compiler to use avr-g++ to build logger.c. Or rename logger.c to logger.cpp.
+
+Note: when building for Arduino, several warnings are generated when trying to place strings in
+PROGMEM
+"warning: only initialized variables can be placed into program memory area"
+This appears to be a known gcc bug - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
+
--- /dev/null
+INFO: Arduino: Arduino Logger Test
+DEBUG: Arduino: this is a DEBUG message
+INFO: Arduino: this is a INFO message
+WARNING: Arduino: this is a WARNING message
+ERROR: Arduino: this is a ERROR message
+FATAL: Arduino: this is a FATAL message
+DEBUG: Arduino: this is a DEBUG message
+on multiple
+lines
+DEBUG: Arduino: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+DEBUG: Arduino: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+DEBUG: Arduino: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+DEBUG: Arduino: 30 31
+DEBUG: Arduino: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+DEBUG: Arduino: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+DEBUG: Arduino: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+DEBUG: Arduino: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+DEBUG: Arduino: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+DEBUG: Arduino: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+DEBUG: Arduino: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+DEBUG: Arduino: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+DEBUG: Arduino: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+DEBUG: Arduino: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+DEBUG: Arduino: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+DEBUG: Arduino: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+DEBUG: Arduino: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+DEBUG: Arduino: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+DEBUG: Arduino: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+DEBUG: Arduino: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E
+DEBUG: Arduino: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+DEBUG: Arduino: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+DEBUG: Arduino: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+DEBUG: Arduino: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+DEBUG: Arduino: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+DEBUG: Arduino: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+DEBUG: Arduino: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+DEBUG: Arduino: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+DEBUG: Arduino: 80
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+extern "C" {
+ #include "logger.h"
+}
+
+
+#include "gtest/gtest.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <iostream>
+#include <stdint.h>
+using namespace std;
+
+
+//-----------------------------------------------------------------------------
+// file_exist citation -
+// http://stackoverflow.com/questions/230062/whats-the-best-way-to-check-if-a-file-exists-in-c-cross-platform/230070#230070
+//-----------------------------------------------------------------------------
+bool file_exist(const char *filename) {
+ struct stat buffer;
+ return (stat(filename, &buffer) == 0);
+}
+
+//-----------------------------------------------------------------------------
+// stdio redirection citation - http://www.cplusplus.com/forum/general/94879/
+//-----------------------------------------------------------------------------
+static int fd;
+static int defout;
+
+bool directStdOutToFile(const char *filename) {
+ if (!filename) {
+ return false;
+ }
+
+ if ((defout = dup(1)) < 0) {
+ fprintf(stderr, "Can't dup(2) - (%s)\n", strerror(errno));
+ return false;
+ }
+ if ((fd = open(filename, O_RDWR | O_TRUNC | O_CREAT, S_IRUSR | S_IWUSR)) < 0) {
+ fprintf(stderr, "Can't open(2) - (%s)\n", strerror(errno));
+ return false;
+ }
+ // redirect output to the file
+ if (dup2(fd, 1) < 0) {
+ fprintf(stderr, "Can't dup2(2) - (%s)\n", strerror(errno));
+ return false;
+ }
+ close(fd); // Descriptor no longer needed
+
+ fflush(stdout); // FLUSH ALL OUTPUT TO file
+
+ return true;
+}
+
+bool directStdOutToConsole() {
+ fflush(stdout); // FLUSH ALL OUTPUT TO file
+
+ // redirect output back to stdout
+ if (dup2(defout, 1) < 0) {
+ fprintf(stderr, "Can't dup2(2) - (%s)\n", strerror(errno));
+ return false;
+ }
+ close(defout); // Copy of stdout no longer needed
+
+ return true;
+}
+
+//-----------------------------------------------------------------------------
+// CalcFileMD5 citation - http://stackoverflow.com/questions/3395690/md5sum-of-file-in-linux-c
+//-----------------------------------------------------------------------------
+#include <stdio.h>
+#include <ctype.h>
+
+#define STR_VALUE(val) #val
+#define STR(name) STR_VALUE(name)
+
+#define PATH_LEN 256
+#define MD5_LEN 32
+
+bool CalcFileMD5(const char *file_name, char *md5_sum) {
+ #define MD5SUM_CMD_FMT "md5sum %." STR(PATH_LEN) "s 2>/dev/null"
+ char cmd[PATH_LEN + sizeof (MD5SUM_CMD_FMT)];
+ sprintf(cmd, MD5SUM_CMD_FMT, file_name);
+ #undef MD5SUM_CMD_FMT
+
+ FILE *p = popen(cmd, "r");
+ if (p == NULL) return 0;
+
+ int i, ch;
+ for (i = 0; i < MD5_LEN && isxdigit(ch = fgetc(p)); i++) {
+ *md5_sum++ = ch;
+ }
+
+ *md5_sum = '\0';
+ pclose(p);
+ return (i == MD5_LEN);
+}
+
+
+//-----------------------------------------------------------------------------
+// Tests
+//-----------------------------------------------------------------------------
+TEST(LoggerTest, StringArg) {
+ char testFile[] = "tst_stringarg.txt";
+ char stdFile[] = "std_stringarg.txt";
+
+ // Try deleting test file
+ remove(testFile);
+
+ directStdOutToFile(testFile);
+ const char *tag = "StringArg";
+ OC_LOG(INFO, tag, "This is a fixed string call");
+ directStdOutToConsole();
+
+ bool testFileExists = file_exist(testFile);
+ EXPECT_TRUE(testFileExists);
+ bool stdFileExists = file_exist(stdFile);
+ EXPECT_TRUE(stdFileExists);
+
+ if (testFileExists && stdFileExists) {
+ char testFileMD5[MD5_LEN + 1] = {0};
+ char stdFileMD5[MD5_LEN + 1] = {0};
+
+ EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5));
+ EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5));
+
+ EXPECT_STREQ(stdFileMD5, testFileMD5);
+ }
+}
+
+TEST(LoggerTest, StringArgNoTag) {
+ char testFile[] = "tst_stringargnotag.txt";
+ char stdFile[] = "std_stringargnotag.txt";
+
+ directStdOutToFile(testFile);
+ OC_LOG(INFO, 0, "This is a fixed string call");
+ directStdOutToConsole();
+
+ bool testFileExists = file_exist(testFile);
+ EXPECT_TRUE(testFileExists);
+ bool stdFileExists = file_exist(stdFile);
+ EXPECT_TRUE(stdFileExists);
+
+ if (testFileExists && stdFileExists) {
+ char testFileMD5[MD5_LEN + 1] = {0};
+ char stdFileMD5[MD5_LEN + 1] = {0};
+
+ EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5));
+ EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5));
+
+ EXPECT_STREQ(stdFileMD5, testFileMD5);
+ }
+}
+
+TEST(LoggerTest, StringArgNoLogStr) {
+ char testFile[] = "tst_stringargnologstr.txt";
+ char stdFile[] = "std_stringargnologstr.txt";
+
+ directStdOutToFile(testFile);
+ const char *tag = "StringArgNoLogStr";
+ OC_LOG(INFO, tag, 0);
+ directStdOutToConsole();
+
+ bool testFileExists = file_exist(testFile);
+ EXPECT_TRUE(testFileExists);
+ bool stdFileExists = file_exist(stdFile);
+ EXPECT_TRUE(stdFileExists);
+
+ if (testFileExists && stdFileExists) {
+ char testFileMD5[MD5_LEN + 1] = {0};
+ char stdFileMD5[MD5_LEN + 1] = {0};
+
+ EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5));
+ EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5));
+
+ EXPECT_STREQ(stdFileMD5, testFileMD5);
+ }
+}
+
+TEST(LoggerTest, StringArgNoTagNoLogStr) {
+ char testFile[] = "tst_stringargnotagnologstr.txt";
+ char stdFile[] = "std_stringargnotagnologstr.txt";
+
+ directStdOutToFile(testFile);
+ OC_LOG(INFO, 0, 0);
+ directStdOutToConsole();
+
+ bool testFileExists = file_exist(testFile);
+ EXPECT_TRUE(testFileExists);
+ bool stdFileExists = file_exist(stdFile);
+ EXPECT_TRUE(stdFileExists);
+
+ if (testFileExists && stdFileExists) {
+ char testFileMD5[MD5_LEN + 1] = {0};
+ char stdFileMD5[MD5_LEN + 1] = {0};
+
+ EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5));
+ EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5));
+
+ EXPECT_STREQ(stdFileMD5, testFileMD5);
+ }
+}
+
+TEST(LoggerTest, StringArgLevels) {
+ char testFile[] = "tst_stringarglevels.txt";
+ char stdFile[] = "std_stringarglevels.txt";
+
+ directStdOutToFile(testFile);
+ const char *tag = "StringArgLevels";
+ // DEBUG, INFO, WARNING, ERROR, FATAL
+ OC_LOG(DEBUG, tag, "this is a DEBUG message");
+ OC_LOG(INFO, tag, "this is a INFO message");
+ OC_LOG(WARNING, tag, "this is a WARNING message");
+ OC_LOG(ERROR, tag, "this is a ERROR message");
+ OC_LOG(FATAL, tag, "this is a FATAL message");
+ directStdOutToConsole();
+
+ bool testFileExists = file_exist(testFile);
+ EXPECT_TRUE(testFileExists);
+ bool stdFileExists = file_exist(stdFile);
+ EXPECT_TRUE(stdFileExists);
+
+ if (testFileExists && stdFileExists) {
+ char testFileMD5[MD5_LEN + 1] = {0};
+ char stdFileMD5[MD5_LEN + 1] = {0};
+
+ EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5));
+ EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5));
+
+ EXPECT_STREQ(stdFileMD5, testFileMD5);
+ }
+}
+
+TEST(LoggerTest, StringArgMultiline) {
+ char testFile[] = "tst_stringargmultiline.txt";
+ char stdFile[] = "std_stringargmultiline.txt";
+
+ directStdOutToFile(testFile);
+ const char *tag = "StringArgMultiline";
+ OC_LOG(DEBUG, tag, "this is a DEBUG message\non multiple\nlines");
+ directStdOutToConsole();
+
+ bool testFileExists = file_exist(testFile);
+ EXPECT_TRUE(testFileExists);
+ bool stdFileExists = file_exist(stdFile);
+ EXPECT_TRUE(stdFileExists);
+
+ if (testFileExists && stdFileExists) {
+ char testFileMD5[MD5_LEN + 1] = {0};
+ char stdFileMD5[MD5_LEN + 1] = {0};
+
+ EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5));
+ EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5));
+
+ EXPECT_STREQ(stdFileMD5, testFileMD5);
+ }
+}
+
+TEST(LoggerTest, VariableArg) {
+ char testFile[] = "tst_variablearg.txt";
+ char stdFile[] = "std_variablearg.txt";
+
+ directStdOutToFile(testFile);
+ const char *tag = "VariableArg";
+ // DEBUG, INFO, WARNING, ERROR, FATAL
+ OC_LOG_V(DEBUG, tag, "this is a char: %c", 'A');
+ OC_LOG_V(DEBUG, tag, "this is an integer: %d", 123);
+ OC_LOG_V(DEBUG, tag, "this is a string: %s", "hello");
+ OC_LOG_V(DEBUG, tag, "this is a float: %5.2f", 123.45);
+ directStdOutToConsole();
+
+ bool testFileExists = file_exist(testFile);
+ EXPECT_TRUE(testFileExists);
+ bool stdFileExists = file_exist(stdFile);
+ EXPECT_TRUE(stdFileExists);
+
+ if (testFileExists && stdFileExists) {
+ char testFileMD5[MD5_LEN + 1] = {0};
+ char stdFileMD5[MD5_LEN + 1] = {0};
+
+ EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5));
+ EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5));
+
+ EXPECT_STREQ(stdFileMD5, testFileMD5);
+ }
+}
+
+TEST(LoggerTest, LogBuffer) {
+ char testFile[] = "tst_logbuffer.txt";
+ char stdFile[] = "std_logbuffer.txt";
+
+ directStdOutToFile(testFile);
+ const char *tag = "LogBuffer";
+
+ // Log buffer
+ uint8_t buffer[50];
+ for (int i = 0; i < (int)(sizeof buffer); i++) {
+ buffer[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer, sizeof buffer);
+
+ // Log buffer, 128 bytes is a good boundary (8 rows of 16 values)
+ uint8_t buffer1[128];
+ for (int i = 0; i < (int)(sizeof buffer1); i++) {
+ buffer1[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer1, sizeof buffer1);
+
+ // 1 below 128 byte boundary
+ uint8_t buffer2[127];
+ for (int i = 0; i < (int)(sizeof buffer2); i++) {
+ buffer2[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer2, sizeof buffer2);
+
+ // 1 above 128 byte boundary
+ uint8_t buffer3[129];
+ for (int i = 0; i < (int)(sizeof buffer3); i++) {
+ buffer3[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer3, sizeof buffer3);
+
+ directStdOutToConsole();
+
+ bool testFileExists = file_exist(testFile);
+ EXPECT_TRUE(testFileExists);
+ bool stdFileExists = file_exist(stdFile);
+ EXPECT_TRUE(stdFileExists);
+
+ if (testFileExists && stdFileExists) {
+ char testFileMD5[MD5_LEN + 1] = {0};
+ char stdFileMD5[MD5_LEN + 1] = {0};
+
+ EXPECT_TRUE(CalcFileMD5(testFile, testFileMD5));
+ EXPECT_TRUE(CalcFileMD5(stdFile, stdFileMD5));
+
+ EXPECT_STREQ(stdFileMD5, testFileMD5);
+ }
+}
--- /dev/null
+DEBUG: LogBuffer: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+DEBUG: LogBuffer: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+DEBUG: LogBuffer: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+DEBUG: LogBuffer: 30 31
+DEBUG: LogBuffer: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+DEBUG: LogBuffer: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+DEBUG: LogBuffer: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+DEBUG: LogBuffer: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+DEBUG: LogBuffer: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+DEBUG: LogBuffer: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+DEBUG: LogBuffer: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+DEBUG: LogBuffer: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+DEBUG: LogBuffer: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+DEBUG: LogBuffer: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+DEBUG: LogBuffer: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+DEBUG: LogBuffer: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+DEBUG: LogBuffer: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+DEBUG: LogBuffer: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+DEBUG: LogBuffer: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+DEBUG: LogBuffer: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E
+DEBUG: LogBuffer: 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
+DEBUG: LogBuffer: 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F
+DEBUG: LogBuffer: 20 21 22 23 24 25 26 27 28 29 2A 2B 2C 2D 2E 2F
+DEBUG: LogBuffer: 30 31 32 33 34 35 36 37 38 39 3A 3B 3C 3D 3E 3F
+DEBUG: LogBuffer: 40 41 42 43 44 45 46 47 48 49 4A 4B 4C 4D 4E 4F
+DEBUG: LogBuffer: 50 51 52 53 54 55 56 57 58 59 5A 5B 5C 5D 5E 5F
+DEBUG: LogBuffer: 60 61 62 63 64 65 66 67 68 69 6A 6B 6C 6D 6E 6F
+DEBUG: LogBuffer: 70 71 72 73 74 75 76 77 78 79 7A 7B 7C 7D 7E 7F
+DEBUG: LogBuffer: 80
--- /dev/null
+INFO: StringArg: This is a fixed string call
--- /dev/null
+DEBUG: StringArgLevels: this is a DEBUG message
+INFO: StringArgLevels: this is a INFO message
+WARNING: StringArgLevels: this is a WARNING message
+ERROR: StringArgLevels: this is a ERROR message
+FATAL: StringArgLevels: this is a FATAL message
--- /dev/null
+DEBUG: StringArgMultiline: this is a DEBUG message
+on multiple
+lines
--- /dev/null
+DEBUG: VariableArg: this is a char: A
+DEBUG: VariableArg: this is an integer: 123
+DEBUG: VariableArg: this is a string: hello
+DEBUG: VariableArg: this is a float: 123.45
--- /dev/null
+# override with `make BUILD=release`
+# default to debug build
+BUILD := debug
+PLATFORM := linux
+CC := gcc
+
+ifeq ($(ROOT_DIR), )
+ROOT_DIR = $(PWD)
+endif
+
+ifeq ($(OBJ_DIR), )
+OBJ_DIR = $(ROOT_DIR)/obj
+endif
+
+OCLOGGER_DIR = $(ROOT_DIR)/logger
+OCRANDOM_DIR = $(ROOT_DIR)/ocrandom
+OCSOCKET_DIR = $(ROOT_DIR)/ocsocket
+LCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1
+OCCOAP_DIR = $(ROOT_DIR)/occoap
+OCTBSTACK_DIR = $(ROOT_DIR)/stack
+UTILS_DIR = $(ROOT_DIR)/../../../ccf-utilities/tb
+CJSON_DIR = $(UTILS_DIR)/cJSON
+
+OCCOAP_SRC = $(OCCOAP_DIR)/src
+OCTBSTACK_SRC = $(OCTBSTACK_DIR)/src
+CJSON_SRC = $(CJSON_DIR)
+
+OCLOGGER_INC = $(OCLOGGER_DIR)/include
+OCRANDOM_INC = $(OCRANDOM_DIR)/include
+OCSOCKET_INC = $(OCSOCKET_DIR)/include
+LCOAP_INC = $(LCOAP_DIR)
+OCCOAP_INC = $(OCCOAP_DIR)/include
+OCTBSTACK_INC = $(OCTBSTACK_DIR)/include
+CJSON_INC = $(CJSON_DIR)
+
+INC_DIRS := -I$(OCLOGGER_INC)
+INC_DIRS += -I$(OCRANDOM_INC)
+INC_DIRS += -I$(OCSOCKET_INC)
+INC_DIRS += -I$(LCOAP_INC)
+INC_DIRS += -I$(OCCOAP_INC)
+INC_DIRS += -I$(OCTBSTACK_INC)
+INC_DIRS += -I$(OCTBSTACK_INC)/internal
+INC_DIRS += -I$(CJSON_INC)
+
+CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -DTB_LOG -L./libcoap-4.1.1/
+CC_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -fpic -L./libcoap-4.1.1/
+
+CFLAGS += $(CC_FLAGS.$(BUILD)) -DWITH_POSIX $(INC_DIRS)
+LDLIBS += -lcoap
+
+CJSON_SOURCES := $(CJSON_SRC)/cJSON.c
+
+OCCOAP_SOURCES := $(OCCOAP_SRC)/occoap.c
+
+OCTBSTACK_SOURCES := $(OCTBSTACK_SRC)/ocstack.c
+OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/occlientcb.c
+OCTBSTACK_SOURCES += $(OCTBSTACK_SRC)/ocserverrequest.c
+
+SOURCES := $(CJSON_SOURCES)
+SOURCES += $(OCCOAP_SOURCES)
+SOURCES += $(OCTBSTACK_SOURCES)
+
+all: make_lcoap objdirs obj_build liboctbstack.a #print_vars
+
+make_lcoap:
+ $(MAKE) -C $(LCOAP_DIR)
+
+objdirs: $(ROOT_DIR)
+ mkdir -p $(OBJ_DIR)
+ mkdir -p $(OBJ_DIR)/$(BUILD)
+
+obj_build:
+ @echo "Building $@"
+ $(foreach source,$(SOURCES), $(CC) $(LDLIBS) $(CFLAGS) $(source) -o $(patsubst %.c, %.o, $(patsubst %, $(OBJ_DIR)/$(BUILD)/%, $(notdir $(source))));) # Output all *.o files to $(OBJ_DIR)/$(BUILD)
+
+liboctbstack.a:
+ @echo "Building $@"
+ @cd $(OBJ_DIR)/$(BUILD) && ar -x $(LCOAP_DIR)/libcoap.a # Unpackage libcoap.a to $(OBJ_DIR)/$(BUILD). The output objects from OCStack and OCCoap are already at this location
+ ar -r $@ $(OBJ_DIR)/$(BUILD)/*.o # Repackage all the objects at this location into a single archive. This is OCStack, OCCoap, and LibCoap (LibCoap contains OCRandom, OCLogger, and OCSocket.).
+
+.PHONY: clean print_vars
+
+clean: $(ROOT_DIR)
+ @echo "Cleaning all."
+ rm -f $(OBJ_DIR)/$(BUILD)/*.o
+ rm -f $(ROOT_DIR)/liboctbstack.a
+
+deepclean: $(ROOT_DIR)
+ @echo "Deep-Cleaning all."
+ rm -f $(OBJ_DIR)/$(BUILD)/*.o
+ rm -f $(ROOT_DIR)/liboctbstack.a
+ $(MAKE) clean -C $(LCOAP_DIR)
+
+print_vars:
+ @echo ""
+ @echo 'INCLUDES ARE: '$(value INC_DIRS)
+ @echo ""
+ @echo 'SOURCE FILES ARE: '$(value SOURCES)
+ @echo ""
+ @echo 'OBJ_DIR/BUILD is: '$(OBJ_DIR)'/'$(BUILD)
+ @echo ""
+ @echo 'ROOT_DIR is: '$(ROOT_DIR)
--- /dev/null
+#==============================================================================
+# Build instructions for Linux
+#==============================================================================
+
+In ./occoap directory
+clean ==> make clean
+build ==> make
+
+#==============================================================================
+# Unit test instructions for Linux
+#==============================================================================
+
+After building (make), run
+./occoap/bin/debug/occoaptest
+
+
--- /dev/null
+//******************************************************************
+///
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OCCOAP_H_
+#define OCCOAP_H_
+
+//-----------------------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------------------
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include <stdint.h>
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+
+typedef enum {
+ OC_COAP_OK = 0,
+ OC_COAP_ERR
+} OCCoAPResult;
+
+//-----------------------------------------------------------------------------
+// Function Prototypes
+//-----------------------------------------------------------------------------
+
+/**
+ * Initialize the CoAP client or server with the its IPv4 address and CoAP port
+ *
+ * @param ipAddr
+ * IP Address of host device
+ * @param port
+ * Port of host device
+ * @param mode
+ * Host device is client, server, or client-server
+ *
+ * @return
+ * 0 - success
+ * TBD - TBD error
+ */
+int OCInitCoAP(const char *address, uint16_t port, OCMode mode);
+
+/**
+ * Discover OC resources
+ *
+ * @param method - method to perform on the resource
+ * @param Uri - URI of the resource to interact with
+ * @param asyncReturnFunc - asynchronous callback function that is invoked
+ * by the stack when discovery or resource interaction is complete
+ * @return
+ * 0 - success
+ * TBD - TBD error
+ */
+int OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCToken * token, const char *Uri);
+
+
+/**
+ * Stop the CoAP client or server processing
+ *
+ * @return 0 - success, else - TBD error
+ */
+int OCStopCoAP();
+
+/**
+ * Called in main loop of CoAP client or server. Allows low-level CoAP processing of
+ * send, receive, timeout, discovery, callbacks, etc.
+ *
+ * @return 0 - success, else - TBD error
+ */
+int OCProcessCoAP();
+
+
+#endif /* OCCOAP_H_ */
--- /dev/null
+# override with `make BUILD=release`
+# default to debug build
+BUILD := debug
+
+# You must create the file "local.properties" on your local machine which contains any local paths, etc
+# local_settings.mk should NOT be committed to repo
+include ./local.properties
+# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties
+# Example:
+# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0
+
+# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable
+# contains $(GTEST_DIR)/lib/.libs
+
+CC := gcc
+CXX := g++
+
+PROG := occoaptest
+
+#SRC_DIR := ./src
+TEST_DIR:= ./test
+#INC_DIR := ./include
+#LOG_DIR := ../logger
+#STACK_DIR := ../stack
+
+CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -D TB_LOG
+CC_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -fpic
+CC_FLAGS := $(CC_FLAGS.$(BUILD))
+
+CXX_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c++0x -fpic -D TB_LOG
+CXX_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fpic
+CXX_FLAGS := $(CXX_FLAGS.$(BUILD))
+
+#INC := -I$(SRC_DIR)
+#INC += -I$(TEST_DIR)
+#INC += -I$(INC_DIR)
+#INC += -I$(LOG_DIR)/include
+#INC += -I$(STACK_DIR)/include
+INC += -I$(GTEST_DIR)/include
+
+
+# using make's computed variables to select object and bin folders
+# depending on the build type
+OBJ_DIR.debug := ./obj/debug
+OBJ_DIR.release := ./obj/release
+OBJ_DIR := $(OBJ_DIR.$(BUILD))
+
+BIN_DIR.debug := ./bin/debug
+BIN_DIR.release := ./bin/release
+BIN_DIR := $(BIN_DIR.$(BUILD))
+
+#C_FILES := $(wildcard $(LOG_DIR)/src/*.c)
+#C_FILES += $(wildcard $(SRC_DIR)/*.c)
+#CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp)
+CPP_FILES := $(wildcard $(TEST_DIR)/*.cpp)
+#CPP_FILES += $(wildcard $(LOG_DIR)/src/*.c)
+OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o)))
+H_FILES := $(wildcard $(TEST_DIR)/*.h)
+#H_FILES += $(wildcard $(INC_DIR)/*.h)
+#H_FILES += $(wildcard $(LOG_DIR)/include/*.h)
+LD_FLAGS := -L/usr/lib
+LD_FLAGS += -L$(GTEST_DIR)/lib/.libs
+
+
+LIBS := -lpthread
+LIBS += -lgtest
+LIBS += -lgtest_main
+
+
+all: $(PROG)
+ mkdir -p ./$(OBJ_DIR)
+ mkdir -p ./$(BIN_DIR)
+
+$(PROG): $(OBJ_FILES)
+ $(CXX) -o $@ $^ $(LD_FLAGS) $(LIBS)
+ mkdir -p ./$(BIN_DIR)
+ mv ./$(PROG) ./$(BIN_DIR)
+
+#$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h $(H_FILES)
+# $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+#$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(INC_DIR)/%.h $(H_FILES)
+# $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC_DIR)/%.h $(H_FILES)
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(LOG_DIR)/src/%.c $(LOG_DIR)/include/%.h $(H_FILES)
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES)
+ mkdir -p ./$(OBJ_DIR)
+ $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+.PHONY: clean
+clean :
+ rm -rf ./obj/debug/*
+ rm -rf ./obj/release/*
+ rm -rf ./lib/*
+ rm -rf ./bin/debug/*
+ rm -rf ./bin/release/*
+
+
+.PHONY: print_vars
+
+print_vars:
+ @echo ""
+ @echo 'BUILD = '$(value BUILD)
+ @echo 'INC = '$(value INC)
+ @echo 'CPP_FILES = '$(value CPP_FILES)
+ @echo 'C_FILES = '$(value C_FILES)
+ @echo 'LIBS = '$(value LIBS)
+ @echo 'OBJ_FILES = '$(value OBJ_FILES)
+ @echo 'SRC_DIR = '$(value SRC_DIR)
+
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+//=============================================================================
+// Includes
+//=============================================================================
+#include "occoap.h"
+#include <coap.h>
+#include <unistd.h>
+#include <limits.h>
+#include <ctype.h>
+
+//-----------------------------------------------------------------------------
+// Macros
+//-----------------------------------------------------------------------------
+#define TAG PCF("OCCoAP")
+#define VERIFY_SUCCESS(op, successCode) { if (op != successCode) \
+ {OC_LOG(FATAL, TAG, #op " failed !!"); goto exit;} }
+#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, TAG, #arg " is NULL"); goto exit;} }
+
+#define BUF_SIZE (64)
+#define BUF_SIZE_ENCODE_OPTION (3)
+#define BUF_SIZE_PORT (2)
+
+//=============================================================================
+// Private Variables
+//=============================================================================
+
+static uint8_t coapWKIpAddr[] = { 224, 0, 1, 187 };
+static coap_context_t *gCoAPCtx = NULL;
+
+//=============================================================================
+// Helper Functions
+//=============================================================================
+
+//generate a coap message
+static coap_pdu_t *
+GenerateCoAPPdu(uint8_t msgType, uint8_t code, unsigned short id,
+ size_t tokenLength, uint8_t * token, coap_list_t *options) {
+ coap_pdu_t *pdu;
+ coap_list_t *opt;
+
+ pdu = coap_pdu_init(msgType, code, id, COAP_MAX_PDU_SIZE);
+ VERIFY_NON_NULL(pdu);
+
+ pdu->hdr->token_length = tokenLength;
+ if (!coap_add_token(pdu, tokenLength, token)) {
+ OC_LOG(FATAL, TAG, "coap_add_token failed");
+ }
+
+ // display the pdu for debugging purposes
+ coap_show_pdu(pdu);
+
+ for (opt = options; opt; opt = opt->next) {
+ coap_add_option(pdu, COAP_OPTION_KEY(*(coap_option *)opt->data),
+ COAP_OPTION_LENGTH(*(coap_option *)opt->data),
+ COAP_OPTION_DATA(*(coap_option *)opt->data));
+ }
+ return pdu;
+
+ exit: return NULL;
+}
+
+//a function to help in ordering coap options
+static int OrderOptions(void *a, void *b) {
+ if (!a || !b) {
+ return a < b ? -1 : 1;
+ }
+
+ if (COAP_OPTION_KEY(*(coap_option *)a)
+ < COAP_OPTION_KEY(*(coap_option *)b) ) {
+ return -1;
+ }
+
+ return COAP_OPTION_KEY(*(coap_option *)a)
+ == COAP_OPTION_KEY(*(coap_option *)b) ;
+}
+
+//a function to create a coap option
+static coap_list_t *
+CreateNewOptionNode(unsigned short key, unsigned int length,
+ unsigned char *data) {
+ coap_option *option;
+ coap_list_t *node;
+
+ option = coap_malloc(sizeof(coap_option) + length);
+ if (!option) {
+ goto exit;
+ }
+
+ COAP_OPTION_KEY(*option) = key;
+ COAP_OPTION_LENGTH(*option) = length;
+ VERIFY_NON_NULL(data);
+ memcpy(COAP_OPTION_DATA(*option), data, length);
+
+ /* we can pass NULL here as delete function since option is released automatically */
+ node = coap_new_listnode(option, NULL);
+
+ if (node) {
+ return node;
+ }
+
+ exit: OC_LOG(ERROR,TAG,"new_option_node: malloc: was not created");
+ coap_free(option);
+ return NULL;
+}
+
+//This function is called back by libcoap when a response is received
+static void HandleCoAPRequests(struct coap_context_t *ctx,
+ const coap_queue_t * rcvdRequest) {
+
+ // silence warnings
+ (void) ctx;
+ // fill OCRequest structure
+ OCRequest * request;
+ OCEntityHandlerRequest * entityHandlerRequest;
+ unsigned char bufReq[MAX_REQUEST_LENGTH] = { 0 };
+ unsigned char bufRes[MAX_RESPONSE_LENGTH] = { 0 };
+ size_t bufLen = 0;
+ OCToken * rcvdToken;
+ coap_opt_iterator_t opt_iter;
+ coap_opt_filter_t filter;
+ coap_opt_t *option;
+ unsigned char rcvdUri[MAX_URI_LENGTH] = { 0 };
+ unsigned char rcvdQuery[MAX_QUERY_LENGTH] = { 0 };
+ OCStackResult result;
+ coap_list_t *optList = NULL;
+ unsigned char tempBuf[BUF_SIZE_ENCODE_OPTION];
+ coap_pdu_t *pdu;
+ coap_tid_t tid = COAP_INVALID_TID;
+
+ //TODO:will be deleted at the end
+ entityHandlerRequest = (OCEntityHandlerRequest *) malloc(
+ sizeof(OCEntityHandlerRequest));
+
+ entityHandlerRequest->method = OC_REST_NOMETHOD;
+ if (rcvdRequest->pdu->hdr->code == COAP_REQUEST_GET) {
+ entityHandlerRequest->method = OC_REST_GET;
+ } else {
+ OC_LOG(DEBUG, TAG, "!!!!!!!!!!!!!!!!!!!!!!!method not supported in HandleCoAPRequests");
+ }
+
+ coap_get_data(rcvdRequest->pdu, &bufLen, (unsigned char **)&bufReq);
+ bufReq[bufLen] = 0;
+ OC_LOG_V(INFO, TAG, "received payload %d bytes : %s", bufLen, bufReq);
+ entityHandlerRequest->reqJSONPayload = bufReq;
+
+ entityHandlerRequest->resJSONPayload = bufRes;
+ entityHandlerRequest->resJSONPayloadLen = MAX_RESPONSE_LENGTH;
+
+ //TODO:will be deleted at the end
+ rcvdToken = (OCToken *) malloc(sizeof(OCToken));
+ rcvdToken->tokenLength = rcvdRequest->pdu->hdr->token_length;
+ memcpy(rcvdToken->token, rcvdRequest->pdu->hdr->token,
+ rcvdToken->tokenLength);
+
+ OC_LOG_V(INFO,TAG,"Token received %d bytes..........%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+ rcvdToken->tokenLength,rcvdToken->token[0],rcvdToken->token[1],rcvdToken->token[2],rcvdToken->token[3],
+ rcvdToken->token[4],rcvdToken->token[5],rcvdToken->token[6],rcvdToken->token[7]);
+ entityHandlerRequest->token = rcvdToken;
+
+ //TODO:will be deleted at the end
+ request = (OCRequest *) malloc(sizeof(OCRequest));
+ request->entityHandlerRequest = entityHandlerRequest;
+
+ request->qos = OC_NON_CONFIRMABLE;
+ if (rcvdRequest->pdu->hdr->type == COAP_MESSAGE_CON) {
+ request->qos = OC_CONFIRMABLE;
+ }
+
+ //getting the uri
+ request->resourceUrl = NULL;
+ bufLen = 0;
+ coap_option_filter_clear(filter);
+ coap_option_setb(filter, COAP_OPTION_URI_PATH);
+ coap_option_iterator_init(rcvdRequest->pdu, &opt_iter, filter);
+ while ((option = coap_option_next(&opt_iter))) {
+ rcvdUri[bufLen++] = '/';
+ memcpy(rcvdUri + bufLen, COAP_OPT_VALUE(option),
+ COAP_OPT_LENGTH(option));
+ bufLen += COAP_OPT_LENGTH(option);
+ }
+ rcvdUri[bufLen] = '\0';
+ OC_LOG_V(INFO, TAG, " Receveid uri %s", rcvdUri);
+ request->resourceUrl = rcvdUri;
+
+ request->query = NULL;
+ bufLen = 0;
+ coap_option_filter_clear(filter);
+ coap_option_setb(filter, COAP_OPTION_URI_QUERY);
+ coap_option_iterator_init(rcvdRequest->pdu, &opt_iter, filter);
+ while ((option = coap_option_next(&opt_iter))) {
+ memcpy(rcvdQuery + bufLen, COAP_OPT_VALUE(option),
+ COAP_OPT_LENGTH(option));
+ bufLen += COAP_OPT_LENGTH(option);
+ rcvdQuery[bufLen++] = '&';
+ }
+ // delete last '&'
+ rcvdQuery[bufLen - 1] = '\0';
+ OC_LOG_V(INFO, TAG, " Receveid query %s", rcvdQuery);
+ request->query = rcvdQuery;
+
+ result = OCStackHandleReceiveRequest(request);
+
+ if (result == OC_STACK_OK) {
+ OC_LOG_V(INFO, TAG, "Response from ocstack: %s", request->entityHandlerRequest->resJSONPayload);
+ // need to build the response PDU
+ coap_insert(&optList,
+ CreateNewOptionNode(COAP_OPTION_CONTENT_TYPE,
+ coap_encode_var_bytes(tempBuf,
+ COAP_MEDIATYPE_APPLICATION_JSON), tempBuf),
+ OrderOptions);
+ coap_insert(&optList,
+ CreateNewOptionNode(COAP_OPTION_MAXAGE,
+ coap_encode_var_bytes(tempBuf, 0x2ffff), tempBuf),
+ OrderOptions);
+
+ // generate the pdu, if the request was CON, then the response is ACK, otherwire NON
+ pdu = GenerateCoAPPdu(
+ rcvdRequest->pdu->hdr->type == COAP_MESSAGE_CON ?
+ COAP_MESSAGE_ACK : COAP_MESSAGE_NON,
+ COAP_RESPONSE_CODE(205), rcvdRequest->pdu->hdr->id,
+ rcvdToken->tokenLength, rcvdToken->token, optList);
+ coap_add_data(pdu,
+ strlen((const char *)request->entityHandlerRequest->resJSONPayload),
+ (unsigned char*) request->entityHandlerRequest->resJSONPayload);
+
+ if (pdu->hdr->type != COAP_MESSAGE_NON
+ || (pdu->hdr->code >= 64 && !coap_is_mcast(&rcvdRequest->local))) {
+ tid = coap_send(gCoAPCtx, &rcvdRequest->remote, pdu);
+ }OC_LOG_V(INFO, TAG, "TID %d", tid);OC_LOG(INFO, TAG, "Deleting PDU");
+ // unlike stock libcoap (deletion in handle_request in net.c), we are deleting the response here
+ // in the future, the response might be queued for SLOW resources
+ coap_delete_pdu(pdu);
+
+ coap_delete_list(optList);
+
+ OC_LOG(INFO, TAG, "Done Cleaning up");
+ } else {
+ OC_LOG(DEBUG, TAG, "We not supporting other returns of OCServerRequestResult in HandleCoAPRequests/"
+ " ......................yet");
+ }
+ free(rcvdToken);
+ free(entityHandlerRequest);
+ free(request);
+}
+
+//This function is called back by libcoap when a response is received
+static void HandleCoAPResponses(struct coap_context_t *ctx,
+ const coap_queue_t * rcvdResponse) {
+ OCResponse * response;
+ OCToken * token;
+ OCClientResponse * clientResponse;
+ unsigned char bufRes[MAX_RESPONSE_LENGTH] = { 0 };
+ unsigned char * pRes = NULL;
+ size_t bufLen = 0;
+
+ VERIFY_NON_NULL(ctx);
+ VERIFY_NON_NULL(rcvdResponse);
+
+ // TODO: we should check if we are interested in the token
+ // Now, just accept NON packets
+
+ if (rcvdResponse->pdu->hdr->type == COAP_MESSAGE_NON) {
+ // These will be deleted at the end
+ response = (OCResponse *) malloc(sizeof(OCResponse));
+ token = (OCToken *) malloc(sizeof(OCToken));
+ clientResponse = (OCClientResponse *) malloc(sizeof(OCClientResponse));
+
+ token->tokenLength = rcvdResponse->pdu->hdr->token_length;
+ memcpy(token->token, rcvdResponse->pdu->hdr->token, token->tokenLength);
+
+ clientResponse->addr = (OCDevAddr *)&(rcvdResponse->remote);
+
+ coap_get_data(rcvdResponse->pdu, &bufLen, &pRes);
+ memcpy(bufRes, pRes, bufLen);
+ bufRes[bufLen] = 0;
+ clientResponse->resJSONPayload = bufRes;
+ OC_LOG_V(INFO, TAG, "Received a response HandleCoAPResponses in occoap: %s ", bufRes);
+
+ clientResponse->result = OC_STACK_ERROR;
+
+ response->token = token;
+ response->clientResponse = clientResponse;
+
+ if (rcvdResponse->pdu->hdr->code == COAP_RESPONSE_CODE(205)) {
+ response->clientResponse->result = OC_STACK_OK;
+ OCStackHandleReceiveResponse(response);
+ } else {
+ OC_LOG(DEBUG, TAG, "No other response codes are supported in HandleCoAPResponsesooooooooooooooooooooooo");
+ }
+
+ free(response);
+ free(token);
+ free(clientResponse);
+ } else {
+ OC_LOG(DEBUG, TAG, "Do not accept other than NON in HandleCoAPResponsesooooooooooooooooooooooo");
+ }
+#if 0
+ size_t len;
+ unsigned char *dataBuf;
+ const void *addrPtr = NULL;
+ char buf[BUF_SIZE];
+ uint8_t remoteIpAddr[4];
+ uint16_t remotePortNu;
+
+ VERIFY_NON_NULL(received);
+ VERIFY_NON_NULL(ctx);
+ VERIFY_NON_NULL(remote);
+
+ /* check if this is a response to our original request */
+ if (!CheckToken(received)) {
+ return;
+ }
+
+ switch (received->hdr->type) {
+ case COAP_MESSAGE_CON:
+ /* acknowledge received response if confirmable (TODO: check Token) */
+ coap_send_ack(ctx, remote, received);
+ break;
+ case COAP_MESSAGE_RST:
+ return;
+ default:
+ ;
+ }
+
+ if (received->hdr->code == COAP_RESPONSE_CODE(205)) {
+ coap_get_data(received, &len, &dataBuf);
+ OC_LOG_V(INFO, TAG, "This is a success COAP_RESPONSE_CODE(205):Payload data: %s", dataBuf);
+ }
+
+// TODO: we should call OCHandleClientReceiveResponse
+ /*if (storedOCStackCB) {
+ OCDevAddrToIPv4Addr((OCDevAddr *) remote, remoteIpAddr, remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
+ OCDevAddrToPort((OCDevAddr *) remote, &remotePortNu);
+ sprintf(buf, "%d.%d.%d.%d:%d", remoteIpAddr[0], remoteIpAddr[1], remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
+ OC_LOG_V(INFO, TAG, "Calling storedOCStackCB function with remote address %s",buf);
+ storedOCStackCB(buf);
+ }*/
+
+#endif
+ exit: return;
+}
+
+static void parseIPv4Address(const unsigned char * ipAddrStr, uint8_t * ipAddr) {
+ size_t index = 0;
+
+ while (*ipAddrStr) {
+ if (isdigit((unsigned char) *ipAddrStr)) {
+ ipAddr[index] *= 10;
+ ipAddr[index] += *ipAddrStr - '0';
+ } else if ((unsigned char) *ipAddrStr == '.') {
+ index++;
+ } else {
+ return;
+ }
+ ipAddrStr++;
+ }
+}
+//=============================================================================
+// Functions
+//=============================================================================
+
+/**
+ * Initialize the CoAP client or server with its IPv4 address and CoAP port
+ *
+ * @param ipAddr
+ * IP Address of host device
+ * @param port
+ * Port of host device
+ * @param mode
+ * Host device is client, server, or client-server
+ *
+ * @return
+ * 0 - success
+ * TBD - TBD error
+ */
+int OCInitCoAP(const char *address, uint16_t port, OCMode mode) {
+
+ int ret = OC_COAP_ERR;
+
+ TODO ("Below should go away and be replaced by OC_LOG");
+ coap_log_t log_level = LOG_DEBUG + 1;
+ OCDevAddr devAddr, mcastAddr;
+ uint8_t ipAddr[4] = { 0 };
+
+ OC_LOG(INFO, TAG, PCF("Entering OCInitCoAP"));
+
+ coap_set_log_level(log_level);
+
+ if (address) {
+ parseIPv4Address((const unsigned char *) address, ipAddr);
+ OC_LOG_V(INFO, TAG, "Parsed IP Address %d.%d.%d.%d",ipAddr[0],ipAddr[1],ipAddr[2],ipAddr[3]);
+ }
+
+ OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], port,
+ &devAddr);
+
+ gCoAPCtx = coap_new_context((coap_address_t*) &devAddr);
+ VERIFY_NON_NULL(gCoAPCtx);
+ if (mode != OC_CLIENT) {
+ OCBuildIPv4Address(coapWKIpAddr[0], coapWKIpAddr[1], coapWKIpAddr[2],
+ coapWKIpAddr[3], COAP_DEFAULT_PORT, &mcastAddr);
+ VERIFY_SUCCESS(
+ coap_join_wellknown_group(gCoAPCtx,
+ (coap_address_t* )&mcastAddr), 0);
+ }
+
+ coap_register_request_handler(gCoAPCtx, HandleCoAPRequests);
+ coap_register_response_handler(gCoAPCtx, HandleCoAPResponses);
+
+ ret = OC_COAP_OK;
+
+ exit: return ret;
+}
+
+/**
+ * Discover OC resources
+ *
+ * @param method - method to perform on the resource
+ * @param Uri - URI of the resource to interact with
+ * @param asyncReturnFunc - asynchronous callback function that is invoked
+ * by the stack when discovery or resource interaction is complete
+ * @return
+ * 0 - success
+ * TBD - TBD error
+ */
+int OCDoCoAPResource(OCMethod method, OCQualityOfService qos, OCToken * token,
+ const char *Uri) {
+
+ int ret = OC_COAP_ERR;
+ coap_pdu_t *pdu = NULL;
+ coap_uri_t uri;
+ coap_tid_t tid = COAP_INVALID_TID;
+ OCDevAddr dst;
+ uint8_t ipAddr[4] = { 0 };
+ coap_list_t *optList = NULL;
+ unsigned char portBuf[BUF_SIZE_PORT];
+ size_t buflen;
+ unsigned char _buf[BUF_SIZE];
+ unsigned char *buf = _buf;
+ int res;
+ uint8_t coapMsgType;
+ uint8_t coapMethod;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCDoCoAPResource"));
+
+ if (Uri) {
+ OC_LOG_V(INFO, TAG, "URI = %s", Uri);
+ }
+
+ VERIFY_SUCCESS(coap_split_uri((unsigned char * )Uri, strlen(Uri), &uri), 0);
+
+// Generate the destination address
+ if (uri.host.length) {
+ parseIPv4Address(uri.host.s, ipAddr);
+ OCBuildIPv4Address(ipAddr[0], ipAddr[1], ipAddr[2], ipAddr[3], uri.port,
+ &dst);
+ } else {
+ goto exit;
+ }
+
+//create appropriate coap options
+ if (uri.port != COAP_DEFAULT_PORT) {
+ coap_insert(&optList,
+ CreateNewOptionNode(COAP_OPTION_URI_PORT,
+ coap_encode_var_bytes(portBuf, uri.port), portBuf),
+ OrderOptions);
+ }
+
+ if (uri.path.length) {
+ buflen = BUF_SIZE;
+ res = coap_split_path(uri.path.s, uri.path.length, buf, &buflen);
+
+ while (res--) {
+ coap_insert(&optList,
+ CreateNewOptionNode(COAP_OPTION_URI_PATH,
+ COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf)),
+ OrderOptions);
+
+ buf += COAP_OPT_SIZE(buf);
+ }
+ }
+
+ if (uri.query.length) {
+ buflen = BUF_SIZE;
+ buf = _buf;
+ res = coap_split_query(uri.query.s, uri.query.length, buf, &buflen);
+
+ while (res--) {
+ coap_insert(&optList,
+ CreateNewOptionNode(COAP_OPTION_URI_QUERY,
+ COAP_OPT_LENGTH(buf), COAP_OPT_VALUE(buf)),
+ OrderOptions);
+
+ buf += COAP_OPT_SIZE(buf);
+ }
+ }
+
+ OC_LOG_V(DEBUG, TAG, "uri.host.s %s", uri.host.s);OC_LOG_V(DEBUG, TAG, "uri.path.s %s", uri.path.s);OC_LOG_V(DEBUG, TAG, "uri.port %d", uri.port);OC_LOG_V(DEBUG, TAG, "uri.query.s %s", uri.query.s);
+
+ coapMsgType = COAP_MESSAGE_NON;
+
+ // Decide message type
+ if (qos == OC_CONFIRMABLE) {
+ coapMsgType = COAP_MESSAGE_CON;
+ OC_LOG(FATAL, TAG, "qos == OC_CONFIRMABLE is not supported in OCDoCoAPResource");
+ }
+
+ // Decide method type
+ if (method == OC_REST_GET) {
+ coapMethod = COAP_REQUEST_GET;
+ } else {
+ OC_LOG(FATAL, TAG, "OCDoCoAPResource only supports method == OC_REST_GET");
+ }
+
+ VERIFY_NON_NULL(gCoAPCtx);
+ pdu = GenerateCoAPPdu(coapMsgType, coapMethod,
+ coap_new_message_id(gCoAPCtx), token->tokenLength, token->token,
+ optList);
+ VERIFY_NON_NULL(pdu);
+
+ TODO ("Post Sprint 1 -- Send Confirmed requests for non-discovery requests");
+ tid = coap_send(gCoAPCtx, (coap_address_t*) &dst, pdu);
+
+ OC_LOG_V(INFO, TAG, "TID %d", tid);
+ if (pdu->hdr->type != COAP_MESSAGE_CON || tid == COAP_INVALID_TID) {
+ OC_LOG(INFO, TAG, "Deleting PDU");
+ coap_delete_pdu(pdu);
+ OC_LOG(INFO, TAG, "Done Deleting PDU");
+ } else {
+ OC_LOG(INFO, TAG, "Keeping PDU, we should handle the retry of this pdu");
+ }
+
+ coap_delete_list(optList);
+
+ ret = OC_COAP_OK;
+
+ exit: return ret;
+}
+
+/**
+ * Stop the CoAP client or server processing
+ *
+ * @return 0 - success, else - TBD error
+ */
+int OCStopCoAP() {
+ OC_LOG(INFO, TAG, PCF("Entering OCStopCoAP"));
+ coap_free_context(gCoAPCtx);
+ gCoAPCtx = NULL;
+ return 0;
+}
+
+/**
+ * Called in main loop of CoAP client or server. Allows low-level CoAP processing of
+ * send, receive, timeout, discovery, callbacks, etc.
+ *
+ * @return 0 - success, else - TBD error
+ */
+int OCProcessCoAP() {
+ OC_LOG(INFO, TAG, PCF("Entering OCProcessCoAP"));
+
+ coap_read(gCoAPCtx, gCoAPCtx->sockfd);
+ if (-1 != gCoAPCtx->sockfd_wellknown) {
+ coap_read(gCoAPCtx, gCoAPCtx->sockfd_wellknown);
+ }
+ coap_dispatch(gCoAPCtx);
+ return 0;
+}
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+//=============================================================================
+// Includes
+//=============================================================================
+/*extern "C" {
+ #include "occoap.h"
+ #include "logger.h"
+}*/
+
+#include "gtest/gtest.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <iostream>
+#include <stdint.h>
+using namespace std;
+
+//=============================================================================
+// Private Variables
+//=============================================================================
+static const char TAG[] = "TestHarness";
+
+//=============================================================================
+// Callback function
+//=============================================================================
+/*void discoverServicesAsync(const char *Url) {
+ OC_LOG_V(INFO, TAG, "Entering discoverServicesAsync. URL = %s", Url);
+}*/
+
+//=============================================================================
+// Tests
+//=============================================================================
+TEST(OCCoapTest, General) {
+ EXPECT_EQ(0, 0);
+}
+
+/*TEST(OCCoapTest, ServiceDiscovery) {
+ OC_LOG(INFO, TAG, "Running ServiceDiscovery");
+
+ EXPECT_EQ(0, OCInitCoAP("127.0.0.1", 0, OC_CLIENT));
+
+ OCCoAPClientCallbackFunction asyncReturnFunc = discoverServicesAsync;
+ EXPECT_EQ(0, OCDoCoAPResource(OC_REST_GET, "oc/core/d", asyncReturnFunc));
+
+ EXPECT_EQ(0, OCProcessCoAP());
+
+ EXPECT_EQ(0, OCStopCoAP());
+}*/
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#ifndef _RANDOM_H
+#define _RANDOM_H
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#if defined(__ANDROID__) || defined(__linux__)
+#include <time.h>
+#elif defined ARDUINO
+//#include <Arduino.h>
+//#include <wiring_analog.c>
+#define ANALOG_IN (15)
+#endif
+
+/**
+ * Seed the random number generator. Seeding depends on platform.
+ * Android and Linux uses current time. Arduino uses Analog reading on pin ANALOG_IN
+ * @retval 0 for Success, otherwise some error value
+ */
+int8_t OCSeedRandom();
+
+/**
+ * Generate a uniformly [0,2^32] distributed random number
+ * @retval On Success, it returns the random value.
+ */
+uint32_t OCGetRandom();
+
+/**
+ * Generate a uniformly [0,2^8] distributed random number
+ * @retval On Success, it returns the random value, otherwise -1 for error.
+ */
+uint8_t OCGetRandomByte(void);
+
+/**
+ * Generate a uniformly distributed 8-bit (byte) array random numbers
+ * @param[out] location
+ * memory location to start filling with random bytes
+ * @param[in] len
+ * length of array to be filled with random bytes
+ */
+void OCFillRandomMem(uint8_t * location, uint16_t len);
+
+#endif //_RANDOM_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#if defined(__ANDROID__) || defined(__linux__)
+#include "fcntl.h"
+#include "unistd.h"
+#endif
+#include "ocrandom.h"
+
+#ifdef ARDUINO
+#include "Arduino.h"
+
+uint8_t GetRandomBitRaw() {
+ return analogRead((uint8_t)ANALOG_IN) & 0x1;
+}
+
+uint8_t GetRandomBitRaw2() {
+ int a = 0;
+ for(;;) {
+ a = GetRandomBitRaw() | (GetRandomBitRaw()<<1);
+ if (a==1){
+ return 0; // 1 to 0 transition: log a zero bit
+ }
+ if (a==2){
+ return 1;// 0 to 1 transition: log a one bit
+ }
+ // For other cases, try again.
+ }
+}
+
+uint8_t GetRandomBit() {
+ int a = 0;
+ for(;;) {
+ a = GetRandomBitRaw2() | (GetRandomBitRaw2()<<1);
+ if (a==1){
+ return 0; // 1 to 0 transition: log a zero bit
+ }
+ if (a==2){
+ return 1;// 0 to 1 transition: log a one bit
+ }
+ // For other cases, try again.
+ }
+}
+#endif
+
+int8_t OCSeedRandom() {
+#if defined(__ANDROID__) || defined(__linux__)
+ int32_t fd = open("/dev/urandom", O_RDONLY);
+ if (fd > 0) {
+ uint32_t randomSeed;
+ uint32_t totalRead = 0; //how many integers were read
+ int32_t currentRead = 0;
+ while (totalRead < sizeof(randomSeed)) {
+ currentRead = read(fd, (uint8_t*) &randomSeed + totalRead,
+ sizeof(randomSeed) - totalRead);
+ if(currentRead > 0){
+ totalRead += currentRead;
+ }
+ }
+ close(fd);
+ srand(randomSeed);
+ return 0;
+ }
+ close(fd);
+ return -1;
+#elif defined ARDUINO
+ uint32_t result =0;
+ uint8_t i;
+ for (i=32; i--;){
+ result += result + GetRandomBit();
+ }
+ randomSeed(result);
+ return 0;
+#endif
+
+}
+
+void OCFillRandomMem(uint8_t * location, uint16_t len) {
+ if(!location){
+ return;
+ }
+ for (; len--;){
+ *location++ = OCGetRandomByte();
+ }
+}
+
+uint32_t OCGetRandom() {
+ uint32_t result = 0;
+ OCFillRandomMem((uint8_t*) &result, 4);
+ return result;
+}
+
+uint8_t OCGetRandomByte(void) {
+#if defined(__ANDROID__) || defined(__linux__)
+ return rand() & 0x00FF;
+#elif defined ARDUINO
+ return random(256) & 0x00FF;
+#endif
+}
--- /dev/null
+# override with `make BUILD=release`
+# default to debug build
+BUILD := debug
+
+# You must create the file "local.propertiessudo" on your local machine which contains any local paths, etc
+# local_settings.mk should NOT be committed to repo
+include ../../local.properties
+# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties
+# Example:
+# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0
+
+GTEST_DIR := $(GTEST_DIR_ANDROID)
+
+# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable
+# contains $(GTEST_DIR)/lib/.libs
+
+CC := $(ANDROID_NDK)/arm-linux-androideabi-gcc
+CXX := $(ANDROID_NDK)/arm-linux-androideabi-g++
+
+PROG := randomtest
+
+SRC_DIR := ../../src
+TEST_DIR:= ../../test/android
+INC_DIR := ../../include
+
+#CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -D TB_LOG
+CC_FLAGS.debug := -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -D TB_LOG
+#CC_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -fpic
+CC_FLAGS := $(CC_FLAGS.$(BUILD))
+
+#CXX_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c++0x -fpic -D TB_LOG
+CXX_FLAGS.debug := -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -D TB_LOG
+#CXX_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fpic
+CXX_FLAGS := $(CXX_FLAGS.$(BUILD))
+
+CFLAGS_ANDROID := -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -DGTEST_HAS_PTHREAD=0
+
+INC := -I$(SRC_DIR)
+INC += -I$(TEST_DIR)
+INC += -I$(INC_DIR)
+INC += -I$(GTEST_DIR)/include
+
+
+# using make's computed variables to select object and bin folders
+# depending on the build type
+OBJ_DIR.debug := ./obj/debug
+OBJ_DIR.release := ./obj/release
+OBJ_DIR := $(OBJ_DIR.$(BUILD))
+
+BIN_DIR.debug := ./bin/debug
+BIN_DIR.release := ./bin/release
+BIN_DIR := $(BIN_DIR.$(BUILD))
+
+C_FILES := $(wildcard $(SRC_DIR)/*.c)
+#CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp)
+CPP_FILES := $(wildcard $(TEST_DIR)/*.cpp)
+OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o)))
+H_FILES := $(wildcard $(TEST_DIR)/*.h)
+H_FILES += $(wildcard $(INC_DIR)/*.h)
+LD_FLAGS := -L/usr/lib
+LD_FLAGS += -L$(GTEST_DIR)/lib/.libs
+LDFLAGS_ANDROID := -march=armv7-a -Wl,--fix-cortex-a8
+
+#LIBS := -lpthread
+#LIBS := -lgtest
+#LIBS += -lgtest_main
+
+LIBS = $(GTEST_DIR)/lib/.libs/libgtest.a $(GTEST_DIR)/lib/.libs/libgtest_main.a
+#LIBS = libgtest.a libgtest_main.a
+
+all: $(PROG)
+
+$(PROG): $(OBJ_FILES)
+ mkdir -p $(BIN_DIR)
+ $(CXX) -o $@ $^ $(LD_FLAGS) $(LDFLAGS_ANDROID) $(LIBS)
+ mv ./$(PROG) ./$(BIN_DIR)
+
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC_DIR)/%.h $(H_FILES)
+ mkdir -p $(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(CFLAGS_ANDROID) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES)
+ mkdir -p $(OBJ_DIR)
+ $(CXX) $(CXX_FLAGS) $(CFLAGS_ANDROID) $(INC) -c -o $@ $<
+
+install: all
+# adb remount
+ adb push $(BIN_DIR)/$(PROG) /data/local/tmp
+
+.PHONY: clean
+clean :
+ rm -rf ./obj/debug/*
+ rm -rf ./obj/release/*
+ rm -rf ./lib/debug/*
+ rm -rf ./lib/release/*
+ rm -rf ./bin/debug/*
+ rm -rf ./bin/release/*
+ rm -rf ./test/tst_*.txt
+
+
+.PHONY: print_vars
+
+print_vars:
+ @echo ""
+ @echo 'BUILD = '$(value BUILD)
+ @echo 'INC = '$(value INC)
+ @echo 'CPP_FILES = '$(value CPP_FILES)
+ @echo 'LIBS = '$(value LIBS)
+
+
--- /dev/null
+
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+extern "C" {
+ #include "ocrandom.h"
+}
+
+#include "gtest/gtest.h"
+#include "math.h"
+
+
+int main(int argc, char* argv[]) {
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
+TEST(RandomGeneration,OCSeedRandom) {
+ EXPECT_EQ((uint32_t )0, OCSeedRandom());
+}
+
+TEST(RandomGeneration,OCGetRandomByte) {
+ uint8_t value = OCGetRandomByte();
+ EXPECT_LE((uint8_t )0, value);
+ EXPECT_GT(pow(2, 8), value);
+}
+
+TEST(RandomGeneration,OCGetRandom) {
+ uint32_t value = OCGetRandom();
+ EXPECT_LE((uint8_t )0, value);
+ EXPECT_GT(pow(2, 32), value);
+}
+
+TEST(RandomGeneration,OCFillRandomMem) {
+ uint16_t ARR_SIZE = 20;
+ uint8_t array[ARR_SIZE];
+ memset(array, 0, ARR_SIZE);
+ OCFillRandomMem(array + 1, ARR_SIZE - 2);
+
+ for (int i = 1; i < ARR_SIZE - 2; i++) {
+ uint8_t value = array[i];
+ EXPECT_LE((uint8_t )0, value);
+ EXPECT_GT(pow(2, 8), value);
+ }
+ EXPECT_EQ((uint8_t )0, array[0]);
+ EXPECT_EQ((uint8_t )0, array[ARR_SIZE - 1]);
+}
+
--- /dev/null
+# Override with `make BUILD=release`
+# default to debug build
+BUILD := debug
+
+# You must create the file "local.propertiessudo" on your local machine which contains any local paths, etc
+# local_settings.mk should NOT be committed to repo
+include ../../local.properties
+
+# Compilers
+CC := avr-gcc
+CXX := avr-g++
+AR := avr-ar
+OBJCopy := avr-objcopy
+
+# Name of testing application
+PROG := randomtest
+C_COMPONENTS_DIR := ocrandom
+
+# Folders that contain C source code
+C_SRC_DIR := $(foreach d, $(C_COMPONENTS_DIR),../../../$d/src)
+
+#Folders that contain C source code related to arduino
+C_SRC_DIR_ARDUINO := $(ARDUINO_DIR)/hardware/arduino/cores/arduino
+
+#Folders that contain CPP source code
+CPP_SRC_DIR := ../../test/arduino
+
+#Folders that contain CPP source code related to arduino
+CPP_SRC_DIR_ARDUINO := $(ARDUINO_DIR)/hardware/arduino/cores/arduino
+
+# Folders that contain Headers
+TEMP_INC_DIR := $(foreach d, $(C_COMPONENTS_DIR),../../../$d/include)
+TEMP_INC_DIR2 := $(foreach d, $(CXX_COMPONENTS_DIR),../../../$d/include)
+INC_DIR := $(TEMP_INC_DIR) $(TEMP_INC_DIR2)
+INC_DIR += $(ARDUINO_DIR)/hardware/arduino/cores/arduino
+INC_DIR += $(ARDUINO_DIR)/hardware/arduino/variants/mega
+INC_CMD = $(foreach d, $(INC_DIR), -I$d)
+
+# Compiler flags specific to arduino
+ARDUINO_FLAGS = -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=156 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -MMD
+
+# Compiler flags
+CC_FLAGS.debug := -c -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -std=c99 -DATMEGA2560 -DTB_LOG
+CC_FLAGS.release := -c -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -std=c99 -DATMEGA2560
+CC_FLAGS := $(CC_FLAGS.$(BUILD))
+
+CXX_FLAGS.debug := -c -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -felide-constructors -std=c++0x -DATMEGA2560 -DTB_LOG
+CXX_FLAGS.release := -c -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -felide-constructors -std=c++0x -DATMEGA2560
+CXX_FLAGS := $(CXX_FLAGS.$(BUILD))
+
+# using make's computed variables to select object and bin folders
+# depending on the build type
+OBJ_DIR.debug := ./obj/debug
+OBJ_DIR.release := ./obj/release
+OBJ_DIR := $(OBJ_DIR.$(BUILD))
+
+BIN_DIR.debug := ./bin/debug
+BIN_DIR.release := ./bin/release
+BIN_DIR := $(BIN_DIR.$(BUILD))
+
+C_FILES := $(shell find $(C_SRC_DIR) -maxdepth 1 -name '*.c')
+CPP_FILES := $(shell find $(CPP_SRC_DIR) -maxdepth 1 -name '*.cpp')
+OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o)))
+
+C_FILES_ARDUINO := $(shell find $(C_SRC_DIR_ARDUINO) -maxdepth 1 -name '*.c')
+CPP_FILES_ARDUINO := $(shell find $(CPP_SRC_DIR_ARDUINO) -maxdepth 1 -name '*.cpp')
+OBJ_FILES_ARDUINO := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES_ARDUINO:.cpp=.o) $(C_FILES_ARDUINO:.c=.o)))
+
+all: $(BIN_DIR)/$(PROG).hex
+
+$(BIN_DIR)/core.a: $(OBJ_FILES_ARDUINO)
+ mkdir -p $(BIN_DIR)
+ $(AR) rcs $@ $^
+ #mv ./core.a ./$(BIN_DIR)
+ @echo ""
+ @echo 'done making core.a'
+
+$(OBJ_DIR)/%.o: $(CPP_SRC_DIR_ARDUINO)/%.cpp
+ mkdir -p $(OBJ_DIR)
+ $(CXX) $(CXX_FLAGS) $(ARDUINO_FLAGS) $(INC_CMD) $< -o $@
+
+$(OBJ_DIR)/%.o: $(CPP_SRC_DIR)/%.cpp
+ mkdir -p $(OBJ_DIR)
+ $(CXX) $(CXX_FLAGS) $(ARDUINO_FLAGS) $(INC_CMD) $< -o $@
+
+$(OBJ_DIR)/%.o: $(C_SRC_DIR_ARDUINO)/%.c
+ mkdir -p $(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(ARDUINO_FLAGS) $(INC_CMD) $< -o $@
+
+$(OBJ_DIR)/%.o: $(C_SRC_DIR)/%.c
+ mkdir -p $(OBJ_DIR)
+ $(CXX) $(CXX_FLAGS) $(ARDUINO_FLAGS) $(INC_CMD) $< -o $@
+
+$(BIN_DIR)/$(PROG).elf: $(OBJ_FILES) $(BIN_DIR)/core.a
+ #$(CC) -Os -Wl,--gc-sections,--relax $(ARDUINO_FLAGS) $< $(BIN_DIR)/core.a -lm -o $@
+ #$(CC) -Os -Wl,--gc-sections,--relax $(ARDUINO_FLAGS) $(OBJ_FILES) $(OBJ_FILES_ARDUINO) -lm -o $@
+ $(CC) -Os -Wl,--gc-sections,--relax $(ARDUINO_FLAGS) $(OBJ_FILES) $(BIN_DIR)/core.a -lm -o $@
+ @echo ""
+ @echo 'done making elf'
+
+$(BIN_DIR)/$(PROG).hex: $(BIN_DIR)/$(PROG).elf
+ $(OBJCopy) -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $< $(BIN_DIR)/$(PROG).eep
+ $(OBJCopy) -O ihex -R .eeprom $< $@
+ @echo ""
+ @echo 'done making hex'
+
+install: all
+ #$(ARDUINO_DIR)/hardware/tools/avrdude -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P/dev/ttyACM0 -b115200 -D -Uflash:w:$(BIN_DIR)/$(PROG).hex:i
+ avrdude -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P/dev/ttyACM0 -b115200 -D -Uflash:w:$(BIN_DIR)/$(PROG).hex:i
+
+.PHONY: clean
+clean :
+ rm -rf ./obj/debug/*
+ rm -rf ./obj/release/*
+ rm -rf ./lib/debug/*
+ rm -rf ./lib/release/*
+ rm -rf ./bin/debug/*
+ rm -rf ./bin/release/*
+ rm -rf ./test/tst_*.txt
+ rm -fr $(BIN_DIR)
+ rm -fr $(OBJ_DIR)
+
+
+.PHONY: print_vars
+print_vars:
+ @echo ""
+ @echo 'BUILD = '$(value BUILD)
+ @echo 'C_SRC_DIR = '$(value C_SRC_DIR)
+ @echo 'C_SRC_DIR_ARDUINO = '$(value C_SRC_DIR_ARDUINO)
+ @echo 'CPP_SRC_DIR = '$(CPP_SRC_DIR)
+ @echo 'CPP_SRC_DIR_ARDUINO = '$(value CPP_SRC_DIR_ARDUINO)
+ @echo 'INC_DIR = '$(INC_DIR)
+ @echo 'H_FILES = '$(H_FILES)
+ @echo 'C_FILES = '$(C_FILES)
+ @echo 'CPP_FILES = '$(CPP_FILES)
+ @echo 'C_FILES_ARDUINO = '$(C_FILES_ARDUINO)
+ @echo 'CPP_FILES_ARDUINO = '$(CPP_FILES_ARDUINO)
+ @echo 'OBJ_FILES = '$(OBJ_FILES)
+ @echo 'OBJ_FILES_ARDUINO = '$(OBJ_FILES_ARDUINO)
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "ocrandom.h"
+#include "math.h"
+#include <Arduino.h>
+
+#define ARR_SIZE (20)
+
+void setup() {
+ Serial.begin(115200);
+ Serial.println("Testing Random Number generator for Arduino");
+
+ Serial.print("Testing OCSeedRandom ... ");
+ if (OCSeedRandom() == 0) {
+ Serial.println("[Success]");
+ } else {
+ Serial.println("[Fail]");
+ }
+
+ Serial.print("Testing OCGetRandomByte ... ");
+ uint8_t value8 = OCGetRandomByte();
+ if (value8 >= 0 && value8 < pow(2, 8)) {
+ Serial.println("[Success]");
+ } else {
+ Serial.println("[Fail]");
+ }
+
+ Serial.print("Testing OCGetRandom ... ");
+ uint32_t value32 = OCGetRandom();
+ if (value32 >= 0 && value32 < pow(2, 32)) {
+ Serial.println("[Success]");
+ } else {
+ Serial.println("[Fail]");
+ }
+
+ Serial.print("Testing OCFillRandomMem ... ");
+ uint8_t array[ARR_SIZE];
+ memset(array, 0, ARR_SIZE);
+ OCFillRandomMem(array + 1, ARR_SIZE - 2);
+ uint8_t overall = 0;
+ uint8_t value82 = 0;
+ for (int i = 1; i <= ARR_SIZE - 2; i++) {
+ value82 = array[i];
+ if (value82 >= 0 && value82 < pow(2, 8)) {
+ overall++;
+ }
+ }
+ if (overall == ARR_SIZE - 2 && array[0] == 0 && array[ARR_SIZE - 1] == 0) {
+ Serial.println("[Success]");
+ } else {
+ Serial.println("[Fail]");
+ Serial.print("overall:");Serial.println(overall);
+ Serial.print("array[0]:");Serial.println(array[0]);
+ Serial.print("array[ARR_SIZE - 1]:");Serial.println(array[ARR_SIZE - 1]);
+ }
+ Serial.println("========DONE TESTING=========");
+
+}
+
+void loop() {
+
+}
+
--- /dev/null
+# override with `make BUILD=release`
+# default to debug build
+BUILD := debug
+
+# You must create the file "local.propertiessudo" on your local machine which contains any local paths, etc
+# local_settings.mk should NOT be committed to repo
+include ../../local.properties
+# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties
+# Example:
+# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0
+
+# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable
+# contains $(GTEST_DIR)/lib/.libs
+
+CC := gcc
+CXX := g++
+
+PROG := randomtest
+
+SRC_DIR := ../../src
+TEST_DIR:= ../../test/linux
+INC_DIR := ../../include
+
+CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -D TB_LOG
+CC_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -fpic
+CC_FLAGS := $(CC_FLAGS.$(BUILD))
+
+CXX_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c++0x -fpic -D TB_LOG
+CXX_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fpic
+CXX_FLAGS := $(CXX_FLAGS.$(BUILD))
+
+INC := -I$(SRC_DIR)
+INC += -I$(TEST_DIR)
+INC += -I$(INC_DIR)
+INC += -I$(GTEST_DIR)/include
+
+
+# using make's computed variables to select object and bin folders
+# depending on the build type
+OBJ_DIR.debug := ./obj/debug
+OBJ_DIR.release := ./obj/release
+OBJ_DIR := $(OBJ_DIR.$(BUILD))
+
+BIN_DIR.debug := ./bin/debug
+BIN_DIR.release := ./bin/release
+BIN_DIR := $(BIN_DIR.$(BUILD))
+
+C_FILES := $(wildcard $(SRC_DIR)/*.c)
+#CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp)
+CPP_FILES := $(wildcard $(TEST_DIR)/*.cpp)
+OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o)))
+H_FILES := $(wildcard $(TEST_DIR)/*.h)
+H_FILES += $(wildcard $(INC_DIR)/*.h)
+LD_FLAGS := -L/usr/lib
+LD_FLAGS += -L$(GTEST_DIR)/lib/.libs
+
+
+LIBS := -lpthread
+LIBS += -lgtest
+LIBS += -lgtest_main
+
+
+all: $(PROG)
+
+$(PROG): $(OBJ_FILES)
+ mkdir -p $(BIN_DIR)
+ $(CXX) -o $@ $^ $(LD_FLAGS) $(LIBS)
+# $(CXX) -o $@ $^ $(GTEST_DIR)/make/gtest_main.a -lpthread
+ mv ./$(PROG) ./$(BIN_DIR)
+
+#$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(SRC_DIR)/%.h $(H_FILES)
+# $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC_DIR)/%.h $(H_FILES)
+ mkdir -p $(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES)
+ mkdir -p $(OBJ_DIR)
+ $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+
+.PHONY: clean
+clean :
+ rm -rf ./obj/debug/*
+ rm -rf ./obj/release/*
+ rm -rf ./lib/debug/*
+ rm -rf ./lib/release/*
+ rm -rf ./bin/debug/*
+ rm -rf ./bin/release/*
+ rm -rf ./test/tst_*.txt
+
+
+.PHONY: print_vars
+
+print_vars:
+ @echo ""
+ @echo 'BUILD = '$(value BUILD)
+ @echo 'INC = '$(value INC)
+ @echo 'CPP_FILES = '$(value CPP_FILES)
+ @echo 'LIBS = '$(value LIBS)
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+
+extern "C" {
+ #include "ocrandom.h"
+}
+
+#include "gtest/gtest.h"
+#include "math.h"
+
+#define ARR_SIZE (20)
+
+int main(int argc, char* argv[]) {
+ testing::InitGoogleTest(&argc, argv);
+ return RUN_ALL_TESTS();
+}
+
+TEST(RandomGeneration,OCSeedRandom) {
+ EXPECT_EQ((uint32_t )0, OCSeedRandom());
+}
+
+TEST(RandomGeneration,OCGetRandomByte) {
+ uint8_t value = OCGetRandomByte();
+ EXPECT_LE((uint8_t )0, value);
+ EXPECT_GT(pow(2, 8), value);
+}
+
+TEST(RandomGeneration,OCGetRandom) {
+ uint32_t value = OCGetRandom();
+ EXPECT_LE((uint8_t )0, value);
+ EXPECT_GT(pow(2, 32), value);
+}
+
+TEST(RandomGeneration,OCFillRandomMem) {
+ uint8_t array[ARR_SIZE];
+ memset(array, 0, ARR_SIZE);
+ OCFillRandomMem(array + 1, ARR_SIZE - 2);
+
+ for (int i = 1; i <= ARR_SIZE - 2; i++) {
+ uint8_t value = array[i];
+ EXPECT_LE((uint8_t )0, value);
+ EXPECT_GT(pow(2, 8), value);
+ }
+ EXPECT_EQ((uint8_t )0, array[0]);
+ EXPECT_EQ((uint8_t )0, array[ARR_SIZE - 1]);
+}
+
--- /dev/null
+To compile for Linux or Android, include ocsocket.c and ocsocket.h in your project.
+Look at the Makefile in ocsocket/test/linux and ocsocket/test/android for compilation dependencies.
+
+To compile for Arduino, include ocsocket_arduino.cpp and ocsocket.h in your project.
+Look at the Makefile in ocsocket/test/arduino for compilation dependencies.
+Note: Patch your Arduino Ethernet Shield library for arduino/libraries/Ethernet/utility/socket.cpp
+to fix recvfrom issue.
+
+Place appropriate local.properties file under test directory to provide local path for \
+GTEST libraries/header files to compile tests.
+
+#Sample local.properties file
+GTEST_LINUX_DIR = /home/gtest-1.7.0
+GTEST_ANDROID_DIR = /home/gtest-1.7.0_android/gtest-1.7.0
+ARDUINO_DIR = /usr/share/arduino
--- /dev/null
+//******************************************************************
+///
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _OCSOCKET_H
+#define _OCSOCKET_H
+
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**@mainpage
+ *
+ * This module is a part of Open Communication Thin-Block SDK.
+ */
+
+
+/**@defgroup socket Socket Interface
+ *
+ * This Socket interface needs to be implemented for every platform on
+ * which CCF TB stack is expected to run. If some functionality is not
+ * available on a platform, implement the method by returning error
+ * ERR_NOT_IMPLEMENTED.
+ */
+
+#define ERR_SUCCESS (0)
+#define ERR_INVALID_INPUT (-900)
+#define ERR_UNKNOWN (-901)
+#define ERR_NOT_IMPLEMENTED (-903)
+
+
+/** This would need to be modified for specific platforms and specific
+ * technologies
+ */
+#define DEV_ADDR_SIZE_MAX (16)
+
+/**
+ *IPv4 or IPv6 addresses
+ */
+#ifndef AF_INET
+#define AF_INET (2)
+#endif //AF_INET
+
+#ifndef AF_INET6
+#define AF_INET6 (10)
+#endif //AF_INET6
+
+
+/**
+ * Data structure to encapsulate IPv4/IPv6/Contiki/lwIP device addresses
+ *
+*/
+typedef struct OCDevAddr {
+ uint32_t size; /**< length of the address stored in addr field. */
+ uint8_t addr[DEV_ADDR_SIZE_MAX]; /**< device address. */
+}OCDevAddr;
+
+//-- OCInitNetworkStack -----------------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to perform any platform specific network
+ * initialization. Optional to implement.
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCInitNetworkStack();
+
+
+//-- OCInitUDP -----------------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to create a new platform specific UDP socket and binds
+ * it to the address provided.
+ *
+ * @param[in] ipAddr
+ * device address with which the new socket will be bind.
+ * @param[out] sockfd
+ * reference to the new socket.
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCInitUDP(OCDevAddr* ipAddr, int32_t* sockfd);
+
+
+
+//-- OCInitUDPMulticast --------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to create a new platform specific UDP socket for
+ * multicast and and binds it to the address provided.
+ *
+ * @param[in] ipmcastaddr
+ * multicast address to which IGMP membership be added.
+ * @param[out] sockfd
+ * reference to the new socket.
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCInitUDPMulticast(OCDevAddr* ipmcastaddr, int32_t* sockfd);
+
+
+
+//-- OCSendTo -------------------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to transmit a UDP datagram to another endpoint.
+ *
+ * @param[in] sockfd
+ * socket to be used for sending the datagram.
+ * @param[in] buf
+ * datagram buffer.
+ * @param[in] bufLen
+ * length of above buffer.
+ * @param[in] flags
+ * flags to be used for sending datagram.
+ * @param[in] addr
+ * endpoint to which datagram needs to be send.
+ *
+ * @retval On Success, it returns the number of bytes send, otherwise
+ * some negative value.
+ */
+//------------------------------------------------------------------------
+int32_t OCSendTo(int32_t sockfd, const uint8_t* buf, uint32_t bufLen, uint32_t flags,
+ OCDevAddr * addr);
+
+
+//-- OCRecvFrom ------------------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to retrieve a UDP datagram from the socket.
+ *
+ * @param[in] sockfd
+ * socket to be used for retrieving the datagram.
+ * @param[in] buf
+ * datagram buffer.
+ * @param[in] bufLen
+ * length of above buffer.
+ * @param[in] flags
+ * flags to be used for receiving datagram.
+ * @param[out] addr
+ * endpoint from which datagram has been received.
+ *
+ * @retval On Success, it returns the number of bytes read from the socket,
+ * otherwise some negative value.
+ */
+//------------------------------------------------------------------------
+int32_t OCRecvFrom(int32_t sockfd, uint8_t* buf, uint32_t bufLen, uint32_t flags,
+ OCDevAddr * addr);
+
+//-- OCClose ---------------------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to close the platform specific socket and release any
+ * system resources associated with it.
+ *
+ * @param[in] sockfd
+ * socket to be closed.
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCClose(int32_t sockfd);
+
+
+//Utility methods
+//-- OCBuildIPv4Address -------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to create the IPv4 dev_addr structure.
+ *
+ * @param[in] a first byte of IPv4 address.
+ * @param[in] b second byte of IPv4 address.
+ * @param[in] c third byte of IPv4 address.
+ * @param[in] d fourth byte of IPv4 address.
+ * @param[in] port port number.
+ * @param[out] ipAddr
+ * dev_addr to be filled with above data.
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d,
+ uint16_t port, OCDevAddr *ipAddr);
+
+
+//-- OCGetInterfaceAddress ------------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to retrieved the IPv4/IPv6 address of the local interface.
+ * If no interface name is provided, this API retrieves the IP address of
+ * the default interface.
+ *
+ * @note currently, only IPv4(AF_INET) is supported for addrType argument.
+ *
+ * @param[in] ifName
+ * interface whose address needs to be retrieved.
+ * @param[in] ifNameLen
+ * length of the interface name
+ * @param[in] addrType
+ * IPv4 or IPv6
+ * @param[out] addrv4
+ * IPv4 address in a.b.c.d format
+ * @param[in] addrLen
+ * size of the buffer at addrv4. Should be at least 16 bytes for an
+ * IPv4 address.
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//-------------------------------------------------------------------------------
+int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType,
+ uint8_t *addrv4, uint32_t addrLen);
+
+
+//-- OCDevAddrToIPv4Addr -------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to retrieved the IPv4 address from OCDev address
+ * data structure.
+ *
+ * @param[in] ipAddr
+ * OCDevAddr address.
+ * @param[out] a first byte of IPv4 address.
+ * @param[out] b second byte of IPv4 address.
+ * @param[out] c third byte of IPv4 address.
+ * @param[out] d fourth byte of IPv4 address.
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
+ uint8_t *c, uint8_t *d );
+
+
+//-- OCDevAddrToPort -------------------------------------------------
+/** @ingroup ocsocket
+ *
+ * This method is used to retrieve the port number from OCDev address
+ * data structure.
+ *
+ * @param[in] ipAddr
+ * OCDevAddr address.
+ * @param[out] port
+ * port number
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif //_OCSOCKET_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <net/if.h>
+#include <errno.h>
+
+#ifdef __ANDROID__
+#include <sys/ioctl.h>
+#else
+#include <ifaddrs.h>
+#include <linux/if_link.h>
+#endif
+
+#include <logger.h>
+#include <ocsocket.h>
+
+/// Module Name
+#define MOD_NAME ("ocsocket")
+
+/// Macro to verify the validity of input argument
+#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, MOD_NAME, #arg " is NULL"); return ERR_INVALID_INPUT;} }
+
+/// Builds a socket interface address using IP address and port number
+int32_t OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port, OCDevAddr *ipAddr)
+{
+ struct sockaddr_in *sa;
+ uint32_t ip = a;
+
+ VERIFY_NON_NULL(ipAddr);
+ memset(ipAddr, 0, sizeof(OCDevAddr));
+
+ ip <<= 8;
+ ip |= b;
+ ip <<= 8;
+ ip |= c;
+ ip <<= 8;
+ ip |= d;
+
+ ipAddr->size = sizeof(struct sockaddr_in);
+ sa = (struct sockaddr_in*)ipAddr->addr;
+ sa->sin_family = AF_INET;
+ sa->sin_addr.s_addr = htonl(ip);
+ sa->sin_port = htons(port);
+
+ return ERR_SUCCESS;
+}
+
+#ifdef __ANDROID__
+/// Retrieves the IP address assigned to specified wireless interface
+int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType,
+ uint8_t *addr, uint32_t addrLen)
+{
+ int32_t ret = ERR_UNKNOWN;
+ int32_t sfd = 0xFFFFFFFF;
+ struct ifreq ifr;
+
+ VERIFY_NON_NULL(addr);
+ VERIFY_NON_NULL(ifName);
+ if (ifNameLen > (IFNAMSIZ - 1) ) {
+ return ERR_INVALID_INPUT;
+ }
+ if (addrType != AF_INET) {
+ return ERR_INVALID_INPUT;
+ }
+
+ sfd = socket(addrType, SOCK_DGRAM, 0);
+ if (sfd < 0) {
+ OC_LOG_V(FATAL, MOD_NAME, "socket API ret val %d", sfd);
+ goto exit;
+ }
+
+ ifr.ifr_addr.sa_family = addrType;
+
+ strncpy(ifr.ifr_name, (const char*)ifName, ifNameLen);
+
+ if (ioctl(sfd, SIOCGIFADDR, &ifr) != 0) {
+ OC_LOG(FATAL, MOD_NAME, "ioctl call failed");
+ goto exit;
+ }
+
+ strncpy((char *)addr,
+ inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr),
+ addrLen);
+ ret = ERR_SUCCESS;
+
+exit:
+ if (sfd >= 0) {
+ close(sfd);
+ }
+ return ret;
+}
+
+#else
+/// Retrieves the IP address assigned to specified wireless interface
+int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType,
+ uint8_t *addr, uint32_t addrLen)
+{
+ struct ifaddrs *myaddrs = NULL, *ifa = NULL;
+ int32_t ret = ERR_UNKNOWN;
+
+ VERIFY_NON_NULL(addr);
+
+ if (addrType != AF_INET) {
+ return ERR_INVALID_INPUT;
+ }
+
+ if(getifaddrs(&myaddrs) != 0) {
+ goto exit;
+ }
+
+ for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next) {
+ if (ifa->ifa_addr == NULL)
+ continue;
+ if (!(ifa->ifa_flags & IFF_UP))
+ continue;
+ if (!(ifa->ifa_flags & IFF_RUNNING))
+ continue;
+
+ if (ifName && ifa->ifa_name) {
+ if(strncmp((const char*)ifName, ifa->ifa_name, ifNameLen) != 0)
+ continue;
+ }
+
+ switch (ifa->ifa_addr->sa_family)
+ {
+ case AF_INET:
+ {
+ struct sockaddr_in *s4 = (struct sockaddr_in *)ifa->ifa_addr;
+ if(inet_ntop(AF_INET, &(s4->sin_addr), (char *)addr, addrLen))
+ ret = ERR_SUCCESS;
+ goto exit;
+ }
+
+ default:
+ continue;
+ }
+ }
+
+exit:
+ if (myaddrs) {
+ freeifaddrs(myaddrs);
+ }
+ return ret;
+}
+#endif //__ANDROID__
+
+/// Creates a BSD socket and binds it specified port for UDP
+int32_t OCInitUDP(OCDevAddr* ipAddr, int32_t *sockfd)
+{
+ int32_t ret = ERR_UNKNOWN;
+ int32_t sfd = 0xFFFFFFFF;
+ int set_option_on = 1;
+
+ VERIFY_NON_NULL(ipAddr);
+ VERIFY_NON_NULL(sockfd);
+
+ OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ );
+ //Create a datagram socket on which to recv/send.
+ sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sfd < 0) {
+ OC_LOG_V(FATAL, MOD_NAME, "socket API ret val %d", sfd);
+ goto exit;
+ }
+
+ if ((ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on,
+ sizeof(set_option_on))) < 0) {
+ OC_LOG(FATAL, MOD_NAME, "setsockopt API failed");
+ goto exit;
+ }
+
+ if (bind(sfd, (struct sockaddr*)ipAddr->addr, ipAddr->size) < 0) {
+ OC_LOG_V(FATAL, MOD_NAME, "bind API failed with errno %s", strerror(errno));
+ goto exit;
+ }
+
+ ret = ERR_SUCCESS;
+
+exit:
+ if ((ret != ERR_SUCCESS) && (sfd >= 0)) {
+ close(sfd);
+ } else {
+ *sockfd = sfd;
+ }
+
+ OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ );
+ return ret;
+}
+
+
+
+/// Creates a BSD socket and binds the specified port for UDP multicast.
+int32_t OCInitUDPMulticast(OCDevAddr* ipmcastaddr, int32_t* sockfd)
+{
+ int32_t ret = ERR_UNKNOWN;
+ int32_t sfd = 0xFFFFFFFF;
+ char loopch=1;
+ int set_option_on = 1;
+
+ VERIFY_NON_NULL(ipmcastaddr);
+ VERIFY_NON_NULL(sockfd);
+
+ OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ );
+ //Create a datagram socket on which to recv/send.
+ sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sfd < 0) {
+ OC_LOG_V(FATAL, MOD_NAME, "socket API ret val %d", sfd);
+ goto exit;
+
+ }
+
+ if ((ret = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on,
+ sizeof(set_option_on))) < 0) {
+ OC_LOG_V(FATAL, MOD_NAME, "setsockopt API for SO_REUSEADDR failed with errno %s", strerror(errno));
+ goto exit;
+ }
+
+ // bind to multicast port
+ struct sockaddr_in sa;
+ struct sockaddr_in *sin;
+
+ sin = (struct sockaddr_in *)(ipmcastaddr->addr);
+ memset(&sa, 0, sizeof(sa));
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = INADDR_ANY;
+ sa.sin_port = sin->sin_port;
+
+ if ((ret = bind(sfd, (struct sockaddr*)&sa, sizeof(sa))) < 0) {
+ OC_LOG_V(FATAL, MOD_NAME, "bind API failed with errno %s", strerror(errno));
+ goto exit;
+ }
+
+ // add membership to receiving socket
+ struct ip_mreq mreq;
+ memset(&mreq, 0, sizeof(struct ip_mreq));
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ mreq.imr_multiaddr.s_addr = sin->sin_addr.s_addr;
+ if ((ret = setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
+ OC_LOG_V(FATAL, MOD_NAME, "setsockopt API for IP_ADD_MEMBERSHIP failed with errno %s", strerror(errno));
+ goto exit;
+ }
+
+ //Enable loopback so we can receive our own datagrams.
+ if ((ret = setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_LOOP,
+ (char *)&loopch, sizeof(loopch))) < 0) {
+ OC_LOG_V(FATAL, MOD_NAME, "setsockopt API for IP_MULTICAST_LOOP failed with errno %s", strerror(errno));
+ goto exit;
+ }
+
+ ret = ERR_SUCCESS;
+
+exit:
+ if (ret == ERR_SUCCESS) {
+ *sockfd = sfd;
+ } else {
+ close(sfd);
+ }
+
+ OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ );
+ return ret;
+}
+
+
+
+/// Send data to requested end-point using UDP socket
+int32_t OCSendTo(int32_t sockfd, const uint8_t* buf, uint32_t bufLen, uint32_t flags,
+ OCDevAddr * ipAddr)
+{
+ int32_t ret;
+
+ VERIFY_NON_NULL(buf);
+ VERIFY_NON_NULL(ipAddr);
+
+ OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ );
+ ret = sendto(sockfd, buf, bufLen, flags,
+ (struct sockaddr*)ipAddr->addr, ipAddr->size);
+
+ OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ );
+ return ret;
+}
+
+
+/// Retrieve any available data from UDP socket. This is a non-blocking call.
+int32_t OCRecvFrom(int32_t sockfd, uint8_t* buf, uint32_t bufLen, uint32_t flags,
+ OCDevAddr * ipAddr)
+{
+ int32_t ret = 0;
+
+ VERIFY_NON_NULL(buf);
+ VERIFY_NON_NULL(ipAddr);
+
+ struct timeval timeout;
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 5000;
+ fd_set reads;
+
+ OC_LOG_V(DEBUG, MOD_NAME, "%s Begin", __func__ );
+
+ FD_ZERO(&reads);
+ FD_SET(sockfd, &reads);
+ ret = select(sockfd + 1, &reads, NULL, NULL, &timeout);
+ if( ret < 0) {
+ OC_LOG(FATAL, MOD_NAME, "select API failed");
+ return ret;
+ }
+ if (!FD_ISSET(sockfd, &reads)) {
+ OC_LOG(DEBUG, MOD_NAME, "No data to read");
+ return ERR_SUCCESS;
+ }
+
+ // Read available data.
+ ret = recvfrom(sockfd, buf, bufLen, flags,
+ (struct sockaddr*)ipAddr->addr, (socklen_t*)&(ipAddr->size));
+ if (ret < 1) {
+ OC_LOG(FATAL, MOD_NAME, "OCRecvFrom ERR");
+ }
+ OC_LOG_V(DEBUG, MOD_NAME, "%s End", __func__ );
+ return ret;
+}
+
+
+/// Close the socket and release all system resources.
+int32_t OCClose(int32_t sockfd)
+{
+ return (close(sockfd));
+}
+
+
+/// Retrieve the IPv4 address embedded inside OCDev address data structure
+int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
+ uint8_t *c, uint8_t *d )
+{
+ struct sockaddr_in *sa;
+ uint32_t ip;
+
+ if ( !ipAddr || !a || !b || !c || !d ) {
+ OC_LOG(FATAL, MOD_NAME, "Invalid argument");
+ return ERR_INVALID_INPUT;
+ }
+
+ sa = (struct sockaddr_in*)ipAddr->addr;
+ ip = ntohl(sa->sin_addr.s_addr);
+ *d = *((uint8_t*)&ip + 0);
+ *c = *((uint8_t*)&ip + 1);
+ *b = *((uint8_t*)&ip + 2);
+ *a = *((uint8_t*)&ip + 3);
+
+ return ERR_SUCCESS;
+}
+
+
+/// Retrieve the IPv4 address embedded inside OCDev address data structure
+int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port)
+{
+ struct sockaddr_in *sa;
+ if ( !ipAddr || !port ) {
+ OC_LOG(FATAL, MOD_NAME, "Invalid argument");
+ return ERR_INVALID_INPUT;
+ }
+
+ sa = (struct sockaddr_in*)ipAddr->addr;
+ *port = ntohs(sa->sin_port);
+
+ return ERR_SUCCESS;
+}
--- /dev/null
+//******************************************************************
+//
+// copyright 2014 intel corporation all rights reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <Arduino.h>
+#include <Ethernet.h>
+#include <socket.h>
+#include <w5100.h>
+#include <ocsocket.h>
+#include <EthernetUdp.h>
+#include <IPAddress.h>
+#include <logger.h>
+
+/// Ensures the literal string to be stored in Flash memory
+#define PCF(str) ((const prog_char*)(F(str)))
+
+/// Module Name
+#define MOD_NAME PCF("ocsocket")
+
+/// Macro to verify the validity of input argument
+#define VERIFY_NON_NULL(arg) { if (!arg) {OC_LOG(FATAL, MOD_NAME, PCF(#arg " is NULL")); \
+ return ERR_INVALID_INPUT;} }
+
+/// Length of the IP address decimal notation string
+#define IPNAMESIZE (16)
+
+/// IPv4 address representation for Arduino Ethernet Shield
+typedef struct {
+ uint32_t size; /// size of IP address and port bytes
+ uint8_t a;
+ uint8_t b;
+ uint8_t c;
+ uint8_t d;
+ uint16_t port;
+} ArduinoAddr;
+
+
+/// Builds a socket interface address using IP address and port number
+int32_t OCBuildIPv4Address(uint8_t a, uint8_t b, uint8_t c, uint8_t d, uint16_t port, OCDevAddr *ipAddr)
+{
+ ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr;
+
+ VERIFY_NON_NULL(ardAddr);
+
+ memset(ardAddr, 0, sizeof(ArduinoAddr));
+
+ ardAddr->size = sizeof(ArduinoAddr) - sizeof(ardAddr->size);
+ ardAddr-> a = a;
+ ardAddr-> b = b;
+ ardAddr-> c = c;
+ ardAddr-> d = d;
+ ardAddr-> port = port;
+
+ return ERR_SUCCESS;
+}
+
+
+/// Retrieves the IP address assigned to Arduino Ethernet shield
+int32_t OCGetInterfaceAddress(uint8_t* ifName, uint32_t ifNameLen, uint16_t addrType,
+ uint8_t *addr, uint32_t addrLen)
+{
+ //TODO : Fix this for scenarios when this API is invoked when device is not connected
+ uint8_t rawIPAddr[4];
+ VERIFY_NON_NULL(addr);
+ if (addrLen < IPNAMESIZE) {
+ OC_LOG(FATAL, MOD_NAME, PCF("OCGetInterfaceAddress: addrLen MUST be atleast 16"));
+ return ERR_INVALID_INPUT;
+ }
+
+ if (addrType != AF_INET) {
+ return ERR_INVALID_INPUT;
+ }
+ W5100.getIPAddress(rawIPAddr);
+ sprintf((char *)addr,"%d.%d.%d.%d", rawIPAddr[0], rawIPAddr[1], rawIPAddr[2], rawIPAddr[3]);
+
+ OC_LOG_BUFFER(INFO, MOD_NAME, addr, addrLen);
+
+ return ERR_SUCCESS;
+}
+
+/// Retrieves a empty socket and bind it for UDP with the input port
+int32_t OCInitUDP(OCDevAddr* ipAddr, int32_t* sockfd)
+{
+ uint8_t state;
+ ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr;
+
+ VERIFY_NON_NULL(ardAddr);
+ VERIFY_NON_NULL(sockfd);
+
+ OC_LOG(DEBUG, MOD_NAME, PCF("OCInitUDP Begin"));
+ //Is any socket available to work with ?
+ *sockfd = -1;
+ for (int i = 0; i < MAX_SOCK_NUM; i++) {
+ state = W5100.readSnSR(i);
+ if (state == SnSR::CLOSED || state == SnSR::FIN_WAIT) {
+ *sockfd = i;
+ break;
+ }
+ }
+
+ if ( *sockfd == -1) {
+ return ERR_UNKNOWN;
+ }
+
+ //Create a datagram socket on which to recv/send.
+ if (!socket(*sockfd, SnMR::UDP, ardAddr->port, 0)) {
+ return ERR_UNKNOWN;
+ }
+
+ OC_LOG(DEBUG, MOD_NAME, PCF("OCInitUDP End"));
+ return ERR_SUCCESS;
+}
+
+
+
+/// Retrieves a empty socket and bind it for UDP with the input multicast ip address/port
+int32_t OCInitUDPMulticast(OCDevAddr* ipMcastMacAddr, int32_t* sockfd)
+{
+ uint8_t state;
+ uint8_t mcastMacAddr[] = { 0x01, 0x00, 0x5E, 0x00, 0x00, 0x00};
+ ArduinoAddr* ardAddr = (ArduinoAddr*)ipMcastMacAddr;
+
+ VERIFY_NON_NULL(ardAddr);
+ VERIFY_NON_NULL(sockfd);
+
+ OC_LOG(DEBUG, MOD_NAME, PCF("OCInitUDPMulticast Begin"));
+ //Is any socket available to work with ?
+ *sockfd = -1;
+ for (int i = 0; i < MAX_SOCK_NUM; i++) {
+ state = W5100.readSnSR(i);
+ if (state == SnSR::CLOSED || state == SnSR::FIN_WAIT) {
+ *sockfd = i;
+ break;
+ }
+ }
+
+ if ( *sockfd == -1) {
+ return ERR_UNKNOWN;
+ }
+
+ //Calculate Multicast MAC address
+ mcastMacAddr[3] = ardAddr->b & 0x7F;
+ mcastMacAddr[4] = ardAddr->c;
+ mcastMacAddr[5] = ardAddr->d;
+ W5100.writeSnDIPR(*sockfd, (uint8_t*)&(ardAddr->a));
+ W5100.writeSnDHAR(*sockfd, mcastMacAddr);
+ W5100.writeSnDPORT(*sockfd, ardAddr->port);
+
+ //Create a datagram socket on which to recv/send.
+ if (!socket(*sockfd, SnMR::UDP, ardAddr->port, SnMR::MULTI)) {
+ return ERR_UNKNOWN;
+ }
+
+ OC_LOG(DEBUG, MOD_NAME, PCF("OCInitUDPMulticast End"));
+ return ERR_SUCCESS;
+}
+
+
+/// Send data to requested end-point using UDP socket
+int32_t OCSendTo(int32_t sockfd, const uint8_t* buf, uint32_t bufLen, uint32_t flags,
+ OCDevAddr * ipAddr)
+{
+ int32_t ret;
+ ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr;
+
+ VERIFY_NON_NULL(buf);
+ VERIFY_NON_NULL(ardAddr);
+
+ OC_LOG(DEBUG, MOD_NAME, PCF("OCSendTo Begin"));
+ ret = sendto( sockfd, buf, bufLen, (uint8_t*)&(ardAddr->a), ardAddr->port);
+ OC_LOG(DEBUG, MOD_NAME, PCF("OCSendTo End"));
+ return ret;
+}
+
+
+/// Retrieve any available data from UDP socket. This is a non-blocking call.
+int32_t OCRecvFrom(int32_t sockfd, uint8_t* buf, uint32_t bufLen, uint32_t flags,
+ OCDevAddr * ipAddr)
+{
+ /**Bug : When there are multiple UDP packets in Wiznet buffer, W5100.getRXReceivedSize
+ * will not return correct length of the first packet.
+ * Fix : Use the patch provided for arduino/libraries/Ethernet/utility/socket.cpp
+ */
+ int32_t ret = 0;
+ uint16_t recvLen;
+ ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr;
+
+ VERIFY_NON_NULL(buf);
+ VERIFY_NON_NULL(ardAddr);
+
+ OC_LOG(DEBUG, MOD_NAME, PCF("OCRecvFrom Begin"));
+ recvLen = W5100.getRXReceivedSize(sockfd);
+ if (recvLen == 0) {
+ return recvLen;
+ }
+
+ // Read available data.
+ ret = recvfrom(sockfd, buf, bufLen, (uint8_t*)&(ardAddr->a), (uint16_t*)&(ardAddr->port));
+ ardAddr->size = sizeof(ArduinoAddr) - sizeof(ardAddr->size);
+
+ OC_LOG(DEBUG, MOD_NAME, PCF("OCRecvFrom End"));
+ return ret;
+}
+
+
+/// Close the socket and release all system resources.
+int32_t OCClose(int32_t sockfd)
+{
+ close(sockfd);
+ return ERR_SUCCESS;
+}
+
+
+/// Retrieve the IPv4 address embedded inside OCDev address data structure
+int32_t OCDevAddrToIPv4Addr(OCDevAddr *ipAddr, uint8_t *a, uint8_t *b,
+ uint8_t *c, uint8_t *d )
+{
+ ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr;
+
+ if ( !ardAddr || !a || !b || !c || !d ) {
+ OC_LOG(FATAL, MOD_NAME, "Invalid argument");
+ return ERR_INVALID_INPUT;
+ }
+
+ *a = ardAddr->a;
+ *b = ardAddr->b;
+ *c = ardAddr->c;
+ *d = ardAddr->d;
+
+ return ERR_SUCCESS;
+}
+
+
+/// Retrieve the IPv4 address embedded inside OCDev address data structure
+int32_t OCDevAddrToPort(OCDevAddr *ipAddr, uint16_t *port)
+{
+ ArduinoAddr* ardAddr = (ArduinoAddr*)ipAddr;
+
+ if ( !ardAddr || !port ) {
+ OC_LOG(FATAL, MOD_NAME, "Invalid argument");
+ return ERR_INVALID_INPUT;
+ }
+
+ *port = ardAddr->port;
+
+ return ERR_SUCCESS;
+}
+
--- /dev/null
+all:
+ $(MAKE) -C android all
+ $(MAKE) -C linux all
+ $(MAKE) -C arduino all
+
+install: all
+ $(MAKE) -C android install
+ $(MAKE) -C arduino install
+
+.PHONY: clean
+
+clean:
+ $(MAKE) -C android clean
+ $(MAKE) -C linux clean
+ $(MAKE) -C arduino clean
+
--- /dev/null
+include ../local.properties
+
+ROOT_DIR = ../../..
+OCSOCK_DIR = $(ROOT_DIR)/ocsocket
+LOGGER_DIR = $(ROOT_DIR)/logger
+BIN_DIR = $(OCSOCK_DIR)/bin/android/
+OBJ_DIR = $(OCSOCK_DIR)/obj/android/
+INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include
+
+CCPLUS=arm-linux-androideabi-g++
+CC=arm-linux-androideabi-gcc
+CFLAGS_ANDROID = -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -DGTEST_HAS_PTHREAD=0
+LDFLAGS_ANDROID = -march=armv7-a -Wl,--fix-cortex-a8 -llog
+
+DEP_LIBS = $(GTEST_ANDROID_DIR)/lib/.libs/libgtest_main.a $(GTEST_ANDROID_DIR)/lib/.libs/libgtest.a
+
+CFLAGS += -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -DTB_LOG
+
+TEST_APP = ocsocket_gtest
+
+COBJ = ocsocket.o logger.o
+
+VPATH = $(OCSOCK_DIR)/src:$(LOGGER_DIR)/src
+
+all: $(TEST_APP)
+ mkdir -p $(BIN_DIR)
+ cp $(TEST_APP) $(BIN_DIR)
+ mkdir -p $(OBJ_DIR)
+ cp *.o $(OBJ_DIR)
+
+%.o: %.c
+ $(CCPLUS) -c $(CFLAGS) $(CFLAGS_ANDROID) $(INC_DIRS) $< -o $@
+
+$(TEST_APP).o: $(TEST_APP).cpp
+ $(CCPLUS) -c $(CFLAGS) $(CFLAGS_ANDROID) $(INC_DIRS) -I$(GTEST_ANDROID_DIR)/include -o $@ $<
+
+$(TEST_APP): $(TEST_APP).o $(DEP_LIBS) $(COBJ)
+ $(CCPLUS) -Os -Wl,--gc-sections $(LDFLAGS_ANDROID) $^ -o $@
+
+install: all
+# adb remount
+ adb push $(BIN_DIR)$(TEST_APP) /data/local/tmp/
+
+.PHONY: clean
+
+clean:
+ rm -f *.o $(TEST_APP) recv
+ rm -fr $(BIN_DIR)
+ rm -fr $(OBJ_DIR)
+
--- /dev/null
+//******************************************************************
+//
+// copyright 2014 intel corporation all rights reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <gtest/gtest.h>
+#include <ocsocket.h>
+#include <logger.h>
+
+#define MOD_NAME ("ocsocket_test")
+#define TEST_PORT_NUM (8888)
+
+unsigned char buf1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05,
+ 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01
+};
+unsigned int buf1_len = sizeof(buf1);
+
+
+unsigned char buf2[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+};
+
+unsigned int buf2_len = sizeof(buf2);
+
+
+TEST(BuildIPv4, Positive) {
+ OCDevAddr ipaddr;
+ EXPECT_EQ(ERR_SUCCESS, OCBuildIPv4Address(224,0,0,251,5353, &ipaddr));
+}
+
+
+TEST(BuildIPv4, InvalidInput) {
+ EXPECT_EQ(ERR_INVALID_INPUT, OCBuildIPv4Address(24,24,24,24,2424, NULL));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCBuildIPv4Address(-24,24,-24,24,2424, NULL));
+}
+
+
+TEST(DevAddrToIPv4Addr, Positive) {
+ OCDevAddr ipaddr;
+ uint8_t a,b,c,d;
+ uint16_t port;
+ OCBuildIPv4Address(1,2,3,4,5353, &ipaddr);
+ EXPECT_EQ(ERR_SUCCESS, OCDevAddrToIPv4Addr(&ipaddr, &a, &b, &c, &d ));
+ EXPECT_TRUE((a == 1) && (b == 2) && (c == 3) && (d ==4));
+ EXPECT_EQ(ERR_SUCCESS, OCDevAddrToPort(&ipaddr, &port ));
+ EXPECT_TRUE(port == 5353);
+}
+
+
+TEST(DevAddrToIPv4Addr, InvalidInput) {
+ OCDevAddr ipaddr;
+ uint8_t a,b,c,d;
+ uint16_t port;
+ OCBuildIPv4Address(1,2,3,4,5353, &ipaddr);
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(NULL, &a, &b, &c, &d ));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(&ipaddr, NULL, &b, &c, &d ));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(NULL, NULL, &b, &c, &d ));
+
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(NULL, &port ));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(&ipaddr, NULL ));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(NULL, NULL ));
+}
+
+
+TEST(GetInterfaceAddress, Positive) {
+ uint8_t addr[20];
+ uint8_t ifname[] = "wlan0";
+ EXPECT_EQ(ERR_SUCCESS, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)));
+ OC_LOG_V(INFO, MOD_NAME, "IPv4 Address: %s\n", addr);
+ //On Android, it is MUST to provide interface name
+ //EXPECT_EQ(0, get_ipv4addr( NULL, 0, addr, sizeof(addr)));
+}
+
+TEST(GetInterfaceAddress, Negative) {
+ uint8_t addr[20];
+ uint8_t ifname[] = "ethxx";
+ EXPECT_EQ(ERR_INVALID_INPUT, OCGetInterfaceAddress( NULL, 0, AF_INET, addr, sizeof(addr)));
+ EXPECT_EQ(ERR_UNKNOWN, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, NULL, sizeof(addr)));
+ EXPECT_EQ(ERR_UNKNOWN, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, 0));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET6, addr, sizeof(addr)));
+}
+
+TEST(InitUDP, Positive) {
+ OCDevAddr ipaddr;
+ int32_t sockfd;
+ uint8_t addr[20];
+ uint8_t ifname[] = "wlan0";
+ uint8_t a,b,c,d;
+
+ OCBuildIPv4Address(0,0,0,0, 0, &ipaddr);
+ EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd));
+ OCClose(sockfd);
+
+ OCBuildIPv4Address(0,0,0,0, 5678, &ipaddr);
+ EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd));
+ OCClose(sockfd);
+
+ OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+ sscanf((const char*)addr, "%d.%d.%d.%d", (int*)&a, (int*)&b, (int*)&c, (int*)&d);
+ OCBuildIPv4Address(a,b,c,d, TEST_PORT_NUM, &ipaddr);
+ EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd));
+ OCClose(sockfd);
+}
+
+
+TEST(InitUDP, Negative) {
+ OCDevAddr ipaddr;
+ int32_t sockfd;
+
+ OCBuildIPv4Address(0,0,0,0, 0, &ipaddr);
+ EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDP(NULL, &sockfd));
+
+ EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDP(&ipaddr, NULL));
+}
+
+
+
+TEST(InitUDPMulticast, Positive) {
+ OCDevAddr ipaddr1;
+ int32_t sfd;
+
+ OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr1); //address to which MEMBERSHIP needs to be added
+ EXPECT_EQ(ERR_SUCCESS, OCInitUDPMulticast(&ipaddr1, &sfd));
+ OCClose(sfd);
+}
+
+
+TEST(InitUDPMulticast, Negative) {
+ OCDevAddr ipaddr1;
+ int32_t sfd;
+
+ OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr1); //address to which MEMBERSHIP needs to be added
+ EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDPMulticast(NULL, &sfd));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDPMulticast(&ipaddr1, NULL));
+}
+
+
+TEST(SendToRecvfromUnicast, Positive) {
+ OCDevAddr ipaddr1, ipaddr2, ipaddr3;
+ int32_t ssfd, rsfd;
+ uint8_t addr[20];
+ uint8_t ifname[] = "wlan0";
+ uint8_t a,b,c,d;
+ //uint8_t tmp1[512];
+
+
+ OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+ sscanf((const char*)addr, "%d.%d.%d.%d", (int*)&a, (int*)&b, (int*)&c, (int*)&d);
+
+ //Create sending socket
+ OCBuildIPv4Address(a, b, c, d, 0, &ipaddr1);
+ OCInitUDP(&ipaddr1, &ssfd);
+
+ //Create receiving socket...i.e. bind to the specific port
+ OCBuildIPv4Address(a,b,c, d+1, TEST_PORT_NUM, &ipaddr2);
+ OCInitUDP(&ipaddr2, &rsfd);
+
+ //Test 1 -- Send 40 bytes
+ //Send the packet to ipaddr2(myself:TEST_PORT_NUM)
+ EXPECT_EQ(buf1_len, OCSendTo(ssfd, buf1, buf1_len, 0, &ipaddr2));
+ //Receive the packet
+ ipaddr3.size = sizeof(ipaddr3.addr);
+ //EXPECT_EQ(buf1_len, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3));
+ //Compare the received buffer with send buffer
+ //EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, buf1_len));
+
+ //Test 2 -- Send 1 byte
+ //Send the packet to ipaddr2(myself:TEST_PORT_NUM)
+ EXPECT_EQ( 1, OCSendTo(ssfd, buf1, 1, 0, &ipaddr2));
+ //Receive the packet
+ ipaddr3.size = sizeof(ipaddr3.addr);
+ //EXPECT_EQ( 1, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3));
+ //Compare the received buffer with send buffer
+ //EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, 1));
+
+ //Test 3 -- Send 320 byte
+ //Send the packet to ipaddr2(myself:TEST_PORT_NUM)
+ EXPECT_EQ(buf2_len, OCSendTo(ssfd, buf2, buf2_len, 0, &ipaddr2));
+ //Receive the packet
+ ipaddr3.size = sizeof(ipaddr3.addr);
+ //EXPECT_EQ(buf2_len, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3));
+ //Compare the received buffer with send buffer
+ //EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf2, buf2_len));
+
+ OCClose(ssfd);
+ OCClose(rsfd);
+}
+
+
+
+TEST(SendToRecvfromMulticast, Positive) {
+ OCDevAddr ipaddr1, ipaddr2, ipaddr3, ipaddr4;
+ int32_t ssfd;
+ uint8_t tmp1[512];
+
+ //Create sending socket
+ OCBuildIPv4Address(0,0,0,0, 5353, &ipaddr1);
+ OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr2); //address to which MEMBERSHIP needs to be added
+ OCInitUDPMulticast(&ipaddr2, &ssfd);
+
+ //build the multicast address to which we need to send the datagram
+ OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr3);
+
+ //Test 1 -- Send 40 bytes
+ EXPECT_EQ(buf1_len, OCSendTo(ssfd, buf1, buf1_len, 0, &ipaddr3));
+ //Receive the packet
+ ipaddr4.size = sizeof(ipaddr4.addr);
+ EXPECT_EQ(buf1_len, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr4));
+ //Compare the received buffer with send buffer
+ EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, buf1_len));
+
+ //Test 2 -- Send 1 byte
+ EXPECT_EQ( 1, OCSendTo(ssfd, buf1, 1, 0, &ipaddr3));
+ //Receive the packet
+ ipaddr4.size = sizeof(ipaddr4.addr);
+ EXPECT_EQ( 1, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr4));
+ //Compare the received buffer with send buffer
+ EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, 1));
+
+ //Test 3 -- Send 320 byte
+ EXPECT_EQ(buf2_len, OCSendTo(ssfd, buf2, buf2_len, 0, &ipaddr3));
+ //Receive the packet
+ ipaddr4.size = sizeof(ipaddr4.addr);
+ EXPECT_EQ(buf2_len, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr3));
+ //Compare the received buffer with send buffer
+ EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf2, buf2_len));
+
+ OCClose(ssfd);
+}
+
--- /dev/null
+include ../local.properties
+
+ROOT_DIR = ../../..
+OCSOCK_DIR = $(ROOT_DIR)/ocsocket
+LOGGER_DIR = $(ROOT_DIR)/logger
+BIN_DIR = $(OCSOCK_DIR)/bin/arduino/
+OBJ_DIR = $(OCSOCK_DIR)/obj/arduino/
+
+#Source directories
+SDIR_ARD_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino
+SDIR_ARD_SPI = $(ARDUINO_DIR)/libraries/SPI
+SDIR_ARD_ETH = $(ARDUINO_DIR)/libraries/Ethernet
+SDIR_ARD_ETH_UTIL = $(ARDUINO_DIR)/libraries/Ethernet/utility
+
+VPATH = $(SDIR_ARD_CORE):$(SDIR_ARD_SPI):$(SDIR_ARD_ETH):$(SDIR_ARD_ETH_UTIL):$(OCSOCK_DIR)/src:$(LOGGER_DIR)/src
+
+#include directories
+IDIR_ARD_CORE = $(ARDUINO_DIR)/hardware/arduino/cores/arduino
+IDIR_ARD_VARIANT = $(ARDUINO_DIR)/hardware/arduino/variants/mega
+IDIR_ARD_SPI = $(ARDUINO_DIR)/libraries/SPI
+IDIR_ARD_ETH = $(ARDUINO_DIR)/libraries/Ethernet
+IDIR_ARD_ETH_UTIL = $(ARDUINO_DIR)/libraries/Ethernet/utility
+
+INC_DIRS = -I$(IDIR_ARD_CORE) -I$(IDIR_ARD_VARIANT) -I$(IDIR_ARD_SPI) -I$(IDIR_ARD_ETH) -I$(IDIR_ARD_ETH_UTIL) -I$(OCSOCK_DIR)/include -I$(LOGGER_DIR)/include
+
+#Compiler/Linker flags
+COPTIONS_ARDUINO = -mmcu=atmega2560 -DF_CPU=16000000L -DARDUINO=156 -DARDUINO_AVR_MEGA2560 -DARDUINO_ARCH_AVR -MMD
+CFLAGS += -c -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -felide-constructors -std=c++0x -DATMEGA2560 -DTB_LOG
+
+#Compilers
+CCPLUS=avr-g++
+CC=avr-gcc
+AR=avr-ar
+RANLIB=avr-ranlib
+
+TESTAPP = ocsocket_test
+
+CORE_COBJ = WInterrupts.o wiring.o wiring_digital.o
+CORE_CPPOBJ = main.o Stream.o WMath.o WString.o HardwareSerial.o Print.o SPI.o IPAddress.o
+ETH_CPPOBJ = Dhcp.o Dns.o Ethernet.o EthernetUdp.o
+ETH_UTIL_CPPOBJ = socket.o w5100.o
+OCSOCKET_CPPOBJ = logger.o ocsocket_arduino.o
+
+all: core.a $(TESTAPP).o $(TESTAPP).elf $(TESTAPP).hex
+ mkdir -p $(BIN_DIR)
+ cp $(TESTAPP).hex $(BIN_DIR)
+ mkdir -p $(OBJ_DIR)
+ cp *.o $(OBJ_DIR)
+ cp *.elf $(OBJ_DIR)
+
+%.o: %.c
+ $(CC) $(CFLAGS) $(COPTIONS_ARDUINO) $(INC_DIRS) $< -o $@
+
+%.o: %.cpp
+ $(CCPLUS) $(CFLAGS) $(COPTIONS_ARDUINO) $(INC_DIRS) $< -o $@
+
+#logger needs to be compiled using C++ compiler
+logger.o: logger.c
+ $(CCPLUS) $(CFLAGS) $(COPTIONS_ARDUINO) $(INC_DIRS) $< -o $@
+
+core.a: $(CORE_COBJ) $(CORE_CPPOBJ) $(ETH_CPPOBJ) $(ETH_UTIL_CPPOBJ)
+ $(AR) rcs $@ $^
+ $(RANLIB) $@
+
+$(TESTAPP).elf: $(TESTAPP).o core.a $(OCSOCKET_CPPOBJ)
+ $(CC) -Os -Wl,--gc-sections,--relax $(COPTIONS_ARDUINO) $^ -lm -o $@
+
+$(TESTAPP).hex: $(TESTAPP).elf
+ avr-objcopy -O ihex -j .eeprom --set-section-flags=.eeprom=alloc,load --no-change-warnings --change-section-lma .eeprom=0 $< $(TESTAPP).eep
+ avr-objcopy -O ihex -R .eeprom $< $@
+
+install: all
+ avrdude -C$(ARDUINO_DIR)/hardware/tools/avrdude.conf -v -v -v -v -patmega2560 -cstk500v2 -P/dev/ttyACM0 -b115200 -D -Uflash:w:$(TESTAPP).hex:i
+
+.PHONY: clean
+
+clean:
+ rm -f *.o *.d *.elf *.eep *.a *.hex *-
+ rm -fr $(BIN_DIR)
+ rm -fr $(OBJ_DIR)
+
--- /dev/null
+//******************************************************************
+//
+// copyright 2014 intel corporation all rights reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <SPI.h>
+#include <Ethernet.h>
+#include <ocsocket.h>
+#include <logger.h>
+
+//Mac address of my ethernet shield
+static uint8_t ETHERNET_MAC[] = {0x90, 0xA2, 0xDA, 0x0F, 0x24, 0xCC };
+//IP address of the peer whom I wish to send some data
+static uint8_t PEER_IP_ADDR[] = {192, 168, 1, 125};
+static uint8_t MULTICAST_IP_ADDR[] = {224, 0, 1, 187};
+
+//Set below to 0 to disable multicast testing
+//#define MCAST_TESTING_EN 1
+
+#define TEST_NUM_PKTS (20)
+#define TEST_PORT_NUM (8888)
+#define MAX_BUF_SIZE (256)
+
+unsigned char TEST_BUF[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+};
+unsigned int TEST_BUF_LEN = sizeof(TEST_BUF);
+
+#define PCF(str) ((const prog_char*)(F(str)))
+
+#define MOD_NAME PCF("ocsocket_test")
+
+#define VERIFY_SUCCESS(op, res) { if (op == res) {OC_LOG(DEBUG, MOD_NAME, PCF(#op " SUCCEEDED"));} \
+ else {OC_LOG(FATAL, MOD_NAME, PCF(#op "!!!! FAILED FAILED FAILED !!!!"));} }
+
+
+//OCGetInterfaceAddress tests
+void test10() {
+ char strAddr[16] = "";
+ VERIFY_SUCCESS(OCGetInterfaceAddress(NULL, 0, AF_INET, (uint8_t*)strAddr, 16), ERR_SUCCESS);
+ OC_LOG(DEBUG, MOD_NAME, PCF("My IP address :"));
+ OC_LOG_BUFFER(INFO, MOD_NAME, (uint8_t*)strAddr, sizeof(strAddr));
+ delay(15000);
+ VERIFY_SUCCESS(OCGetInterfaceAddress(NULL, 0, AF_INET, NULL, 16), ERR_INVALID_INPUT);
+ VERIFY_SUCCESS(OCGetInterfaceAddress(NULL, 0, AF_INET, (uint8_t*)strAddr, 10), ERR_INVALID_INPUT);
+ OC_LOG(DEBUG, MOD_NAME, PCF("test10 - Completed"));
+}
+
+//OCBuildIPv4Address tests
+void test20() {
+ OCDevAddr ipAddr;
+ VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, NULL), ERR_INVALID_INPUT);
+ OC_LOG(DEBUG, MOD_NAME, PCF("test20 - Completed"));
+}
+
+
+void test30() {
+
+ OCDevAddr ipAddr;
+ uint8_t a, b, c, d;
+ uint16_t port;
+ VERIFY_SUCCESS(OCBuildIPv4Address( 1, 2, 3, 4, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCDevAddrToIPv4Addr( &ipAddr, &a, &b, &c, &d), ERR_SUCCESS);
+ if ((a != 1) || (b != 2) || (c !=3) || (d !=4)) {
+ OC_LOG(DEBUG, MOD_NAME, PCF("test30 - Failed !!!"));
+ return;
+ }
+
+ VERIFY_SUCCESS(OCDevAddrToPort( &ipAddr, &port), ERR_SUCCESS);
+ if (port != TEST_PORT_NUM) {
+ OC_LOG(DEBUG, MOD_NAME, PCF("test30 - Failed !!!"));
+ return;
+ }
+ VERIFY_SUCCESS(OCDevAddrToIPv4Addr( NULL, &a, &b, &c, &d), ERR_INVALID_INPUT);
+ VERIFY_SUCCESS(OCDevAddrToPort( &ipAddr, NULL), ERR_INVALID_INPUT);
+ OC_LOG(DEBUG, MOD_NAME, PCF("test30 - Completed"));
+}
+
+//OCInitUDP tests
+void test40() {
+ OCDevAddr ipAddr;
+ int32_t sfd1, sfd2, sfd3, sfd4, sfd5;
+
+ //We should be able to successfully open 4 sockets.
+ VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd1), ERR_SUCCESS);
+
+ VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM + 1, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd2), ERR_SUCCESS);
+
+ VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM + 2, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd3), ERR_SUCCESS);
+
+ VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM + 3, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd4), ERR_SUCCESS);
+
+ //5th socket creation call should FAIL
+ VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM + 4, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd5), ERR_UNKNOWN);
+
+ VERIFY_SUCCESS(OCClose( sfd4), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd5), ERR_SUCCESS);
+
+ VERIFY_SUCCESS(OCClose( sfd1), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCClose( sfd2), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCClose( sfd3), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCClose( sfd5), ERR_SUCCESS);
+ OC_LOG(DEBUG, MOD_NAME, PCF("test40 - Completed"));
+}
+
+
+//OCInitUDPMulticast tests
+void test50() {
+ OCDevAddr ipAddr;
+ int32_t sfd1, sfd2;
+
+ VERIFY_SUCCESS(OCBuildIPv4Address( MULTICAST_IP_ADDR[0], MULTICAST_IP_ADDR[1],
+ MULTICAST_IP_ADDR[2], MULTICAST_IP_ADDR[3], TEST_PORT_NUM, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDPMulticast( &ipAddr, &sfd1), ERR_SUCCESS);
+
+ VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM + 1, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd2), ERR_SUCCESS);
+
+ VERIFY_SUCCESS(OCClose( sfd1), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCClose( sfd2), ERR_SUCCESS);
+ OC_LOG(DEBUG, MOD_NAME, PCF("test50 - Completed"));
+}
+
+
+//OCSendTo -- Unicast tests
+void test60() {
+ OCDevAddr ipAddr, peerAddr;
+ int32_t sfd;
+
+ VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCBuildIPv4Address(PEER_IP_ADDR[0], PEER_IP_ADDR[0],
+ PEER_IP_ADDR[0], PEER_IP_ADDR[0], TEST_PORT_NUM, &peerAddr), ERR_SUCCESS);
+
+ VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd), ERR_SUCCESS);
+ for (int i = 2; i < 300; ) {
+ VERIFY_SUCCESS(OCSendTo(sfd, TEST_BUF, i, 0, &peerAddr), i);
+ i = i + 12;
+
+ delay(100);
+ }
+ VERIFY_SUCCESS(OCClose( sfd), ERR_SUCCESS);
+ OC_LOG(DEBUG, MOD_NAME, PCF("test60 - Completed"));
+}
+
+
+//OCSendTo -- Multicast tests
+void test70() {
+ OCDevAddr ipAddrMcast;
+ int32_t sfd;
+
+ VERIFY_SUCCESS(OCBuildIPv4Address( MULTICAST_IP_ADDR[0], MULTICAST_IP_ADDR[1],
+ MULTICAST_IP_ADDR[2], MULTICAST_IP_ADDR[3], TEST_PORT_NUM, &ipAddrMcast), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDPMulticast( &ipAddrMcast, &sfd), ERR_SUCCESS);
+ for (int i = 2; i < 300; ) {
+ VERIFY_SUCCESS(OCSendTo(sfd, TEST_BUF, i, 0, &ipAddrMcast), i);
+ i = i + 12;
+
+ delay(100);
+ }
+ VERIFY_SUCCESS(OCClose( sfd), ERR_SUCCESS);
+ OC_LOG(DEBUG, MOD_NAME, PCF("test70 - Completed"));
+}
+
+
+
+//End to End - Unicast Send/Recv test
+//Start sample app 'sendrecv' on different Linux box.
+void test80() {
+ OCDevAddr ipAddr, peerAddr;
+ int32_t sfd;
+ int32_t recvLen;
+ uint8_t buf[MAX_BUF_SIZE];
+ uint8_t pktrecv = 0;
+
+ //Unicast
+ VERIFY_SUCCESS(OCBuildIPv4Address( 0, 0, 0, 0, TEST_PORT_NUM, &ipAddr), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDP( &ipAddr, &sfd), ERR_SUCCESS);
+
+ do {
+ recvLen = OCRecvFrom(sfd, buf, MAX_BUF_SIZE, 0, &peerAddr);
+ if (recvLen > 0) {
+ pktrecv++;
+ OC_LOG(DEBUG, MOD_NAME, PCF("Rcvd data from :"));
+ OC_LOG_BUFFER(INFO, MOD_NAME, peerAddr.addr, peerAddr.size);
+ OC_LOG(DEBUG, MOD_NAME, PCF("Data Length :"));
+ OC_LOG_BUFFER(INFO, MOD_NAME, (uint8_t*)&recvLen, sizeof(recvLen));
+
+ VERIFY_SUCCESS(OCSendTo(sfd, buf, recvLen, 0, &peerAddr), recvLen);
+ } else {
+ OC_LOG(DEBUG, MOD_NAME, PCF("No data received"));
+ }
+ delay(500); //delay secs
+ } while (pktrecv < TEST_NUM_PKTS);
+
+ VERIFY_SUCCESS(OCClose(sfd), ERR_SUCCESS);
+ OC_LOG(DEBUG, MOD_NAME, PCF("test80 - Completed"));
+}
+
+
+//End to End - Multicast Send/Recv test
+//Start sample app 'sendrecv' on different Linux box.
+void test90() {
+ OCDevAddr ipAddrMcast, peerAddr;
+ int32_t sfd;
+ int32_t recvLen;
+ uint8_t buf[MAX_BUF_SIZE];
+ uint8_t pktrecv = 0;
+
+ //Multicast
+ VERIFY_SUCCESS(OCBuildIPv4Address( MULTICAST_IP_ADDR[0], MULTICAST_IP_ADDR[1],
+ MULTICAST_IP_ADDR[2], MULTICAST_IP_ADDR[3], TEST_PORT_NUM, &ipAddrMcast), ERR_SUCCESS);
+ VERIFY_SUCCESS(OCInitUDPMulticast( &ipAddrMcast, &sfd), ERR_SUCCESS);
+
+ do {
+
+ recvLen = OCRecvFrom(sfd, buf, MAX_BUF_SIZE, 0, &peerAddr);
+ if (recvLen > 0) {
+ pktrecv++;
+ OC_LOG(DEBUG, MOD_NAME, PCF("Rcvd data from :"));
+ OC_LOG_BUFFER(INFO, MOD_NAME, peerAddr.addr, peerAddr.size);
+ OC_LOG(DEBUG, MOD_NAME, PCF("Data Length :"));
+ OC_LOG_BUFFER(INFO, MOD_NAME, (uint8_t*)&recvLen, sizeof(recvLen));
+
+ VERIFY_SUCCESS(OCSendTo(sfd, buf, recvLen, 0, &ipAddrMcast), recvLen);
+ } else {
+ OC_LOG(DEBUG, MOD_NAME, PCF("No data received"));
+ }
+ delay(500); //delay secs
+ } while (pktrecv < TEST_NUM_PKTS);
+
+ VERIFY_SUCCESS(OCClose(sfd), ERR_SUCCESS);
+ OC_LOG(DEBUG, MOD_NAME, PCF("test90 - Completed"));
+}
+
+
+
+//End to End - 'Simultaneous' Unicast-Multicast Send/Recv test
+//This tests if Arduino Wiznet shield can open 2 independent sockets listening on same port:
+// one for unicast traffic and another for multicast traffic.
+//Start sample app 'sendrecv' on different Linux box.
+void test100() {
+ //TBD
+ //TBD
+ //TBD
+}
+
+
+
+
+
+void setup() {
+
+ Serial.begin(115200);
+
+ Serial.println("Trying to get an IP address using DHCP");
+ if (Ethernet.begin(ETHERNET_MAC) == 0) {
+ Serial.println("Failed to configure Ethernet using DHCP");
+ }
+}
+
+void loop() {
+ test10();
+ test20();
+ test30();
+ test40();
+ test50();
+ test60(); //SendTo --Unicast
+ test70(); //SendTo --Multicast
+ test80(); //End-to-End --Unicast
+ delay(5000);
+ test90(); //End-to-End --Multicast
+
+ do {
+ OC_LOG(DEBUG, MOD_NAME, PCF("All tests Completed"));
+ delay(10000);
+ } while (1);
+}
+
+
--- /dev/null
+
+include ../local.properties
+
+ROOT_DIR = ../../..
+OCSOCK_DIR = $(ROOT_DIR)/ocsocket
+LOGGER_DIR = $(ROOT_DIR)/logger
+BIN_DIR = $(OCSOCK_DIR)/bin/linux/
+OBJ_DIR = $(OCSOCK_DIR)/obj/linux/
+INC_DIRS = -I$(OCSOCK_DIR)/include/ -I$(LOGGER_DIR)/include
+
+CCPLUS = g++
+CC = gcc
+
+CFLAGS += -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -DTB_LOG
+DEP_LIBS = $(GTEST_LINUX_DIR)/lib/.libs/libgtest_main.a $(GTEST_LINUX_DIR)/lib/.libs/libgtest.a
+VPATH = $(OCSOCK_DIR)/src:$(LOGGER_DIR)/src
+
+TEST_APP = ocsocket_gtest
+COBJ = logger.o ocsocket.o
+
+all: $(TEST_APP)
+ mkdir -p $(BIN_DIR)
+ cp $(TEST_APP) $(BIN_DIR)
+ mkdir -p $(OBJ_DIR)
+ cp *.o $(OBJ_DIR)
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $(INC_DIRS) $< -o $@
+
+$(TEST_APP).o: $(TEST_APP).cpp
+ $(CCPLUS) -c $(CFLAGS) -pthread $(INC_DIRS) -I$(GTEST_LINUX_DIR)/include -o $@ $<
+
+$(TEST_APP): $(TEST_APP).o $(DEP_LIBS) $(COBJ)
+ $(CCPLUS) -Os -Wl,--gc-sections $^ -lpthread -o $@
+
+.PHONY: clean
+
+clean:
+ rm -f *.o $(TEST_APP)
+ rm -fr $(BIN_DIR)
+ rm -fr $(OBJ_DIR)
+
+
--- /dev/null
+//******************************************************************
+//
+// copyright 2014 intel corporation all rights reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <gtest/gtest.h>
+#include <ocsocket.h>
+#include <logger.h>
+
+#define MOD_NAME ("ocsocket_test")
+
+#define TEST_PORT_NUM (8888)
+
+unsigned char buf1[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f, 0x6f, 0x67,
+ 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74, 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05,
+ 0x6c, 0x6f, 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01
+};
+unsigned int buf1_len = sizeof(buf1);
+
+
+unsigned char buf2[] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x0b, 0x5f, 0x67, 0x6f,
+ 0x6f, 0x67, 0x6c, 0x65, 0x63, 0x61, 0x73, 0x74,
+ 0x04, 0x5f, 0x74, 0x63, 0x70, 0x05, 0x6c, 0x6f,
+ 0x63, 0x61, 0x6c, 0x00, 0x00, 0x0c, 0x00, 0x01,
+};
+unsigned int buf2_len = sizeof(buf2);
+
+TEST(BuildIPv4, Positive) {
+ OCDevAddr ipaddr;
+ EXPECT_EQ(ERR_SUCCESS, OCBuildIPv4Address(224,0,0,251,5353, &ipaddr));
+}
+
+
+TEST(BuildIPv4, InvalidInput) {
+ EXPECT_EQ(ERR_INVALID_INPUT, OCBuildIPv4Address(24,24,24,24,2424, NULL));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCBuildIPv4Address(-24,24,-24,24,2424, NULL));
+}
+
+TEST(DevAddrToIPv4Addr, Positive) {
+ OCDevAddr ipaddr;
+ uint8_t a,b,c,d;
+ uint16_t port;
+ OCBuildIPv4Address(1,2,3,4,5353, &ipaddr);
+ EXPECT_EQ(ERR_SUCCESS, OCDevAddrToIPv4Addr(&ipaddr, &a, &b, &c, &d ));
+ EXPECT_TRUE((a == 1) && (b == 2) && (c == 3) && (d ==4));
+ EXPECT_EQ(ERR_SUCCESS, OCDevAddrToPort(&ipaddr, &port ));
+ EXPECT_TRUE(port == 5353);
+}
+
+
+TEST(DevAddrToIPv4Addr, InvalidInput) {
+ OCDevAddr ipaddr;
+ uint8_t a,b,c,d;
+ uint16_t port;
+ OCBuildIPv4Address(1,2,3,4,5353, &ipaddr);
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(NULL, &a, &b, &c, &d ));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(&ipaddr, NULL, &b, &c, &d ));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToIPv4Addr(NULL, NULL, &b, &c, &d ));
+
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(NULL, &port ));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(&ipaddr, NULL ));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCDevAddrToPort(NULL, NULL ));
+}
+
+
+
+
+TEST(GetInterfaceAddress, Positive) {
+ uint8_t addr[20];
+ uint8_t ifname[] = "eth0";
+ EXPECT_EQ(ERR_SUCCESS, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)));
+ printf("IPv4 Address: %s\n", addr);
+ EXPECT_EQ(ERR_SUCCESS, OCGetInterfaceAddress( NULL, 0, AF_INET, addr, sizeof(addr)));
+ printf("IPv4 Address: %s\n", addr);
+}
+
+TEST(GetInterfaceAddress, Negative) {
+ uint8_t addr[20];
+ uint8_t ifname[] = "ethxx";
+ EXPECT_EQ(ERR_UNKNOWN, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr)));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, NULL, sizeof(addr)));
+ EXPECT_EQ(ERR_UNKNOWN, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, 0));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET6, addr, sizeof(addr)));
+}
+
+TEST(InitUDP, Positive) {
+ OCDevAddr ipaddr;
+ int32_t sockfd;
+ uint8_t addr[20];
+ uint8_t ifname[] = "eth0";
+ uint8_t a,b,c,d;
+
+ OCBuildIPv4Address(0,0,0,0, 0, &ipaddr);
+ EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd));
+ OCClose(sockfd);
+
+ OCBuildIPv4Address(0,0,0,0, 5678, &ipaddr);
+ EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd));
+ OCClose(sockfd);
+
+ OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+ sscanf((const char*)addr, "%d.%d.%d.%d", (int*)&a, (int*)&b, (int*)&c, (int*)&d);
+ OCBuildIPv4Address(a,b,c,d, TEST_PORT_NUM, &ipaddr);
+ EXPECT_EQ(ERR_SUCCESS, OCInitUDP(&ipaddr, &sockfd));
+ OCClose(sockfd);
+}
+
+
+TEST(InitUDP, Negative) {
+ OCDevAddr ipaddr;
+ int32_t sockfd;
+
+ OCBuildIPv4Address(0,0,0,0, 0, &ipaddr);
+ EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDP(NULL, &sockfd));
+
+ EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDP(&ipaddr, NULL));
+}
+
+
+
+TEST(InitUDPMulticast, Positive) {
+ OCDevAddr ipaddr1;
+ int32_t sfd;
+
+ OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr1); //address to which MEMBERSHIP needs to be added
+ EXPECT_EQ(ERR_SUCCESS, OCInitUDPMulticast(&ipaddr1, &sfd));
+ OCClose(sfd);
+}
+
+
+TEST(InitUDPMulticast, Negative) {
+ OCDevAddr ipaddr1;
+ int32_t sfd;
+
+ OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr1); //address to which MEMBERSHIP needs to be added
+ EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDPMulticast(NULL, &sfd));
+ EXPECT_EQ(ERR_INVALID_INPUT, OCInitUDPMulticast(&ipaddr1, NULL));
+}
+
+
+TEST(SendToRecvfromUnicast, Positive) {
+ OCDevAddr ipaddr1, ipaddr2, ipaddr3;
+ int32_t ssfd, rsfd;
+ uint8_t addr[20];
+ uint8_t ifname[] = "eth0";
+ uint8_t a,b,c,d;
+ uint8_t tmp1[512];
+
+ //Create sending socket
+ OCBuildIPv4Address(0,0,0,0, 0, &ipaddr1);
+ OCInitUDP(&ipaddr1, &ssfd);
+
+ //Create receiving socket...i.e. bind to the specific port
+ OCBuildIPv4Address(0,0,0,0, TEST_PORT_NUM, &ipaddr2);
+ OCInitUDP(&ipaddr2, &rsfd);
+
+ //Since this is a Unit test, we will attempt to send message to ourself at a specific port
+ OCGetInterfaceAddress( ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+ sscanf((const char*)addr, "%d.%d.%d.%d", (int*)&a, (int*)&b, (int*)&c, (int*)&d);
+ OCBuildIPv4Address(a,b,c,d, TEST_PORT_NUM, &ipaddr2);
+
+ //Test 1 -- Send 40 bytes
+ //Send the packet to ipaddr2(myself:TEST_PORT_NUM)
+ EXPECT_EQ(buf1_len, OCSendTo(ssfd, buf1, buf1_len, 0, &ipaddr2));
+ //Receive the packet
+ ipaddr3.size = sizeof(ipaddr3.addr);
+ EXPECT_EQ(buf1_len, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3));
+ //Compare the received buffer with send buffer
+ EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, buf1_len));
+
+ //Test 2 -- Send 1 byte
+ //Send the packet to ipaddr2(myself:TEST_PORT_NUM)
+ EXPECT_EQ( 1, OCSendTo(ssfd, buf1, 1, 0, &ipaddr2));
+ //Receive the packet
+ ipaddr3.size = sizeof(ipaddr3.addr);
+ EXPECT_EQ( 1, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3));
+ //Compare the received buffer with send buffer
+ EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, 1));
+
+ //Test 3 -- Send 320 byte
+ //Send the packet to ipaddr2(myself:TEST_PORT_NUM)
+ EXPECT_EQ(buf2_len, OCSendTo(ssfd, buf2, buf2_len, 0, &ipaddr2));
+ //Receive the packet
+ ipaddr3.size = sizeof(ipaddr3.addr);
+ EXPECT_EQ(buf2_len, OCRecvFrom(rsfd, tmp1, sizeof(tmp1), 0, &ipaddr3));
+ //Compare the received buffer with send buffer
+ EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf2, buf2_len));
+
+ OCClose(ssfd);
+ OCClose(rsfd);
+}
+
+
+TEST(SendToRecvfromMulticast, Positive) {
+ OCDevAddr ipaddr1, ipaddr2, ipaddr3, ipaddr4;
+ int32_t ssfd;
+ uint8_t tmp1[512];
+
+ //Create sending socket
+ OCBuildIPv4Address(0,0,0,0, 5353, &ipaddr1);
+ OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr2); //address to which MEMBERSHIP needs to be added
+ OCInitUDPMulticast(&ipaddr2, &ssfd);
+
+ //build the multicast address to which we need to send the datagram
+ OCBuildIPv4Address(224, 0, 0, 251, 5353, &ipaddr3);
+
+ //Test 1 -- Send 40 bytes
+ EXPECT_EQ(buf1_len, OCSendTo(ssfd, buf1, buf1_len, 0, &ipaddr3));
+ //Receive the packet
+ ipaddr4.size = sizeof(ipaddr4.addr);
+ EXPECT_EQ(buf1_len, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr4));
+ //Compare the received buffer with send buffer
+ EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, buf1_len));
+
+ //Test 2 -- Send 1 byte
+ EXPECT_EQ( 1, OCSendTo(ssfd, buf1, 1, 0, &ipaddr3));
+ //Receive the packet
+ ipaddr4.size = sizeof(ipaddr4.addr);
+ EXPECT_EQ( 1, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr4));
+ //Compare the received buffer with send buffer
+ EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf1, 1));
+
+ //Test 3 -- Send 320 byte
+ EXPECT_EQ(buf2_len, OCSendTo(ssfd, buf2, buf2_len, 0, &ipaddr3));
+ //Receive the packet
+ ipaddr4.size = sizeof(ipaddr4.addr);
+ EXPECT_EQ(buf2_len, OCRecvFrom(ssfd, tmp1, sizeof(tmp1), 0, &ipaddr3));
+ //Compare the received buffer with send buffer
+ EXPECT_EQ(ERR_SUCCESS, memcmp(tmp1, buf2, buf2_len));
+
+ OCClose(ssfd);
+}
+
--- /dev/null
+//******************************************************************
+//
+// copyright 2014 intel corporation all rights reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/select.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <math.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <net/if.h>
+
+#include <ifaddrs.h>
+#include <linux/if_link.h>
+
+#include <signal.h>
+
+//static uint8_t MULTICAST_IP_ADDR[] = {224, 0, 1, 187};
+//static uint32_t TEST_PORT_NUM = 8888;
+
+
+#define MAX_BUF (1024)
+uint8_t g_bfr[] = {
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA,
+ };
+uint32_t g_bfrlen = sizeof(g_bfr);
+
+int multicast_test(int argc, char* argv[])
+{
+ int32_t sfd;
+ char loopch=0;
+ int set_option_on = 1;
+ struct sockaddr_in mcastsock, peer;
+ uint8_t recvbuf[MAX_BUF];
+ uint32_t len, bufLen, fromlen;
+
+ printf("Running multicast tests\n");
+
+ bufLen = atoi(argv[4]);
+ if (bufLen > g_bfrlen) {
+ printf("Warning: Input buffer provided too big. Trimming to supported size\n");
+ bufLen = g_bfrlen;
+ }
+
+ //Create a datagram socket on which to send.
+ sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sfd < 0) {
+ printf("Error in opening datagram socket");
+ return -1;
+ }
+
+ //Initialize the group sockaddr structure with a
+ memset((char *) &mcastsock, 0, sizeof(mcastsock));
+ mcastsock.sin_family = AF_INET;
+ mcastsock.sin_addr.s_addr = inet_addr(argv[2]);
+ mcastsock.sin_port = htons(atoi(argv[3]));
+
+ //Disable loopback so you do not receive your own datagrams.
+ if (setsockopt(sfd, IPPROTO_IP, IP_MULTICAST_LOOP,
+ (char *)&loopch, sizeof(loopch)) < 0) {
+ //printf("setting IP_MULTICAST_LOOP:");
+ close(sfd);
+ return -1;
+ }
+
+ //Play nice with other processes who may be listening at this
+ //port/IP address combination
+ if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (char*) &set_option_on,
+ sizeof(set_option_on)) < 0) {
+ //printf("setting SO_REUSEADDR:");
+ close(sfd);
+ return -1;
+ }
+
+ if (bind(sfd, (sockaddr*)&mcastsock, sizeof(mcastsock)) < 0) {
+ printf("bind returns error");
+ close(sfd);
+ return -1;
+ }
+
+ struct ip_mreq mreq;
+ memset(&mreq, 0, sizeof(struct ip_mreq));
+ mreq.imr_interface.s_addr = htonl(INADDR_ANY);
+ mreq.imr_multiaddr.s_addr = mcastsock.sin_addr.s_addr;
+ if ((setsockopt(sfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *) &mreq, sizeof(mreq))) < 0) {
+ printf("multicast -- adding membership failed");
+ close(sfd);
+ return -1;
+ }
+
+ do {
+ len = sendto(sfd, g_bfr, bufLen, 0,
+ (struct sockaddr*)&mcastsock, sizeof(mcastsock));
+ if (len > 0) {
+ printf ("Send %d bytes to %s\n", len, inet_ntoa(mcastsock.sin_addr));
+ }
+
+ fromlen = sizeof(peer);
+ len = recvfrom(sfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&peer, &fromlen);
+ if (len > 0) {
+ printf("Rcvd %d bytes from %s\n", len, inet_ntoa(peer.sin_addr));
+ }
+
+ sleep(1);
+ } while (true);
+
+ close(sfd);
+ return 0;
+}
+
+
+
+
+int unicast_test(int argc, char* argv[])
+{
+ int32_t sfd;
+ struct sockaddr_in sa, peer;
+ uint8_t recvbuf[MAX_BUF];
+ uint32_t len, bufLen, fromlen;
+
+ printf("Running unicast tests\n");
+
+ bufLen = atoi(argv[4]);
+ if (bufLen > g_bfrlen) {
+ printf("Warning: Input buffer provided too big. Trimming to supported size\n");
+ bufLen = g_bfrlen;
+ }
+
+ sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ if (sfd < 0) {
+ printf("socket API ret val %d\n", sfd);
+ return -1;
+ }
+
+ sa.sin_family = AF_INET;
+ sa.sin_addr.s_addr = INADDR_ANY;
+ sa.sin_port = htons(atoi(argv[3]));
+
+ if (bind(sfd, (struct sockaddr*)&sa, sizeof(sa)) < 0) {
+ printf("bin API ret val %d\n", sfd);
+ close(sfd);
+ return -1;
+ }
+
+ peer.sin_family = AF_INET;
+ inet_aton(argv[2], &peer.sin_addr);
+ peer.sin_port = htons(atoi(argv[3]));
+
+ do {
+ len = sendto(sfd, g_bfr, bufLen, 0,
+ (struct sockaddr*)&peer, sizeof(peer));
+
+ if (len > 0) {
+ printf ("Send %d bytes to %s\n", len, inet_ntoa(peer.sin_addr));
+ }
+
+ fromlen = sizeof(peer);
+ len = recvfrom(sfd, recvbuf, sizeof(recvbuf), 0, (struct sockaddr*)&peer, &fromlen);
+ if (len > 0) {
+ printf("Rcvd %d bytes from %s\n", len, inet_ntoa(peer.sin_addr));
+ }
+
+ sleep(1);
+ } while(true);
+
+ close(sfd);
+ return 0;
+}
+
+
+
+
+int main(int argc, char * argv[])
+{
+
+ if (argc < 5) {
+ printf("Usage: sendrecv <u|m> <ipAddr 192.168.1.107 | 224.0.1.187> <portnum 8888> <pkt_size 200>\n");
+ return -1;
+ }
+
+ if (argv[1][0] == 'u') {
+ unicast_test(argc, argv);
+ } else {
+ multicast_test(argc, argv);
+ }
+
+ return 0;
+}
--- /dev/null
+sendrecv.cpp is a test application for verifying the end to end test for Arduino/Android platforms.
+To compile:
+ g++ -o sendrecv sendrecv.cpp
--- /dev/null
+Build notes
+
+//-------------------------------------------------
+// Linux
+//-------------------------------------------------
+To build, run
+make
+
+To enable logging, ensure that
+-D TB_LOG
+is set in the compiler flags
+
+//-------------------------------------------------
+// Android
+//-------------------------------------------------
+To enable logging for Android, TB_LOG should be defined in the ./jni/Android.mk file as
+
+LOCAL_CFLAGS := -DTB_LOG
+
+//-------------------------------------------------
+// Arduino
+//-------------------------------------------------
+To enable the logger for Arduino, TB_LOG should be defined in
+Properties|C/C++ Build|Settings|Tool Settings|AVR Compiler|Symbols
+and
+Properties|C/C++ Build|Settings|Tool Settings|AVR C++ Compiler|Symbols
+
+Note: when building for Arduino, force the compiler to use avr-g++ to build logger.c. Or rename logger.c to logger.cpp.
+
+Note: when building for Arduino, several warnings are generated when trying to place strings in
+PROGMEM
+"warning: only initialized variables can be placed into program memory area"
+This appears to be a known gcc bug - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+
+#ifndef OC_CLIENT_CB
+#define OC_CLIENT_CB
+
+#include <ocstack.h>
+#include <occoap.h>
+
+typedef struct ClientCB {
+ // callback method defined in application address space
+ OCClientApplicationCBType callBack;
+ // callback context data
+ void * context;
+ // when a response is recvd with this token, above callback will be invoked
+ OCToken * token;
+ // next node in this list
+ struct ClientCB *next;
+} ClientCB;
+
+//-- AddClientCB -----------------------------------------------------------
+/** @ingroup ocstack
+ *
+ * This method is used to add a client callback method in cbList.
+ *
+ * @param[in] cb
+ * address to client callback function.
+ * @param[out] token
+ * address to token.
+ *
+ * @retval 0 for Success, otherwise some error value
+ */
+//------------------------------------------------------------------------
+int AddClientCB(OCCallbackData *cbData, OCToken * token);
+
+//-- DeleteClientCB -----------------------------------------------------------
+/** @ingroup ocstack
+ *
+ * This method is used to remove a callback node from cbList.
+ *
+ * @param[in] cbNode
+ * address to client callback node.
+ */
+//------------------------------------------------------------------------
+void DeleteClientCB(ClientCB *cbNode);
+
+
+//-- GetClientCB -----------------------------------------------------------
+/** @ingroup ocstack
+ *
+ * This method is used to search a cb node in cbList.
+ *
+ * @param[in] token
+ * token to search for.
+ *
+ * @retval address of the node if found, otherwise NULL
+ */
+//------------------------------------------------------------------------
+ClientCB* GetClientCB(OCToken * token);
+
+//-- DeleteClientCBList -----------------------------------------------------------
+/** @ingroup ocstack
+ *
+ * This method is used to clear the cbList.
+ *
+ */
+//------------------------------------------------------------------------
+void DeleteClientCBList();
+
+#endif //OC_CLIENT_CB
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OC_SERVER_REQUEST_H
+#define OC_SERVER_REQUEST_H
+
+#define OC_RSRVD_OC "oc"
+#define OC_RSRVD_PAYLOAD "payload"
+#define OC_RSRVD_HREF "href"
+#define OC_RSRVD_RESOURCE_TYPE "rt"
+#define OC_RSRVD_INTERFACE "if"
+#define OC_RSRVD_OBSERVABLE "obs"
+#define OC_RESOURCE_OBSERVABLE 1
+
+#define OC_RESOURCE_DISCOVERY_URI PCF("/oc/core")
+
+typedef enum {
+ STACK_RES_DISCOVERY_NOFILTER = 0,
+ STACK_RES_DISCOVERY_IF_FILTER,
+ STACK_RES_DISCOVERY_RT_FILTER
+} StackQueryTypes;
+
+OCStackResult processResourceDiscoverReq (const char *request, char *response,
+ uint8_t filterOn, char *filterValue);
+
+OCStackResult validateUrlQuery (char *url, char *query, uint8_t *filterOn, char **filterValue);
+#endif //OC_SERVER_REQUEST_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+//
+
+//-----------------------------------------------------------------------------
+// Internal include file used by lower layers of the OC stack
+//-----------------------------------------------------------------------------
+#ifndef OCSTACKINTERNAL_H_
+#define OCSTACKINTERNAL_H_
+
+//-----------------------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------------------
+#include "ocstack.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+
+//-----------------------------------------------------------------------------
+// Forward declarations
+//-----------------------------------------------------------------------------
+struct rsrc_t;
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+typedef struct resourcetype_t {
+ struct resourcetype_t *next; // linked list; for multiple types on resource
+
+ // Name of the type; this string is ‘.’ (dot) separate list of segments where each segment is a
+ // namespace and the final segment is the type; type and sub-types can be separate with ‘-‘ (dash)
+ // usually only two segments would be defined. Either way this string is meant to be human friendly
+ // and is used opaquely and not parsed by code
+ // This name is used in the “rt=” parameter of a resource description when resources are introspected
+ // and is also use in the <base URI>/types list of available types
+ char *resourcetypename;
+ // An array of strings; each string defines the attribute and attribute data type.
+ // NOTE: this is not the same as the request/response payload representation;
+ // but is the definition of attribute/value pairs that go into the payload
+ char *typerepresentation;
+} OCResourceType;
+
+typedef struct attr_t {
+ struct attr_t *next; // Points to next resource in list
+
+ // The name of the attribute; used to look up the attribute in list;
+ // for a given attribute SHOULD not be changed once assigned
+ const char *attrName;
+ char *attrValue; // value of the attribute as string
+} OCAttribute;
+
+typedef struct resourceinterface_t {
+ struct resourceinterface_t *next; // linked list; for multiple interfaces on resource
+
+ // Name of the interface; this is ‘.’ (dot) separate list of segments where each segment is
+ // a namespace and the final segment is the interface; usually only two segments would be defined.
+ // Either way this string is opaque and not parsed by segment
+ char *name ;
+ // Allowed methods on this resource through this interface
+ // Use the methods in OCMethod to create a bitmap
+ // Example: OC_REST_GET|OC_REST_PUT.
+ uint8_t allowedMethods;
+ // Supported content types to serialize request and response on this interface
+ // (REMOVE for V1 – only jSON for all but core.ll that uses Link Format)
+#if 0
+ char *inputContentType ;
+ char *outputContentType ;
+#endif
+ /*** Future placeholder for access control and policy ***/
+} OCResourceInterface;
+
+typedef struct rsrc_t {
+ struct rsrc_t *next; // Points to next resource in list
+ // Relative path on the device; will be combined with base url to create fully qualified path
+ char *uri;
+ OCResourceType *rsrcType; // Resource type(s); linked list
+ OCResourceInterface *rsrcInterface; // Resource interface(s); linked list
+ OCAttribute *rsrcAttributes; // Resource interface(s); linked list
+ // Array of pointers to resources; can be used to represent a container of resources
+ // (i.e. hierarchies of resources) or for reference resources (i.e. for a resource collection)
+ struct rsrc_t *rsrcResources[MAX_CONTAINED_RESOURCES];
+ //struct rsrc_t *rsrcResources;
+ // Pointer to function that handles the entity bound to the resource.
+ // This handler has to be explicitly defined by the programmer
+ OCEntityHandler entityHandler;
+ // Properties on the resource – defines meta information on the resource
+ OCResourceProperty resourceProperties ; /* ACTIVE, DISCOVERABLE etc */
+ // Pointer to an opaque object where app/user specific data can be placed with the resource;
+ // this could be information for the entity handler between invocations
+ void *context;
+ // NOTE: Methods supported by this resource should be based on the interface targeted
+ // i.e. look into the interface structure based on the query request Can be removed here; place holder for the note above
+ /* method_t methods; */
+} OCResource;
+
+// following structure will be created in occoap and passed up the stack on the server side
+typedef struct {
+ // resourceUrl will be filled in occoap using the path options in received request PDU
+ unsigned char * resourceUrl;
+ // resourceUrl will be filled in occoap using the query options in received request PDU
+ unsigned char * query;
+ // qos is indicating if the request is CON or NON
+ OCQualityOfService qos;
+ // this structure will be passed to entity handler
+ OCEntityHandlerRequest * entityHandlerRequest;
+} OCRequest;
+
+// following structure will be created in occoap and passed up the stack on the client side
+typedef struct {
+ // token is copied from the received response PDU
+ OCToken * token;
+ // this structure will be passed to client
+ OCClientResponse * clientResponse;
+} OCResponse;
+
+//-----------------------------------------------------------------------------
+// Internal function prototypes
+//-----------------------------------------------------------------------------
+
+OCStackResult OCStackHandleReceiveRequest(OCRequest * request);
+void OCStackHandleReceiveResponse(OCResponse * response);
+
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* OCSTACKINTERNAL_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OCSTACK_H_
+#define OCSTACK_H_
+
+#include <netinet/ip.h>
+
+#include <ocsocket.h>
+#include <logger.h>
+#include <ocrandom.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif // __cplusplus
+
+//-----------------------------------------------------------------------------
+// Defines
+//-----------------------------------------------------------------------------
+
+//May want to refactor this in upcoming sprints. Don't want to expose to application layer that lower level stack is using CoAP.
+#define OC_WELL_KNOWN_QUERY PCF("coap://224.0.1.187:5683/.well-known/core")
+#define OC_EXPLICIT_DEVICE_DISCOVERY_URI PCF("coap://224.0.1.187:5683/oc/core?rt=core.led")
+
+#define USE_RANDOM_PORT (0)
+#define MAX_TOKEN_LENGTH (8)
+#define MAX_RESPONSE_LENGTH (128)
+#define MAX_REQUEST_LENGTH (128)
+#define MAX_URI_LENGTH (64)
+#define MAX_QUERY_LENGTH (64)
+#define MAX_CONTAINED_RESOURCES (5)
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+
+/**
+ * Standard RESTful HTTP Methods
+ */
+typedef enum {
+ OC_REST_NOMETHOD = 0,
+ OC_REST_GET = (1 << 0), // Read
+ OC_REST_PUT = (1 << 1), // Write
+ OC_REST_POST = (1 << 2), // Update
+ OC_REST_DELETE = (1 << 3), // Delete
+ OC_REST_OBSERVE = (1 << 4) // Register observe request
+} OCMethod;
+
+/**
+ * Host Mode of Operation
+ */
+typedef enum {
+ OC_CLIENT = 0,
+ OC_SERVER,
+ OC_CLIENT_SERVER
+} OCMode;
+
+/**
+ * Quality of Service
+ */
+typedef enum {
+ OC_NON_CONFIRMABLE = 0,
+ OC_CONFIRMABLE
+} OCQualityOfService;
+
+/**
+ * Resource Properties
+ */
+typedef enum {
+ OC_ACTIVE = (1 << 0), // set == initialized; unset == deleted
+ OC_DISCOVERABLE = (1 << 1), // Discovery of this resource allowed
+ OC_OBSERVABLE = (1 << 2), // Observe allowed
+ OC_SLOW = (1 << 3) // Expect delay in processing requests. Send ACK to request and send response later
+} OCResourceProperty;
+
+/**
+ * Declares Stack Results & Errors
+ */
+typedef enum {
+ OC_STACK_OK = 0,
+ OC_STACK_INVALID_URI,
+ OC_STACK_INVALID_QUERY,
+ OC_STACK_INVALID_IP,
+ OC_STACK_INVALID_PORT,
+ OC_STACK_INVALID_CALLBACK,
+ OC_STACK_INVALID_METHOD,
+ OC_STACK_NO_MEMORY,
+ OC_STACK_COMM_ERROR,
+ OC_STACK_INVALID_PARAM,
+ OC_STACK_NOTIMPL,
+ OC_STACK_NO_RESOURCE, /* resource not found*/
+ OC_STACK_RESOURCE_ERROR, /*ex: not supported method or interface*/
+ OC_STACK_SLOW_RESOURCE,
+ OC_STACK_ERROR
+} OCStackResult;
+
+/**
+ * Handle to an OCResource object owned by the OCStack.
+ */
+typedef void * OCResourceHandle;
+
+typedef struct {
+ uint8_t token[MAX_TOKEN_LENGTH];
+ size_t tokenLength;
+} OCToken;
+
+/**
+ * Incoming requests handled by the server. Requests are passed in as a parameter to the @ref OCEntityHandler callback API.
+ * @brief The @ref OCEntityHandler callback API must be implemented in the application in order to receive these requests.
+ */
+typedef struct {
+ // Associated resource
+ OCResourceHandle resource;
+ // the REST method retrieved from received request PDU
+ OCMethod method;
+ // reqJSON is retrieved from the payload of the received request PDU
+ unsigned const char * reqJSONPayload;
+ // token is copied from the received request PDU
+ OCToken * token;
+ // resJSON is allocated in the stack and will be used by entity handler to fill in its response
+ unsigned char * resJSONPayload;
+ // Length of maximum allowed response
+ uint16_t resJSONPayloadLen;
+}OCEntityHandlerRequest;
+
+/**
+ * Response from queries to remote servers. Queries are made by calling the @ref OCDoResource API.
+ */
+typedef struct {
+ // the is the result of our stack, OCStackResult should contain coap/other error codes;
+ OCStackResult result;
+ // Address of remote server
+ OCDevAddr * addr;
+ // reqJSON is retrieved from the payload of the received request PDU
+ unsigned const char * resJSONPayload;
+}OCClientResponse;
+
+typedef enum {
+ OC_INIT_FLAG = (1 << 0),
+ OC_REQUEST_FLAG = (1 << 1),
+ OC_OBSERVE_FLAG = (1 << 2)
+} OCEntityHandlerFlag; //entity_handler_flag_t ;
+
+// possible returned values from client application
+typedef enum {
+ OC_STACK_DELETE_TRANSACTION = 0,
+ OC_STACK_KEEP_TRANSACTION
+} OCStackApplicationResult;
+
+//-----------------------------------------------------------------------------
+// Callback function definitions
+//-----------------------------------------------------------------------------
+typedef OCStackApplicationResult (* OCClientApplicationCBType)(void *ctx, OCClientResponse * clientResponse);
+
+typedef struct {
+ void *context;
+ OCClientApplicationCBType cb;
+} OCCallbackData;
+
+/**
+ * Application server implementations must implement this callback to consume requests OTA.
+ */
+typedef void (*OCEntityHandler) (OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest);
+
+
+//-----------------------------------------------------------------------------
+// Function prototypes
+//-----------------------------------------------------------------------------
+
+/**
+ * Initialize the OC Stack. Must be called prior to starting the stack.
+ *
+ * @param ipAddr
+ * IP Address of host device
+ * @param port
+ * Port of host device
+ * @param mode
+ * Host device is client, server, or client-server
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack init error
+ */
+OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode);
+
+/**
+ * Stop the OC stack. Use for a controlled shutdown.
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack not initialized
+ */
+OCStackResult OCStop();
+
+/**
+ * Called in main loop of OC client or server. Allows low-level processing of
+ * stack services.
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCProcess();
+
+/**
+ * Discover OC resources.
+ *
+ * @param method - method to perform on the resource
+ * @param requiredUri - URI of the resource to interact with
+ * @param referenceUri - URI of the reference resource
+ * @param request - JSON encoded request
+ * @param qos - quality of service
+ * @param clientApplicationCB- asynchronous callback function that is invoked
+ * by the stack when discovery or resource interaction is complete
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_INVALID_CALLBACK - invalid callback function pointer
+ * OC_STACK_INVALID_METHOD - invalid resource method
+ * OC_STACK_INVALID_URI - invalid required or reference URI
+ */
+OCStackResult OCDoResource(OCMethod method, const char *requiredUri, const char *referenceUri,
+// const char *request, OCQualityOfService qos, OCClientApplicationCBType clientApplicationCB);
+ const char *request, OCQualityOfService qos, OCCallbackData *cbData);
+
+
+
+/**
+ * Create a resource.
+ *
+ * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource
+ * @param resourceTypeName - name of resource type. Example: "core.led"
+ * @param resourceAttributeRepresentation - attribute representation. list of attributes:type, with each pair
+ * separated by semicolons. Example: "state:oc.bt.b;power:oc.bt.i"
+ * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
+ * @param allowedMethods - methods permitted on interface. Example: OC_REST_GET|OC_REST_PUT
+ * @param uri - URI of the resource. Example: "/a/led"
+ * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
+ * @param resourceProperties - properties supported by resource. Example: OC_DISCOVERABLE|OC_OBSERVABLE
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCCreateResource(OCResourceHandle *handle,
+ const char *resourceTypeName,
+ const char *resourceAttributeRepresentation,
+ const char *resourceInterfaceName,
+ uint8_t allowedMethods,
+ const char *uri,
+ OCEntityHandler entityHandler,
+ uint8_t resourceProperties);
+
+/**
+ * Add a resource to a container resource.
+ *
+ * @param containerHandle - handle to the container resource
+ * @param addedResourceHandle - handle to resource to be added to the container resource
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCBindContainedResourceToResource(OCResourceHandle containerHandle, OCResourceHandle addedResourceHandle);
+
+/**
+ * Bind a resourcetype to a resource.
+ *
+ * @param handle - handle to the container resource
+ * @param resourceTypeName - name of resource type. Example: "core.led"
+ * @param resourceAttributeRepresentation - attribute representation. list of attributes:type, with each pair
+ * separated by semicolons. Example: "state:oc.bt.b;power:oc.bt.i"
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
+ const char *resourceTypeName,
+ const char *resourceAttributeRepresentation);
+/**
+ * Bind a resource interface to a resource.
+ *
+ * @param handle - handle to the container resource
+ * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
+ * @param allowedMethods - methods permitted on interface. Example: OC_REST_GET|OC_REST_PUT
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
+ const char *resourceInterfaceName,
+ uint8_t allowedMethods);
+
+/**
+ * Bind an entity handler to the resource.
+ *
+ * @param handle - handle to the resource that the contained resource is to be bound
+ * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCBindResourceHandler(OCResourceHandle handle, OCEntityHandler entityHandler);
+
+/**
+ * Get the number of resources that have been created in the stack.
+ *
+ * @param numResources - pointer to count variable
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+
+ */
+OCStackResult OCGetNumberOfResources(uint8_t *numResources);
+
+/**
+ * Get a resource handle by index.
+ *
+ * @param index - index of resource, 0 to Count - 1
+ *
+ * @return
+ * Resource handle - if found
+ * NULL - if not found
+ */
+OCResourceHandle OCGetResourceHandle(uint8_t index);
+
+/**
+ * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
+ * linked lists.
+ *
+ * @param handle - handle of resource to be deleted
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCDeleteResource(OCResourceHandle handle);
+
+/**
+ * Get the URI of the resource specified by handle.
+ *
+ * @param handle - handle of resource
+ * @return
+ * URI string - if resource found
+ * NULL - resource not found
+ */
+const char *OCGetResourceUri(OCResourceHandle handle);
+
+/**
+ * Get the properties of the resource specified by handle.
+ * NOTE: that after a resource is created, the OC_ACTIVE property is set
+ * for the resource by the stack.
+ *
+ * @param handle - handle of resource
+ * @return
+ * property bitmap - if resource found
+ * NULL - resource not found
+ */
+uint8_t OCGetResourceProperties(OCResourceHandle handle);
+
+/**
+ * Get the number of resource types of the resource.
+ *
+ * @param handle - handle of resource
+ * @param numResourceTypes - pointer to count variable
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle, uint8_t *numResourceTypes);
+
+/**
+ * Get name of resource type of the resource.
+ *
+ * @param handle - handle of resource
+ * @param index - index of resource, 0 to Count - 1
+ *
+ * @return
+ * resource type name - if resource found
+ * NULL - resource not found
+ */
+const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index);
+
+/**
+ * Get attributes of resource type of the resource.
+ *
+ * @param handle - handle of resource
+ * @param index - index of resource, 0 to Count - 1
+ *
+ * @return
+ * resource type attributes - if resource found
+ * NULL - resource not found
+ */
+const char *OCGetResourceAttributeRepresentation(OCResourceHandle handle, uint8_t index);
+
+/**
+ * Get the number of resource interfaces of the resource.
+ *
+ * @param handle - handle of resource
+ * @param numResources - pointer to count variable
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+
+ */
+OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle, uint8_t *numResourceInterfaces);
+
+/**
+ * Get name of resource interface of the resource.
+ *
+ * @param handle - handle of resource
+ * @param index - index of resource, 0 to Count - 1
+ *
+ * @return
+ * resource interface name - if resource found
+ * NULL - resource not found
+ */
+const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index);
+
+/**
+ * Get methods of resource interface of the resource.
+ *
+ * @param handle - handle of resource
+ * @param index - index of resource, 0 to Count - 1
+ *
+ * @return
+ * allowed methods - if resource found
+ * NULL - resource not found
+ */
+uint8_t OCGetResourceInterfaceAllowedMethods(OCResourceHandle handle, uint8_t index);
+
+/**
+ * Get name of resource interface of the resource.
+ *
+ * @param containerHandle - handle of container resource
+ * @param index - index of contained resource, 0 to Count - 1
+ *
+ * @return
+ * handle to contained resource - if resource found
+ * NULL - resource not found
+ */
+OCResourceHandle OCGetContainedResourceHandle(OCResourceHandle containerHandle, uint8_t index);
+
+/**
+ * Get the entity handler for a resource.
+ *
+ * @param handle - handle of resource
+ *
+ * @return
+ * entity handler - if resource found
+ * NULL - resource not found
+ */
+OCEntityHandler OCGetResourceHandler(OCResourceHandle handle);
+
+/**
+ * Notify observers that an observed value has changed.
+ *
+ * **NOTE: This API has NOT been finalized!!!**
+ *
+ * @param handle - handle of resource
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack not initialized
+ */
+OCStackResult OCNotifyObservers(OCResourceHandle handle);
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif /* OCSTACK_H_ */
--- /dev/null
+# override with `make BUILD=release`
+# default to debug build
+BUILD := debug
+
+# You must create the file "local.properties" on your local machine which contains any local paths, etc
+# local.properties should NOT be committed to repo
+include ./local.properties
+# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties
+# Example:
+# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0
+
+# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable
+# contains $(GTEST_DIR)/lib/.libs
+
+CC := gcc
+CXX := g++
+
+PROG := stacktest
+
+SRC_DIR := ./src
+TEST_DIR:= ./test
+INC_DIR := ./include
+LOG_DIR := ../logger
+SOCKET_DIR := ../ocsocket
+COAP_DIR := ../occoap
+RANDOM_DIR := ../ocrandom
+LIBCOAP_DIR := ../libcoap-4.1.1
+UTIL_DIR := ../../../../ccf-utilities/tb
+JSON_DIR := $(UTIL_DIR)/cJSON
+
+CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions -DTB_LOG -DWITH_POSIX -D__USE_MISC
+#CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -D TB_LOG -D WITH_POSIX -D __USE_MISC
+CC_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -fpic
+CC_FLAGS := $(CC_FLAGS.$(BUILD))
+
+CXX_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c++0x -fpic -DTB_LOG
+CXX_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fpic
+CXX_FLAGS := $(CXX_FLAGS.$(BUILD))
+
+INC := -I$(SRC_DIR)
+INC += -I$(SOCKET_DIR)/include
+INC += -I$(TEST_DIR)
+INC += -I$(INC_DIR)
+INC += -I$(INC_DIR)/internal
+INC += -I$(LOG_DIR)/include
+INC += -I$(COAP_DIR)/include
+INC += -I$(RANDOM_DIR)/include
+INC += -I$(JSON_DIR)
+INC += -I$(LIBCOAP_DIR)
+INC += -I$(GTEST_DIR)/include
+
+
+# using make's computed variables to select object and bin folders
+# depending on the build type
+OBJ_DIR.debug := ./obj/debug
+OBJ_DIR.release := ./obj/release
+OBJ_DIR := $(OBJ_DIR.$(BUILD))
+
+BIN_DIR.debug := ./bin/debug
+BIN_DIR.release := ./bin/release
+BIN_DIR := $(BIN_DIR.$(BUILD))
+
+C_FILES := $(wildcard $(SRC_DIR)/*.c)
+C_FILES += $(wildcard $(COAP_DIR)/src/*.c)
+C_FILES += $(wildcard $(JSON_DIR)/*.c)
+
+CPP_FILES := $(wildcard $(TEST_DIR)/*.cpp)
+
+OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o)))
+
+H_FILES := $(wildcard $(TEST_DIR)/*.h)
+H_FILES += $(wildcard $(SOCKET_DIR)/include/*.h)
+H_FILES += $(wildcard $(INC_DIR)/*.h)
+H_FILES += $(wildcard $(INC_DIR)/internal/*.h)
+H_FILES += $(wildcard $(LOG_DIR)/include/*.h)
+H_FILES += $(wildcard $(COAP_DIR)/include/*.h)
+
+#H_FILES += $(wildcard $(LIBCOAP_DIR)/*.h)
+LD_FLAGS := -L/usr/lib
+LD_FLAGS += -L$(GTEST_DIR)/lib/.libs
+
+
+LIBS := -lpthread
+LIBS += -lgtest
+LIBS += -lgtest_main
+
+DEP_LIBS := $(LIBCOAP_DIR)/libcoap.a
+
+all: $(PROG)
+ mkdir -p ./$(OBJ_DIR)
+ mkdir -p ./$(BIN_DIR)
+
+$(PROG): $(OBJ_FILES)
+ $(CXX) -o $@ $^ $(LD_FLAGS) $(LIBS) $(DEP_LIBS)
+ mkdir -p ./$(BIN_DIR)
+ mv ./$(PROG) ./$(BIN_DIR)
+
+#$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h $(H_FILES)
+# $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+#$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(INC_DIR)/%.h $(H_FILES)
+# $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+# ocstack
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.c $(INC_DIR)/%.h $(H_FILES)
+ echo "** Building ocstack"
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+# occlientcb
+$(OBJ_DIR)/occlientcb.o: $(SRC_DIR)/occlientcb.c $(H_FILES)
+ echo "** Building ocstack"
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/ocserverrequest.o: $(SRC_DIR)/ocserverrequest.c $(H_FILES)
+ echo "** Building ocstack"
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+# logger
+$(OBJ_DIR)/%.o: $(LOG_DIR)/src/%.c $(LOG_DIR)/include/%.h $(H_FILES)
+ echo "** Building logger"
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+# occoap
+$(OBJ_DIR)/%.o: $(COAP_DIR)/src/%.c $(COAP_DIR)/include/%.h $(H_FILES)
+ echo "** Building occoap"
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+# ocsocket
+$(OBJ_DIR)/%.o: $(SOCKET_DIR)/src/%.c $(SOCKET_DIR)/include/%.h $(H_FILES)
+ echo "** Building ocsocket"
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+# util/json
+$(OBJ_DIR)/%.o: $(JSON_DIR)/%.c $(JSON_DIR)/%.h $(H_FILES)
+ echo "** Building util/json"
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+# libcoap
+#$(OBJ_DIR)/%.o: $(LIBCOAP_DIR)/%.c $(LIBCOAP_DIR)/%.h $(H_FILES)
+# echo "** Building libcoap"
+# mkdir -p ./$(OBJ_DIR)
+# $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES)
+ mkdir -p ./$(OBJ_DIR)
+ $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+.PHONY: clean
+clean :
+ rm -rf ./obj/debug/*
+ rm -rf ./obj/release/*
+ rm -rf ./lib/*
+ rm -rf ./bin/debug/*
+ rm -rf ./bin/release/*
+
+
+.PHONY: print_vars
+
+print_vars:
+ @echo ""
+ @echo 'BUILD = '$(value BUILD)
+ @echo 'INC = '$(value INC)
+ @echo 'CPP_FILES = '$(value CPP_FILES)
+ @echo 'C_FILES = '$(value C_FILES)
+ @echo 'LIBS = '$(value LIBS)
+ @echo 'OBJ_FILES = '$(value OBJ_FILES)
+ @echo 'SRC_DIR = '$(value SRC_DIR)
+ @echo 'H_FILES = '$(value H_FILES)
+
+
--- /dev/null
+INFO: occlient: Starting occlient on address
+INFO: OCStack: Entering OCInit
+INFO: OCStack: IP Address =
+INFO: OCStack: Client mode
+INFO: OCCoAP: Entering OCInitCoAP
+INFO: OCCoAP: Parsed IP Address 0.0.0.0
+DEBUG: ocsocket: OCInitUDP Begin
+DEBUG: ocsocket: OCInitUDP End
+INFO: OCStack: Entering OCDoResource
+INFO: OCStack: Token generated 8 bytes..........9e:10:4a:13:a3:a1:a6:ab
+INFO: OCCoAP: Entering OCDoCoAPResource
+INFO: OCCoAP: URI = coap://224.0.1.187:5683/oc/core?rt=core.led
+DEBUG: OCCoAP: uri.host.s 224.0.1.187:5683/oc/core?rt=core.led
+DEBUG: OCCoAP: uri.path.s oc/core?rt=core.led
+DEBUG: OCCoAP: uri.port 5683
+DEBUG: OCCoAP: uri.query.s rt=core.led
+v:1 t:1 tkl:8 c:1 id:58622
+DEBUG: ocsocket: OCSendTo Begin
+DEBUG: ocsocket: OCSendTo End
+bytes_written 32
+INFO: OCCoAP: TID 41504
+INFO: OCCoAP: Deleting PDU
+INFO: OCCoAP: Done Deleting PDU
+INFO: OCStack: Done with this function
+INFO: occlient: Entering occlient main loop...
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:36 DEBG coap_read: discarded invalid frame
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:37 DEBG coap_read: discarded invalid frame
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:38 DEBG coap_read: discarded invalid frame
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:39 DEBG coap_read: discarded invalid frame
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:40 DEBG coap_read: discarded invalid frame
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:41 DEBG coap_read: discarded invalid frame
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:42 DEBG coap_read: discarded invalid frame
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:43 DEBG coap_read: discarded invalid frame
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:44 DEBG coap_read: discarded invalid frame
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:45 DEBG coap_read: discarded invalid frame
+INFO: OCStack: Entering OCProcess
+INFO: OCCoAP: Entering OCProcessCoAP
+DEBUG: ocsocket: OCRecvFrom Begin
+DEBUG: ocsocket: No data to read
+Jul 21 15:43:46 DEBG coap_read: discarded invalid frame
+INFO: occlient: Exiting occlient main loop...
+INFO: OCStack: Entering OCStop
+INFO: OCCoAP: Entering OCStopCoAP
--- /dev/null
+# override with `make BUILD=release`
+# default to debug build
+BUILD := debug
+PLATFORM := linux
+CC := gcc
+
+ifeq ($(ROOT_DIR), )
+ROOT_DIR = $(PWD)/../../..
+endif
+
+OUT_DIR = $(PWD)
+
+OCLOGGER_DIR = $(ROOT_DIR)/logger
+OCRANDOM_DIR = $(ROOT_DIR)/ocrandom
+OCSOCKET_DIR = $(ROOT_DIR)/ocsocket
+LCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1
+OCCOAP_DIR = $(ROOT_DIR)/occoap
+OCTBSTACK_DIR = $(ROOT_DIR)/stack
+
+OCLOGGER_INC = $(OCLOGGER_DIR)/include
+OCRANDOM_INC = $(OCRANDOM_DIR)/include
+OCSOCKET_INC = $(OCSOCKET_DIR)/include
+LCOAP_INC = $(LCOAP_DIR)
+OCCOAP_INC = $(OCCOAP_DIR)/include
+OCTBSTACK_INC = $(OCTBSTACK_DIR)/include
+
+INC_DIRS := -I$(OCLOGGER_INC)
+INC_DIRS += -I$(OCRANDOM_INC)
+INC_DIRS += -I$(OCSOCKET_INC)
+INC_DIRS += -I$(LCOAP_INC)
+INC_DIRS += -I$(OCCOAP_INC)
+INC_DIRS += -I$(OCTBSTACK_INC)
+
+CC_FLAGS.debug := -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions \
+ -Wextra -Wno-variadic-macros -pedantic $(INC_DIRS) -L$(ROOT_DIR) -DTB_LOG
+CC_FLAGS.release := -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions \
+ -Wextra -Wno-variadic-macros $(INC_DIRS) -L$(ROOT_DIR)
+
+LDLIBS += -loctbstack
+CPPFLAGS += $(CC_FLAGS.$(BUILD)) $(LDLIBS)
+
+SOURCES += logger.c
+SOURCES += ./occlient.cpp
+SOURCES += ./ocserver.cpp
+
+PROGRAMS += ocserver
+PROGRAMS += occlient
+
+VPATH += $(OCLOGGER_DIR)/src/
+
+all: $(PROGRAMS)
+
+%.o: %.cpp
+ $(CC) -c $(CPPFLAGS) $< -o $@
+
+.PHONY: clean
+
+clean:
+ rm -f *.o $(PROGRAMS)
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <ocstack.h>
+
+static const char * LEVEL[] __attribute__ ((unused)) = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
+char *getResult(OCStackResult result);
+void printToScreen(LogLevel level, const char * tag, const char * logStr);
+void printToScreenV(LogLevel level, const char * tag, const char * format, ...);
+
+#define TAG PCF("occlient")
+#define CTX_VAL 0x99
+
+int gQuitFlag = 0;
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum) {
+ if (signum == SIGINT) {
+ gQuitFlag = 1;
+ }
+}
+
+// This is a function called back when a device is discovered
+//OC_STACK_DELETE_TRANSACTION = 0,
+ //OC_STACK_KEEP_TRANSACTION,
+OCStackApplicationResult clientApplicationCB(void* ctx, OCClientResponse * clientResponse) {
+ printToScreen(INFO, TAG, "Entering clientApplicationCB (Application Layer CB)");
+
+ printToScreenV(INFO, TAG, "StackResult: %s", getResult(clientResponse->result));
+
+ printToScreenV(INFO, TAG, "JSON = %s =============> Discovered", clientResponse->resJSONPayload);
+
+ if(ctx == (void*)CTX_VAL) {
+ printToScreenV(INFO, TAG, "Callback Context recvd successfully");
+ }
+
+
+ return OC_STACK_KEEP_TRANSACTION;
+}
+//This function is called back when a resource is discovered.
+
+int main() {
+ uint8_t addr[20] = {0};
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+ OCCallbackData cbData;
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+ printToScreenV(INFO, TAG, "Starting occlient on address %s",addr);
+
+ /* Initialize OCStack*/
+ if (OCInit((char *) addr, port, OC_CLIENT) != OC_STACK_OK) {
+ printToScreen(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ /* Start a discovery query*/
+ char szQueryUri[64] = { 0 };
+ strcpy(szQueryUri, OC_EXPLICIT_DEVICE_DISCOVERY_URI);
+ cbData.cb = clientApplicationCB;
+ cbData.context = (void*)CTX_VAL;
+ if (OCDoResource(OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData)
+ != OC_STACK_OK) {
+ printToScreen(ERROR, TAG, "OCStack resource error");
+ return 0;
+ }
+
+ // Break from loop with Ctrl+C
+ printToScreen(INFO, TAG, "Entering occlient main loop...");
+ signal(SIGINT, handleSigInt);
+ while (!gQuitFlag) {
+
+ if (OCProcess() != OC_STACK_OK) {
+ printToScreen(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+
+ sleep(1);
+ }
+ printToScreen(INFO, TAG, "Exiting occlient main loop...");
+
+ if (OCStop() != OC_STACK_OK) {
+ printToScreen(ERROR, TAG, "OCStack stop error");
+ }
+
+ return 0;
+}
+
+char *getResult(OCStackResult result) {
+ char resString[40] = {0};
+ strcpy(resString, "Result: ");
+ switch(result) {
+ case OC_STACK_OK:
+ strcat(resString, "OC_STACK_OK");
+ break;
+ case OC_STACK_INVALID_URI:
+ strcat(resString, "OC_STACK_INVALID_URI");
+ break;
+ case OC_STACK_INVALID_IP:
+ strcat(resString, "OC_STACK_INVALID_IP");
+ break;
+ case OC_STACK_INVALID_PORT:
+ strcat(resString, "OC_STACK_INVALID_PORT");
+ break;
+ case OC_STACK_INVALID_CALLBACK:
+ strcat(resString, "OC_STACK_INVALID_CALLBACK");
+ break;
+ case OC_STACK_INVALID_METHOD:
+ strcat(resString, "OC_STACK_INVALID_METHOD");
+ break;
+ case OC_STACK_ERROR:
+ strcat(resString, "OC_STACK_ERROR");
+ break;
+ default:
+ strcat(resString, "UNKNOWN");
+ }
+ return resString;
+}
+void printToScreen(LogLevel level, const char * tag, const char * logStr) {
+ printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
+}
+void printToScreenV(LogLevel level, const char * tag, const char * format, ...) {
+ if (!format || !tag) {
+ return;
+ }
+ char buffer[MAX_LOG_V_BUFFER_SIZE];
+ memset(buffer, 0, sizeof buffer);
+ va_list args;
+ va_start(args, format);
+ vsnprintf(buffer, sizeof buffer - 1, format, args);
+ va_end(args);
+ printToScreen(level, tag, buffer);
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <ocstack.h>
+
+static const char * LEVEL[] __attribute__ ((unused)) = {"DEBUG", "INFO", "WARNING", "ERROR", "FATAL"};
+char *getResult(OCStackResult result);
+void printToScreen(LogLevel level, const char * tag, const char * logStr);
+void printToScreenV(LogLevel level, const char * tag, const char * format, ...);
+
+#define TAG PCF("ocserver")
+
+int gQuitFlag = 0;
+void createLEDResource();
+typedef struct LEDRESOURCE{
+ OCResourceHandle handle;
+ bool power;
+} LEDResource;
+
+static LEDResource LED;
+
+void MyOCEntityHandler (OCEntityHandlerFlag flag, const char *request, char *response, uint16_t maxResponseSize, OCResourceHandle resource) {
+ char* typeOfMessage;
+ switch (flag) {
+ case OC_INIT_FLAG:
+ typeOfMessage = "OC_INIT_FLAG";
+ break;
+ case OC_REQUEST_FLAG:
+ typeOfMessage = "OC_REQUEST_FLAG";
+ break;
+ case OC_OBSERVE_FLAG:
+ typeOfMessage = "OC_OBSERVE_FLAG";
+ break;
+ default:
+ typeOfMessage = "UNKNOWN";
+ }
+ printToScreenV(INFO, TAG, "/nReceiving message type:/n/t %s. /n/nWith request:/n/t %s", typeOfMessage, request);
+}
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum) {
+ if (signum == SIGINT) {
+ gQuitFlag = 1;
+ }
+}
+
+int main() {
+ printToScreen(DEBUG, TAG, "OCServer is starting...");
+ LED = {0};
+ uint8_t addr[20] = {0};
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ printToScreenV(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ if (OCInit((char *) addr, port, OC_SERVER) != OC_STACK_OK) {
+ printToScreen(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ /*
+ * Declare and create the example resource: LED
+ */
+ createLEDResource();
+
+ // Break from loop with Ctrl-C
+ printToScreen(INFO, TAG, "Entering ocserver main loop...");
+ signal(SIGINT, handleSigInt);
+ while (!gQuitFlag) {
+ if (OCProcess() != OC_STACK_OK) {
+ printToScreen(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+ sleep(1);
+ }
+
+ printToScreen(INFO, TAG, "Exiting ocserver main loop...");
+
+ if (OCStop() != OC_STACK_OK) {
+ printToScreen(ERROR, TAG, "OCStack process error");
+ }
+
+ return 0;
+}
+void createLEDResource() {
+ LED.power = false;
+ OCStackResult res = OCCreateResource(&LED.handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE);
+ printToScreenV(INFO, TAG, "Created LED resource with result: %s", getResult(res));
+}
+char *getResult(OCStackResult result) {
+ char resString[40] = {0};
+ strcpy(resString, "Result: ");
+ switch(result) {
+ case OC_STACK_OK:
+ strcat(resString, "OC_STACK_OK");
+ break;
+ case OC_STACK_INVALID_URI:
+ strcat(resString, "OC_STACK_INVALID_URI");
+ break;
+ case OC_STACK_INVALID_IP:
+ strcat(resString, "OC_STACK_INVALID_IP");
+ break;
+ case OC_STACK_INVALID_PORT:
+ strcat(resString, "OC_STACK_INVALID_PORT");
+ break;
+ case OC_STACK_INVALID_CALLBACK:
+ strcat(resString, "OC_STACK_INVALID_CALLBACK");
+ break;
+ case OC_STACK_INVALID_METHOD:
+ strcat(resString, "OC_STACK_INVALID_METHOD");
+ break;
+ case OC_STACK_ERROR:
+ strcat(resString, "OC_STACK_ERROR");
+ break;
+ default:
+ strcat(resString, "UNKNOWN");
+ }
+ return resString;
+}
+void printToScreen(LogLevel level, const char * tag, const char * logStr) {
+ printf("%s: %s: %s\n", LEVEL[level], tag, logStr);
+}
+void printToScreenV(LogLevel level, const char * tag, const char * format, ...) {
+ if (!format || !tag) {
+ return;
+ }
+ char buffer[MAX_LOG_V_BUFFER_SIZE];
+ memset(buffer, 0, sizeof buffer);
+ va_list args;
+ va_start(args, format);
+ vsnprintf(buffer, sizeof buffer - 1, format, args);
+ va_end(args);
+ printToScreen(level, tag, buffer);
+}
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include "occlientcb.h"
+#include "utlist.h"
+#include "logger.h"
+#include <string.h>
+
+/// Module Name
+#define MOD_NAME PCF("occlientcb")
+
+static struct ClientCB *cbList = NULL;
+
+int AddClientCB(OCCallbackData* cbData, OCToken * token) {
+ ClientCB *cbNode;
+ cbNode = (ClientCB*)malloc(sizeof(ClientCB));
+ if (cbNode) {
+ cbNode->callBack = cbData->cb;
+ cbNode->context = cbData->context;
+ cbNode->token = token;
+ LL_APPEND(cbList, cbNode);
+ return OC_STACK_OK;
+ }
+ return OC_STACK_NO_MEMORY;
+}
+
+void DeleteClientCB(ClientCB * cbNode) {
+ LL_DELETE(cbList, cbNode);
+ free(cbNode->token);
+ free(cbNode);
+}
+
+ClientCB* GetClientCB(OCToken *token) {
+ ClientCB* out;
+ LL_FOREACH(cbList, out) {
+ if((out->token->tokenLength == token->tokenLength) && (memcmp(out->token->token, token->token, token->tokenLength) == 0) ) {
+ return out;
+ }
+ }
+ OC_LOG(INFO, MOD_NAME, PCF("Callback Not found !!"));
+ return NULL;
+}
+
+
+void DeleteClientCBList() {
+ ClientCB* out;
+ ClientCB* tmp;
+ LL_FOREACH_SAFE(cbList, out, tmp) {
+ DeleteClientCB(out);
+ }
+ cbList = NULL;
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "ocserverrequest.h"
+#include "debug.h"
+#include "cJSON.h"
+
+// Module Name
+#define MOD_NAME PCF("ocserverrequest")
+
+#define TAG PCF("OCStackServerRequest")
+
+#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
+ TAG, PCF(#arg " is NULL")); return (retVal); } }
+
+extern OCResource *headResource;
+
+OCStackResult processResourceDiscoverReq (const char *request, char *response,
+ uint8_t filterOn, char *filterValue)
+{
+ OCResource *resourcePtr = headResource;
+ OCResourceType *resourceTypePtr;
+ OCResourceInterface *interfacePtr;
+ cJSON *ocObj, *pLoadObj, *resArray, *resObj, *rtArray;
+ char *jsonStr;
+ uint8_t encodeRes = 0;
+
+ ocObj = cJSON_CreateObject();
+ cJSON_AddItemToObject (ocObj, OC_RSRVD_OC, pLoadObj = cJSON_CreateObject());
+ cJSON_AddItemToObject (pLoadObj, OC_RSRVD_PAYLOAD, resArray = cJSON_CreateArray());
+
+ while (resourcePtr != NULL)
+ {
+ encodeRes = 0;
+ if (filterOn == STACK_RES_DISCOVERY_RT_FILTER) {
+ resourceTypePtr = resourcePtr->rsrcType;
+ while (resourceTypePtr != NULL) {
+ if (strcmp (resourceTypePtr->resourcetypename, filterValue) == 0) {
+ encodeRes = 1;
+ break;
+ }
+ resourceTypePtr = resourceTypePtr->next;
+ }
+ } else if (filterOn == STACK_RES_DISCOVERY_IF_FILTER) {
+ interfacePtr = resourcePtr->rsrcInterface;
+ while (interfacePtr != NULL) {
+ if (strcmp (interfacePtr->name, filterValue) == 0) {
+ encodeRes = 1;
+ break;
+ }
+ interfacePtr = interfacePtr->next;
+ }
+ } else if (filterOn == STACK_RES_DISCOVERY_NOFILTER) {
+ encodeRes = 1;
+ } else {
+ //TODO: Unsupported query filter
+ return OC_STACK_INVALID_QUERY;
+ }
+
+ if (encodeRes) {
+ cJSON_AddItemToArray (resArray, resObj = cJSON_CreateObject());
+ // Add URIs
+ cJSON_AddItemToObject (resObj, OC_RSRVD_HREF, cJSON_CreateString(resourcePtr->uri));
+ // Add resource types
+ cJSON_AddItemToObject (resObj, OC_RSRVD_RESOURCE_TYPE, rtArray = cJSON_CreateArray());
+ resourceTypePtr = resourcePtr->rsrcType;
+ while (resourceTypePtr != NULL) {
+ cJSON_AddItemToArray (rtArray,
+ cJSON_CreateString(resourceTypePtr->resourcetypename));
+ resourceTypePtr = resourceTypePtr->next;
+ }
+ // Add interface types
+ cJSON_AddItemToObject (resObj, OC_RSRVD_INTERFACE, rtArray = cJSON_CreateArray());
+ interfacePtr = resourcePtr->rsrcInterface;
+ while (interfacePtr != NULL) {
+ cJSON_AddItemToArray (rtArray, cJSON_CreateString(interfacePtr->name));
+ interfacePtr = interfacePtr->next;
+ }
+ // If resource is observable, set observability flag.
+ // Resources that are not observable will not have the flag.
+ if (resourcePtr->resourceProperties & OC_OBSERVABLE) {
+ cJSON_AddItemToObject (resObj, OC_RSRVD_OBSERVABLE,
+ cJSON_CreateNumber(OC_RESOURCE_OBSERVABLE));
+ }
+ }
+ resourcePtr = resourcePtr->next;
+ }
+ jsonStr = cJSON_PrintUnformatted (ocObj);
+ memcpy (response, jsonStr, strlen(jsonStr));
+ cJSON_Delete (ocObj);
+ free (jsonStr);
+
+ return OC_STACK_OK;
+}
+
+OCStackResult validateUrlQuery (char *url, char *query, uint8_t *filterOn, char **filterValue)
+{
+ char *filterParam;
+
+ if (NULL == url)
+ return OC_STACK_INVALID_URI;
+
+ if (strcmp (url, OC_RESOURCE_DISCOVERY_URI) == 0) {
+ *filterOn = STACK_RES_DISCOVERY_NOFILTER;
+ if (*query != NULL) {
+ filterParam = strtok (query, "=");
+ *filterValue = strtok (NULL, " ");
+ if (*filterValue == NULL) {
+ return OC_STACK_INVALID_QUERY;
+ } else if (strcmp (filterParam, OC_RSRVD_INTERFACE) == 0) {
+ // Resource discovery with interface filter
+ *filterOn = STACK_RES_DISCOVERY_IF_FILTER;
+ } else if (strcmp (filterParam, OC_RSRVD_RESOURCE_TYPE) == 0) {
+ // Resource discovery with resource type filter
+ *filterOn = STACK_RES_DISCOVERY_RT_FILTER;
+ } else {
+ // Other filter types not supported
+ return OC_STACK_INVALID_QUERY;
+ }
+ }
+ } else {
+ // Other URIs not yet supported
+ return OC_STACK_INVALID_URI;
+ }
+ return OC_STACK_OK;
+}
+
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+//-----------------------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------------------
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include "ocserverrequest.h"
+#include "occlientcb.h"
+#include "debug.h"
+#include "occoap.h"
+#include "cJSON.h"
+#include <string.h>
+#include <stdlib.h>
+
+//-----------------------------------------------------------------------------
+// Typedefs
+//-----------------------------------------------------------------------------
+typedef enum {
+ OC_STACK_UNINITIALIZED = 0, OC_STACK_INITIALIZED
+} OCStackState;
+
+//-----------------------------------------------------------------------------
+// Private variables
+//-----------------------------------------------------------------------------
+static OCStackState stackState = OC_STACK_UNINITIALIZED;
+OCResource *headResource = NULL;
+
+//-----------------------------------------------------------------------------
+// Macros
+//-----------------------------------------------------------------------------
+#define TAG PCF("OCStack")
+#define VERIFY_NON_NULL(arg, logLevel, retVal) { if (!(arg)) { OC_LOG((logLevel), \
+ TAG, PCF(#arg " is NULL")); return (retVal); } }
+
+//-----------------------------------------------------------------------------
+// Internal API function
+//-----------------------------------------------------------------------------
+
+//This function will be called back by occoap layer when a request is received
+OCStackResult OCStackHandleReceiveRequest(OCRequest * request) {
+ OC_LOG(INFO, TAG, "Entering OCStackHandleReceiveRequest (OCStack Layer)");
+
+ char *filterValue;
+ uint8_t filterOn;
+ OCStackResult result;
+
+ VERIFY_NON_NULL(request, ERROR, OC_STACK_ERROR);
+ VERIFY_NON_NULL(request->entityHandlerRequest, ERROR, OC_STACK_ERROR);
+
+ result = validateUrlQuery(request->resourceUrl, request->query, &filterOn,
+ &filterValue);
+
+ if (OC_STACK_OK != result) {
+ return result;
+ }
+
+ result = processResourceDiscoverReq(
+ request->entityHandlerRequest->reqJSONPayload,
+ request->entityHandlerRequest->resJSONPayload, filterOn,
+ filterValue);
+
+ if (OC_STACK_OK != result) {
+ return result;
+ }
+
+ // TODO: lookup and service the resource
+ // TODO: call the entity handler
+ // for now just do this
+ //sprintf((char *) request->entityHandlerRequest->resJSONPayload,
+ // "Thank you, I got it!!!");
+ return OC_STACK_OK;
+}
+
+//This function will be called back by occoap layer when a response is received
+void OCStackHandleReceiveResponse(OCResponse * response) {
+ ClientCB * cbNode = NULL;
+ OCStackApplicationResult result = OC_STACK_DELETE_TRANSACTION;
+ OC_LOG(INFO, TAG, "Entering OCHandleClientReceiveResponse (OCStack Layer)");
+ if (response->clientResponse->result != OC_STACK_OK) {
+ OC_LOG(DEBUG, TAG, "There is a problem in OCSTACK in OCStackHandleReceiveResponseeeeeeeeeeeeeeeeee");
+ }
+
+ cbNode = GetClientCB(response->token);
+ if (cbNode) {
+ OC_LOG(INFO, TAG, PCF("Calling into application address space"));
+ result = cbNode->callBack(cbNode->context, response->clientResponse);
+ if (result == OC_STACK_DELETE_TRANSACTION) {
+ DeleteClientCB(cbNode);
+ }
+ }TODO ("What does the stack does in case of error");
+}
+
+//-----------------------------------------------------------------------------
+// Private internal function prototypes
+//-----------------------------------------------------------------------------
+// TODO: ultimately OCMalloc and OCFree should be defined in a different module
+static void *OCMalloc(size_t size);
+static void OCFree(void *ptr);
+
+static void initResources();
+static void insertResource(OCResource *resource);
+static OCResource *findResource(OCResource *resource);
+static void insertResourceType(OCResource *resource,
+ OCResourceType *resourceType);
+static OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle,
+ uint8_t index);
+static void insertResourceInterface(OCResource *resource,
+ OCResourceInterface *resourceInterface);
+static OCResourceInterface *findResourceInterfaceAtIndex(
+ OCResourceHandle handle, uint8_t index);
+static void deleteResourceType(OCResourceType *resourceType);
+static void deleteResourceInterface(OCResourceInterface *resourceInterface);
+static void deleteResourceElements(OCResource *resource);
+static int deleteResource(OCResource *resource);
+
+//-----------------------------------------------------------------------------
+// Default resource entity handler function
+//-----------------------------------------------------------------------------
+void defaultResourceEHandler(OCEntityHandlerFlag flag,
+ OCEntityHandlerRequest * request) {
+ TODO ("Implement me!!!!");
+ // TODO: remove silence unused param warnings
+ (void) flag;
+ (void) request;
+}
+
+//-----------------------------------------------------------------------------
+// Public APIs
+//-----------------------------------------------------------------------------
+
+/**
+ * Initialize the OC Stack. Must be called prior to starting the stack.
+ *
+ * @param ipAddr
+ * IP Address of host device
+ * @param port
+ * Port of host device
+ * @param mode
+ * Host device is client, server, or client-server
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack init error
+ */
+OCStackResult OCInit(const char *ipAddr, uint16_t port, OCMode mode) {
+ OC_LOG(INFO, TAG, PCF("Entering OCInit"));
+
+ if (ipAddr) {
+ OC_LOG_V(INFO, TAG, "IP Address = %s", ipAddr);
+ }
+
+ switch (mode) {
+ case OC_CLIENT:
+ OC_LOG(INFO, TAG, PCF("Client mode"));
+ break;
+ case OC_SERVER:
+ OC_LOG(INFO, TAG, PCF("Server mode"));
+ break;
+ case OC_CLIENT_SERVER:
+ OC_LOG(INFO, TAG, PCF("Client-server mode"));
+ break;
+ default:
+ OC_LOG(ERROR, TAG, PCF("Invalid mode"));
+ return OC_STACK_ERROR;
+ break;
+ }
+
+ // Initialize resource
+ initResources();
+
+ // Make call to OCCoAP layer
+ if (OCInitCoAP(ipAddr, (uint16_t) port, mode) == 0) {
+ stackState = OC_STACK_INITIALIZED;
+ return OC_STACK_OK;
+ }
+
+ OC_LOG(ERROR, TAG, PCF("Stack initialization error"));
+ return OC_STACK_ERROR;
+}
+
+/**
+ * Stop the OC stack. Use for a controlled shutdown.
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack not initialized
+ */
+OCStackResult OCStop() {
+ OC_LOG(INFO, TAG, PCF("Entering OCStop"));
+
+ if (stackState != OC_STACK_INITIALIZED) {
+ OC_LOG(ERROR, TAG, PCF("Stack not initialized"));
+ return OC_STACK_ERROR;
+ }
+
+ // Make call to OCCoAP layer
+ if (OCStopCoAP() == 0) {
+ // Remove all the client callbacks
+ DeleteClientCBList();
+ stackState = OC_STACK_UNINITIALIZED;
+ return OC_STACK_OK;
+ }
+
+ OC_LOG(ERROR, TAG, PCF("Stack stop error"));
+ return OC_STACK_ERROR;
+}
+
+/**
+ * Discover OC resources.
+ *
+ * @param method - method to perform on the resource
+ * @param requiredUri - URI of the resource to interact with
+ * @param referenceUri - URI of the reference resource
+ * @param request - JSON encoded request
+ * @param qos - quality of service
+ * @param asyncApplicationCB - asynchronous callback function that is invoked
+ * by the stack when discovery or resource interaction is complete
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_INVALID_CALLBACK - invalid callback function pointer
+ * OC_STACK_INVALID_METHOD - invalid resource method
+ * OC_STACK_INVALID_URI - invalid required or reference URI
+ */
+
+OCStackResult OCDoResource(OCMethod method, const char *requiredUri,
+ const char *referenceUri, const char *request, OCQualityOfService qos,
+// OCClientApplicationCBType clientApplicationCB) {
+ OCCallbackData *cbData) {
+
+ OCToken * token;
+
+ // TODO: Remove silence unused parameter warnings.
+ (void) referenceUri;
+ (void) request;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCDoResource"));
+
+ // TODO: Eventually, we want to allow for the caller to pass a null on the callback function.
+ // For now however, ensure that the callback is valid
+ // Storing the return function here, used later to call back the application
+ if (!cbData || !cbData->cb) {
+ return OC_STACK_INVALID_CALLBACK;
+ }
+
+ // Generate token here, it will be deleted when the transaction is deleted
+ token = (OCToken *) malloc(sizeof(OCToken));
+ token->tokenLength = MAX_TOKEN_LENGTH;
+ OCFillRandomMem(token->token, token->tokenLength);
+ OC_LOG_V(INFO,TAG,"Token generated %d bytes..........%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x",
+ token->tokenLength,token->token[0],token->token[1],token->token[2],token->token[3],
+ token->token[4],token->token[5],token->token[6],token->token[7]);
+
+ // TODO: Form and insert transaction structure
+ // for now just store it here
+ //storedCB = clientApplicationCB;
+
+ // Validate method
+ if (method != OC_REST_GET) {
+ return OC_STACK_INVALID_METHOD;
+ }
+
+ TODO ("Need to form the final query by concatenating require and reference URI's");
+ // Validate required URI
+ VERIFY_NON_NULL(requiredUri, FATAL, OC_STACK_INVALID_URI);
+
+ // Make call to OCCoAP layer
+ if (OCDoCoAPResource(method, qos, token, requiredUri) == OC_COAP_OK) {
+ OC_LOG(INFO, TAG, "Done with this function");
+ AddClientCB(cbData, token);
+ return OC_STACK_OK;
+ }
+
+ OC_LOG(ERROR, TAG, PCF("Stack stop error"));
+ return OC_STACK_ERROR;
+}
+
+/**
+ * Called in main loop of OC client or server. Allows low-level processing of
+ * stack services.
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCProcess() {
+
+ OC_LOG(INFO, TAG, PCF("Entering OCProcess"));
+ OCProcessCoAP();
+
+ return OC_STACK_OK;
+}
+/**
+ * Create a resource
+ *
+ * @param handle - pointer to handle to newly created resource. Set by ocstack. Used to refer to resource
+ * @param resourceTypeName - name of resource type. Example: "core.led"
+ * @param resourceAttributeRepresentation - attribute representation. list of attributes:type, with each pair
+ * separated by semicolons. Example: "state:oc.bt.b;power:oc.bt.i"
+ * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
+ * @param allowedMethods - methods permitted on interface. Example: OC_REST_GET|OC_REST_PUT
+ * @param uri - URI of the resource. Example: "/a/led"
+ * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
+ * @param resourceProperties - properties supported by resource. Example: OC_DISCOVERABLE|OC_OBSERVABLE
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCCreateResource(OCResourceHandle *handle,
+ const char *resourceTypeName,
+ const char *resourceAttributeRepresentation,
+ const char *resourceInterfaceName, uint8_t allowedMethods,
+ const char *uri, OCEntityHandler entityHandler,
+ uint8_t resourceProperties) {
+
+ OCResource *pointer = NULL;
+ char *str = NULL;
+ size_t size;
+ OCStackResult result = OC_STACK_ERROR;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCCreateResource"));
+
+ // Validate parameters
+ // TODO: Does resource attribute representation really have to be maintained in stack?
+ // Is it presented during resource discovery?
+ // VERIFY_NON_NULL(resourceAttributeRepresentation, ERROR, OC_STACK_ERROR);
+ if (!handle || !resourceTypeName || !resourceInterfaceName || !uri) {
+ OC_LOG(ERROR, TAG, PCF("Input parameter is NULL"));
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Make sure allowedMethods bitmask has allowed methods specified
+ if ((allowedMethods
+ > (OC_REST_GET | OC_REST_PUT | OC_REST_POST | OC_REST_DELETE
+ | OC_REST_OBSERVE))
+ || (allowedMethods == OC_REST_NOMETHOD)) {
+ OC_LOG(ERROR, TAG, PCF("Invalid method"));
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Make sure resourceProperties bitmask has allowed properties specified
+ if (resourceProperties
+ > (OC_ACTIVE | OC_DISCOVERABLE | OC_OBSERVABLE | OC_SLOW)) {
+ OC_LOG(ERROR, TAG, PCF("Invalid property"));
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // If the headResource is NULL, then no resources have been created...
+ pointer = headResource;
+ if (pointer) {
+ // At least one resources is in the resource list, so we need to search for
+ // repeated URLs, which are not allowed. If a repeat is found, exit with an error
+ while (pointer) {
+ if (strcmp(uri, pointer->uri) == 0) {
+ OC_LOG(ERROR, TAG, PCF("URI already in use"));
+ return OC_STACK_INVALID_PARAM;
+ }
+ pointer = pointer->next;
+ }
+ }
+ // Create the pointer and insert it into the resource list
+ pointer = (OCResource *) OCMalloc(sizeof(OCResource));
+ if (!pointer) {
+ goto exit;
+ }
+ memset(pointer, 0, sizeof(OCResource));
+
+ insertResource(pointer);
+
+ // Set the uri
+ size = strlen(uri) + 1;
+ str = (char *) OCMalloc(size);
+ if (!str) {
+ goto exit;
+ }
+ strncpy(str, uri, size);
+ pointer->uri = str;
+
+ // Set properties. Set OC_ACTIVE
+ pointer->resourceProperties = resourceProperties | OC_ACTIVE;
+
+ // Add the resourcetype to the resource
+ result = OCBindResourceTypeToResource((OCResourceHandle) pointer,
+ resourceTypeName, resourceAttributeRepresentation);
+ if (result != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, PCF("Error adding resourcetype"));
+ goto exit;
+ }
+
+ // Add the resourceinterface to the resource
+ result = OCBindResourceInterfaceToResource((OCResourceHandle) pointer,
+ resourceInterfaceName, allowedMethods);
+ if (result != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, PCF("Error adding resourceinterface"));
+ goto exit;
+ }
+
+ *handle = pointer;
+ result = OC_STACK_OK;
+
+ exit: if (result != OC_STACK_OK) {
+ OCFree(pointer);
+ OCFree(str);
+ }
+ return result;
+}
+
+/**
+ * Add a resource to a container resource.
+ *
+ * @param containerHandle - handle to the container resource
+ * @param addedResourceHandle - handle to resource to be added to the container resource
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCBindContainedResourceToResource(
+ OCResourceHandle containerHandle, OCResourceHandle addedResourceHandle) {
+ OCResource *resource;
+ uint8_t i;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCBindContainedResourceToResource"));
+
+ // Validate parameters
+ VERIFY_NON_NULL(containerHandle, ERROR, OC_STACK_ERROR);
+ VERIFY_NON_NULL(addedResourceHandle, ERROR, OC_STACK_ERROR);
+ // Container cannot contain itself
+ if (containerHandle == addedResourceHandle) {
+ OC_LOG(ERROR, TAG, PCF("Added handle equals container handle"));
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Use the handle to find the resource in the resource linked list
+ resource = findResource(containerHandle);
+ if (!resource) {
+ OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Look for an open slot to add add the child resource.
+ // If found, add it and return success
+ for (i = 0; i < MAX_CONTAINED_RESOURCES; i++) {
+ if (!resource->rsrcResources[i]) {
+ resource->rsrcResources[i] = addedResourceHandle;
+ OC_LOG(INFO, TAG, PCF("resource bound"));
+ return OC_STACK_OK;
+ }
+ }
+
+ // Unable to add addedResourceHandle, so return error
+ return OC_STACK_ERROR;
+}
+
+/**
+ * Bind a resourcetype to a resource.
+ *
+ * @param handle - handle to the container resource
+ * @param resourceTypeName - name of resource type. Example: "core.led"
+ * @param resourceAttributeRepresentation - attribute representation. list of attributes:type, with each pair
+ * separated by semicolons. Example: "state:oc.bt.b;power:oc.bt.i"
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCBindResourceTypeToResource(OCResourceHandle handle,
+ const char *resourceTypeName,
+ const char *resourceAttributeRepresentation) {
+
+ OCResourceType *pointer = NULL;
+ char *str = NULL;
+ size_t size;
+ OCResource *resource;
+ OCStackResult result = OC_STACK_ERROR;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCBindResourceTypeToResource"));
+
+ // Validate parameters
+ VERIFY_NON_NULL(resourceTypeName, ERROR, OC_STACK_INVALID_PARAM);
+ // TODO: Does resource attribute resentation really have to be maintained in stack?
+ // Is it presented during resource discovery?
+ // VERIFY_NON_NULL(resourceAttributeRepresentation, ERROR, OC_STACK_ERROR);
+
+ // Make sure resource exists
+ resource = findResource((OCResource *) handle);
+ if (!resource) {
+ OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ return OC_STACK_ERROR;
+ }
+
+ TODO ("Make sure that the resourcetypename doesn't already exist in the resource");
+
+ // Create the resourcetype and insert it into the resource list
+ pointer = (OCResourceType *) OCMalloc(sizeof(OCResourceType));
+ if (!pointer) {
+ goto exit;
+ }
+ memset(pointer, 0, sizeof(OCResourceType));
+
+ // Set the resourceTypeName
+ size = strlen(resourceTypeName) + 1;
+ str = (char *) OCMalloc(size);
+ if (!str) {
+ goto exit;
+ }
+ strncpy(str, resourceTypeName, size);
+ pointer->resourcetypename = str;
+
+ // If the resourceAttributeRepresentation is defined, add it.
+ if (resourceAttributeRepresentation) {
+ size = strlen(resourceAttributeRepresentation) + 1;
+ str = (char *) OCMalloc(size);
+ if (!str) {
+ goto exit;
+ }
+ strncpy(str, resourceAttributeRepresentation, size);
+ pointer->typerepresentation = str;
+ }
+ // Bind the resourcetype to the resource
+ insertResourceType(resource, pointer);
+
+ result = OC_STACK_OK;
+
+ exit: if (result != OC_STACK_OK) {
+ OCFree(pointer);
+ OCFree(str);
+ }
+ return result;
+}
+
+/**
+ * Bind a resourceinterface to a resource.
+ *
+ * @param handle - handle to the container resource
+ * @param resourceInterfaceName - name of resource interface. Example: "core.rw"
+ * @param allowedMethods - methods permitted on interface. Example: OC_REST_GET|OC_REST_PUT
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCBindResourceInterfaceToResource(OCResourceHandle handle,
+ const char *resourceInterfaceName, uint8_t allowedMethods) {
+
+ OCResourceInterface *pointer = NULL;
+ char *str = NULL;
+ size_t size;
+ OCResource *resource;
+ OCStackResult result = OC_STACK_ERROR;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCBindResourceInterfaceToResource"));
+
+ // Validate parameters
+ VERIFY_NON_NULL(resourceInterfaceName, ERROR, OC_STACK_INVALID_PARAM);
+
+ // Make sure allowedMethods bitmask has allowed methods specified
+ if ((allowedMethods
+ > (OC_REST_GET | OC_REST_PUT | OC_REST_POST | OC_REST_DELETE
+ | OC_REST_OBSERVE))
+ || (allowedMethods == OC_REST_NOMETHOD)) {
+ OC_LOG(ERROR, TAG, PCF("Invalid method"));
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ // Make sure resource exists
+ resource = findResource((OCResource *) handle);
+ if (!resource) {
+ OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ TODO ("Make sure that the resourceinterface name doesn't already exist in the resource");
+
+ // Create the resourceinterface and insert it into the resource list
+ pointer = (OCResourceInterface *) OCMalloc(sizeof(OCResourceInterface));
+ if (!pointer) {
+ goto exit;
+ }
+ memset(pointer, 0, sizeof(OCResourceInterface));
+
+ // Set the resourceinterface name
+ size = strlen(resourceInterfaceName) + 1;
+ str = (char *) OCMalloc(size);
+ if (!str) {
+ goto exit;
+ }
+ strncpy(str, resourceInterfaceName, size);
+ pointer->name = str;
+
+ pointer->allowedMethods = allowedMethods;
+
+ // Bind the resourceinterface to the resource
+ insertResourceInterface(resource, pointer);
+
+ result = OC_STACK_OK;
+ exit: if (result != OC_STACK_OK) {
+ OCFree(pointer);
+ OCFree(str);
+ }
+ return result;
+}
+
+/**
+ * Get the number of resources that have been created in the stack.
+ *
+ * @param numResources - pointer to count variable
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+
+ */
+OCStackResult OCGetNumberOfResources(uint8_t *numResources) {
+ OCResource *pointer = headResource;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResources"));
+ VERIFY_NON_NULL(numResources, ERROR, OC_STACK_INVALID_PARAM);
+ *numResources = 0;
+ while (pointer) {
+ *numResources = *numResources + 1;
+ pointer = pointer->next;
+ }
+ return OC_STACK_OK;
+}
+
+/**
+ * Get a resource handle by index.
+ *
+ * @param index - index of resource, 0 to Count - 1
+ *
+ * @return
+ * Resource handle - if found
+ * NULL - if not found
+ */
+OCResourceHandle OCGetResourceHandle(uint8_t index) {
+ OCResource *pointer = headResource;
+ uint8_t i = 0;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandle"));
+
+ // Iterate through the list
+ while ((i < index) && pointer) {
+ i++;
+ pointer = pointer->next;
+ }
+ return (OCResourceHandle) pointer;
+}
+
+/**
+ * Delete resource specified by handle. Deletes resource and all resourcetype and resourceinterface
+ * linked lists.
+ *
+ * @param handle - handle of resource to be deleted
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCDeleteResource(OCResourceHandle handle) {
+ OC_LOG(INFO, TAG, PCF("Entering OCDeleteResource"));
+
+ if (!handle) {
+ OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ return OC_STACK_INVALID_PARAM;
+ }
+
+ if (deleteResource((OCResource *) handle) == 0) {
+ OC_LOG(ERROR, TAG, PCF("Error deleting resource"));
+ return OC_STACK_ERROR;
+ }
+
+ return OC_STACK_OK;
+}
+
+/**
+ * Get the URI of the resource specified by handle.
+ *
+ * @param handle - handle of resource
+ * @return
+ * URI string - if resource found
+ * NULL - resource not found
+ */
+const char *OCGetResourceUri(OCResourceHandle handle) {
+ OCResource *resource;
+ OC_LOG(INFO, TAG, PCF("Entering OCGetResourceUri"));
+
+ resource = findResource((OCResource *) handle);
+ if (resource) {
+ return resource->uri;
+ }
+ return (const char *) NULL;
+}
+
+/**
+ * Get the properties of the resource specified by handle.
+ * NOTE: that after a resource is created, the OC_ACTIVE property is set
+ * for the resource by the stack.
+ *
+ * @param handle - handle of resource
+ * @return
+ * property bitmap - if resource found
+ * NULL - resource not found
+ */
+uint8_t OCGetResourceProperties(OCResourceHandle handle) {
+ OCResource *resource;
+ OC_LOG(INFO, TAG, PCF("Entering OCGetResourceProperties"));
+
+ resource = findResource((OCResource *) handle);
+ if (resource) {
+ return resource->resourceProperties;
+ }
+ return 0;
+}
+
+/**
+ * Get the number of resource types of the resource.
+ *
+ * @param handle - handle of resource
+ * @param numResourceTypes - pointer to count variable
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCGetNumberOfResourceTypes(OCResourceHandle handle,
+ uint8_t *numResourceTypes) {
+ OCResource *resource;
+ OCResourceType *pointer;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceTypes"));
+ VERIFY_NON_NULL(numResourceTypes, ERROR, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
+
+ *numResourceTypes = 0;
+
+ resource = findResource((OCResource *) handle);
+ if (resource) {
+ pointer = resource->rsrcType;
+ while (pointer) {
+ *numResourceTypes = *numResourceTypes + 1;
+ pointer = pointer->next;
+ }
+ }
+ return OC_STACK_OK;
+}
+
+/**
+ * Get name of resource type of the resource.
+ *
+ * @param handle - handle of resource
+ * @param index - index of resource, 0 to Count - 1
+ *
+ * @return
+ * resource type name - if resource found
+ * NULL - resource not found
+ */
+const char *OCGetResourceTypeName(OCResourceHandle handle, uint8_t index) {
+ OCResourceType *resourceType;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCGetResourceTypeName"));
+
+ resourceType = findResourceTypeAtIndex(handle, index);
+ if (resourceType) {
+ return resourceType->resourcetypename;
+ }
+ return (const char *) NULL;
+}
+
+/**
+ * Get attributes of resource type of the resource.
+ *
+ * @param handle - handle of resource
+ * @param index - index of resource, 0 to Count - 1
+ *
+ * @return
+ * resource type attributes - if resource found
+ * NULL - resource not found
+ */
+const char *OCGetResourceAttributeRepresentation(OCResourceHandle handle,
+ uint8_t index) {
+ OCResourceType *resourceType;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCGetResourceAttributeRepresentation"));
+
+ resourceType = findResourceTypeAtIndex(handle, index);
+ if (resourceType) {
+ return resourceType->typerepresentation;
+ }
+ return (const char *) NULL;
+}
+
+/**
+ * Get the number of resource interfaces of the resource.
+ *
+ * @param handle - handle of resource
+ * @param numResources - pointer to count variable
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+
+ */
+OCStackResult OCGetNumberOfResourceInterfaces(OCResourceHandle handle,
+ uint8_t *numResourceInterfaces) {
+ OCResourceInterface *pointer;
+ OCResource *resource;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCGetNumberOfResourceInterfaces"));
+
+ VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(numResourceInterfaces, ERROR, OC_STACK_INVALID_PARAM);
+
+ *numResourceInterfaces = 0;
+ resource = findResource((OCResource *) handle);
+ if (resource) {
+ pointer = resource->rsrcInterface;
+ while (pointer) {
+ *numResourceInterfaces = *numResourceInterfaces + 1;
+ pointer = pointer->next;
+ }
+ }
+ return OC_STACK_OK;
+}
+
+/**
+ * Get name of resource interface of the resource.
+ *
+ * @param handle - handle of resource
+ * @param index - index of resource, 0 to Count - 1
+ *
+ * @return
+ * resource interface name - if resource found
+ * NULL - resource not found
+ */
+const char *OCGetResourceInterfaceName(OCResourceHandle handle, uint8_t index) {
+ OCResourceInterface *resourceInterface;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceName"));
+
+ resourceInterface = findResourceInterfaceAtIndex(handle, index);
+ if (resourceInterface) {
+ return resourceInterface->name;
+ }
+ return (const char *) NULL;
+}
+
+/**
+ * Get methods of resource interface of the resource.
+ *
+ * @param handle - handle of resource
+ * @param index - index of resource, 0 to Count - 1
+ *
+ * @return
+ * allowed methods - if resource found
+ * NULL - resource not found
+ */
+uint8_t OCGetResourceInterfaceAllowedMethods(OCResourceHandle handle,
+ uint8_t index) {
+ OCResourceInterface *resourceInterface;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCGetResourceInterfaceAllowedMethods"));
+
+ resourceInterface = findResourceInterfaceAtIndex(handle, index);
+ if (resourceInterface) {
+ return resourceInterface->allowedMethods;
+ }
+ return (uint8_t) 0;
+}
+
+/**
+ * Get name of resource interface of the resource.
+ *
+ * @param containerHandle - handle of container resource
+ * @param index - index of contained resource, 0 to Count - 1
+ *
+ * @return
+ * handle to contained resource - if resource found
+ * NULL - resource not found
+ */
+OCResourceHandle OCGetContainedResourceHandle(OCResourceHandle containerHandle,
+ uint8_t index) {
+ OCResource *resource;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCGetContainedResource"));
+
+ if (index >= MAX_CONTAINED_RESOURCES) {
+ return NULL;
+ }
+
+ resource = findResource((OCResource *) containerHandle);
+ if (!resource) {
+ return NULL;
+ }
+
+ return resource->rsrcResources[index];
+}
+
+/**
+ * Bind an entity handler to the resource.
+ *
+ * @param handle - handle to the resource that the contained resource is to be bound
+ * @param entityHandler - entity handler function that is called by ocstack to handle requests, etc
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack process error
+ */
+OCStackResult OCBindResourceHandler(OCResourceHandle handle,
+ OCEntityHandler entityHandler) {
+ OCResource *resource;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCBindResourceHandler"));
+
+ // Validate parameters
+ VERIFY_NON_NULL(handle, ERROR, OC_STACK_INVALID_PARAM);
+ VERIFY_NON_NULL(entityHandler, ERROR, OC_STACK_INVALID_PARAM);
+
+ // Use the handle to find the resource in the resource linked list
+ resource = findResource(handle);
+ if (!resource) {
+ OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ return OC_STACK_ERROR;
+ }
+
+ // Bind the handler
+ resource->entityHandler = entityHandler;
+
+ return OC_STACK_OK;
+}
+
+/**
+ * Get the entity handler for a resource.
+ *
+ * @param handle - handle of resource
+ *
+ * @return
+ * entity handler - if resource found
+ * NULL - resource not found
+ */
+OCEntityHandler OCGetResourceHandler(OCResourceHandle handle) {
+ OCResource *resource;
+
+ OC_LOG(INFO, TAG, PCF("Entering OCGetResourceHandler"));
+
+ // Use the handle to find the resource in the resource linked list
+ resource = findResource(handle);
+ if (!resource) {
+ OC_LOG(ERROR, TAG, PCF("Resource not found"));
+ return NULL;
+ }
+
+ // Bind the handler
+ return resource->entityHandler;
+}
+
+/**
+ * Notify observers that an observed value has changed.
+ *
+ * **NOTE: This API has NOT been finalized!!!**
+ *
+ * @param handle - handle of resource
+ *
+ * @return
+ * OC_STACK_OK - no errors
+ * OC_STACK_ERROR - stack not initialized
+ */
+OCStackResult OCNotifyObservers(OCResourceHandle handle) {
+
+ TODO ("This API has NOT been finalized");
+
+ OC_LOG(INFO, TAG, PCF("Entering OCNotifyObservers"));
+
+ (void) handle;
+
+ return OC_STACK_NOTIMPL;
+}
+
+//-----------------------------------------------------------------------------
+// Private internal function definitions
+//-----------------------------------------------------------------------------
+
+/**
+ * Initialize resource data structures, variables, etc.
+ */
+void initResources() {
+ TODO ("Do we need to create a resource for /oc/core???");
+ // Init resource vars
+ headResource = NULL;
+}
+
+/**
+ * Add a resource to the end of the linked list of resources.
+ *
+ * @param resource - resource to be added
+ */
+void insertResource(OCResource *resource) {
+ OCResource *pointer;
+
+ if (!headResource) {
+ headResource = resource;
+ } else {
+ pointer = headResource;
+
+ while (pointer->next) {
+ pointer = pointer->next;
+ }
+ pointer->next = resource;
+ }
+ resource->next = NULL;
+}
+
+/**
+ * Find a resource in the linked list of resources.
+ *
+ * @param resource - resource to be found
+ * @return
+ * NULL - resource not found
+ * pointer to resource - pointer to resource that was found in the linked list
+ */
+OCResource *findResource(OCResource *resource) {
+ OCResource *pointer = headResource;
+
+ while (pointer) {
+ if (pointer == resource) {
+ return resource;
+ }
+ pointer = pointer->next;
+ }
+ return NULL;
+}
+
+/**
+ * Delete the resource from the linked list.
+ *
+ * @param resource - resource to be deleted
+ * @return
+ * 0 - error
+ * 1 - success
+ */
+int deleteResource(OCResource *resource) {
+ OCResource *prev = NULL;
+ OCResource *temp;
+
+ temp = headResource;
+ while (temp) {
+ if (temp == resource) {
+ if (temp == headResource) {
+ headResource = temp->next;
+ } else {
+ prev->next = temp->next;
+ }
+ deleteResourceElements(temp);
+ OCFree(temp);
+ return 1;
+ } else {
+ prev = temp;
+ temp = temp->next;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Delete all of the dynamically allocated elements that were created for the resource.
+ *
+ * @param resource - specified resource
+ */
+void deleteResourceElements(OCResource *resource) {
+ if (!resource) {
+ return;
+ }
+
+ // remove URI
+ OCFree(resource->uri);
+
+ // Delete resourcetype linked list
+ deleteResourceType(resource->rsrcType);
+
+ // Delete resourceinterface linked list
+ deleteResourceInterface(resource->rsrcInterface);
+}
+
+/**
+ * Delete all of the dynamically allocated elements that were created for the resource type.
+ *
+ * @param resourceType - specified resource type
+ */
+void deleteResourceType(OCResourceType *resourceType) {
+ OCResourceType *pointer = resourceType;
+ OCResourceType *next;
+
+ while (pointer) {
+ next = pointer->next;
+ OCFree(pointer->resourcetypename);
+ OCFree(pointer->typerepresentation);
+ OCFree(pointer);
+ pointer = next;
+ }
+}
+
+/**
+ * Delete all of the dynamically allocated elements that were created for the resource interface.
+ *
+ * @param resourceInterface - specified resource interface
+ */
+void deleteResourceInterface(OCResourceInterface *resourceInterface) {
+ OCResourceInterface *pointer = resourceInterface;
+ OCResourceInterface *next;
+
+ while (pointer) {
+ next = pointer->next;
+ OCFree(pointer->name);
+ OCFree(pointer);
+ pointer = next;
+ }
+}
+
+/**
+ * Insert a resource type into a resource's resource type linked list.
+ *
+ * @param resource - resource where resource type is to be inserted
+ * @param resourceType - resource type to be inserted
+ */
+void insertResourceType(OCResource *resource, OCResourceType *resourceType) {
+ OCResourceType *pointer;
+
+ if (!resource->rsrcType) {
+ resource->rsrcType = resourceType;
+ } else {
+ pointer = resource->rsrcType;
+ while (pointer->next) {
+ pointer = pointer->next;
+ }
+ pointer->next = resourceType;
+ }
+ resourceType->next = NULL;
+}
+
+/**
+ * Get a resource type at the specified index within a resource.
+ *
+ * @param handle - handle of resource
+ * @param index - index of resource type
+ *
+ * @return
+ * resourcetype - if found
+ * NULL - not found
+ */
+OCResourceType *findResourceTypeAtIndex(OCResourceHandle handle, uint8_t index) {
+ OCResource *resource;
+ OCResourceType *pointer;
+ uint8_t i;
+
+ // Find the specified resource
+ resource = findResource((OCResource *) handle);
+ if (!resource) {
+ return NULL;
+ }
+
+ // Make sure a resource has a resourcetype
+ if (!resource->rsrcType) {
+ return NULL;
+ }
+
+ // Iterate through the list
+ pointer = resource->rsrcType;
+ i = 0;
+ while ((i < index) && pointer) {
+ i++;
+ pointer = pointer->next;
+ }
+ return pointer;
+}
+
+/**
+ * Insert a resource interface into a resource's resource interface linked list.
+ *
+ * @param resource - resource where resource interface is to be inserted
+ * @param resourceInterface - resource interface to be inserted
+ */
+void insertResourceInterface(OCResource *resource,
+ OCResourceInterface *resourceInterface) {
+ OCResourceInterface *pointer;
+
+ if (!resource->rsrcInterface) {
+ resource->rsrcInterface = resourceInterface;
+ } else {
+ pointer = resource->rsrcInterface;
+ while (pointer->next) {
+ pointer = pointer->next;
+ }
+ pointer->next = resourceInterface;
+ }
+ resourceInterface->next = NULL;
+}
+
+/**
+ * Get a resource interface at the specified index within a resource.
+ *
+ * @param handle - handle of resource
+ * @param index - index of resource interface
+ *
+ * @return
+ * resourceinterface - if found
+ * NULL - not found
+ */
+OCResourceInterface *findResourceInterfaceAtIndex(OCResourceHandle handle,
+ uint8_t index) {
+ OCResource *resource;
+ OCResourceInterface *pointer;
+ uint8_t i = 0;
+
+ // Find the specified resource
+ resource = findResource((OCResource *) handle);
+ if (!resource) {
+ return NULL;
+ }
+
+ // Make sure a resource has a resourceinterface
+ if (!resource->rsrcInterface) {
+ return NULL;
+ }
+
+ // Iterate through the list
+ pointer = resource->rsrcInterface;
+
+ while ((i < index) && pointer) {
+ i++;
+ pointer = pointer->next;
+ }
+ return pointer;
+}
+
+// TODO: Remove these! Should be in an ocmalloc module
+void *OCMalloc(size_t size) {
+ TODO ("This should be moved into an ocmalloc dir and implemented as a separate OC module");
+ return malloc(size);
+}
+
+void OCFree(void *ptr) {
+ TODO ("This should be moved into an ocmalloc dir and implemented as a separate OC module");
+ free(ptr);
+}
+
--- /dev/null
+stacktests.cpp contain several stack tests that can be used in an Android JNI app.
+
+Note: to enable the logger for Android, TB_LOG should be defined in the ./jni/Android.mk file as
+LOCAL_CFLAGS := -DTB_LOG
+
+Note: add the following to the ./jni/Android.mk file
+LOCAL_SRC_FILES += logger.c
+LOCAL_SRC_FILES += loggertests.cpp
+LOCAL_SRC_FILES += ocstack.c
+LOCAL_SRC_FILES += occoap.c
+LOCAL_SRC_FILES += stacktests.cpp
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+extern "C" {
+ #include "logger.h"
+ #include "ocstack.h"
+ #include "ocstackinternal.h"
+}
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <string.h>
+//-----------------------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------------------
+#include <stdio.h>
+#include <string.h>
+
+#include <stdint.h>
+using namespace std;
+
+
+//-----------------------------------------------------------------------------
+// Private variables
+//-----------------------------------------------------------------------------
+static const char TAG[] = "TestHarness";
+static OCUri SERVICE_URI = "coap://127.0.0.1:5683/";
+
+void EXPECT_EQ(int a, int b) {
+ if (a == b) {
+ OC_LOG(INFO, TAG, "PASS");
+ } else {
+ OC_LOG(ERROR, TAG, "**FAIL**");
+ }
+}
+
+void EXPECT_STREQ(const char *a, const char *b) {
+ if (strcmp(a, b) == 0) {
+ OC_LOG(INFO, TAG, "PASS");
+ } else {
+ OC_LOG(ERROR, TAG, "**FAIL**");
+ }
+}
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+
+extern "C" void asyncDoResourcesCallback(OCStackResult result, OCRepresentationHandle representation) {
+ OC_LOG(INFO, TAG, "Entering asyncDoResourcesCallback");
+
+ EXPECT_EQ(OC_STACK_OK, result);
+ OCResource *resource = (OCResource *)representation;
+ OC_LOG_V(INFO, TAG, "URI = %s", resource->uri);
+ EXPECT_STREQ(SERVICE_URI, resource->uri);
+}
+
+//-----------------------------------------------------------------------------
+// Tests
+//-----------------------------------------------------------------------------
+void test0() {
+ EXPECT_EQ(OC_STACK_OK, OCInit(0, 5683, OC_SERVER));
+}
+
+void test1() {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 0, OC_SERVER));
+}
+
+void test2() {
+ EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER));
+}
+
+void test3() {
+ EXPECT_EQ(OC_STACK_ERROR, OCInit(0, 0, (OCMode)10));
+}
+
+void test4() {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER));
+}
+
+void test5() {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback));
+ EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
+ EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+void test6() {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
+ EXPECT_EQ(OC_STACK_OK, OCStop());
+ EXPECT_EQ(OC_STACK_ERROR, OCStop());
+}
+
+void test7() {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback));
+ EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
+ EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+void stacktests() {
+ test0();
+ test1();
+ test2();
+ test3();
+ test4();
+ test5();
+ test6();
+ test7();
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+// Do not remove the include below
+#include "ArduinoStackTest.h"
+
+#include "logger.h"
+#include "ocstack.h"
+#include "ocstackinternal.h"
+#include <string.h>
+
+#define PCF(str) ((const prog_char*)(F(str)))
+
+const prog_char TAG[] PROGMEM = "Arduino";
+static OCUri SERVICE_URI = "coap://127.0.0.1:5683/";
+
+#if 0 // Turn off logger test stuff
+const prog_char tag[] PROGMEM = "Arduino";
+const prog_char msg[] PROGMEM = "Arduino Logger Test";
+
+const prog_char debugMsg[] PROGMEM = "this is a DEBUG message";
+const prog_char infoMsg[] PROGMEM = "this is a INFO message";
+const prog_char warningMsg[] PROGMEM = "this is a WARNING message";
+const prog_char errorMsg[] PROGMEM = "this is a ERROR message";
+const prog_char fatalMsg[] PROGMEM = "this is a FATAL message";
+
+const prog_char multiLineMsg[] PROGMEM = "this is a DEBUG message\non multiple\nlines";
+#endif
+
+void EXPECT_EQ(int a, int b) {
+ if (a == b) {
+ OC_LOG(INFO, TAG, PCF("PASS"));
+ } else {
+ OC_LOG(ERROR, TAG, PCF("FAIL"));
+ }
+}
+
+void EXPECT_STREQ(const char *a, const char *b) {
+ if (strcmp(a, b) == 0) {
+ OC_LOG(INFO, TAG, "PASS");
+ } else {
+ OC_LOG(ERROR, TAG, "FAIL");
+ }
+}
+//-----------------------------------------------------------------------------
+// Tests
+//-----------------------------------------------------------------------------
+#if 0 // Turn off logger tests
+void test0() {
+ OC_LOG(INFO, tag, msg);
+}
+
+void test1() {
+ OC_LOG(INFO, 0, msg);
+}
+
+void test2() {
+ OC_LOG(INFO, tag, 0);
+}
+
+void test3() {
+ OC_LOG(INFO, 0, 0);
+}
+
+void test4() {
+ OC_LOG(DEBUG, tag, debugMsg);
+ OC_LOG(INFO, tag, infoMsg);
+ OC_LOG(WARNING, tag, warningMsg);
+ OC_LOG(ERROR, tag, errorMsg);
+ OC_LOG(FATAL, tag, fatalMsg);
+}
+
+void test5() {
+ OC_LOG(DEBUG, tag, multiLineMsg);
+}
+
+
+void test6() {
+ // Log buffer
+ uint8_t buffer[50];
+ for (int i = 0; i < (int)(sizeof buffer); i++) {
+ buffer[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer, sizeof buffer);
+
+ // Log buffer, 128 bytes is a good boundary (8 rows of 16 values)
+ uint8_t buffer1[128];
+ for (int i = 0; i < (int)(sizeof buffer1); i++) {
+ buffer1[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer1, sizeof buffer1);
+
+ // 1 below 128 byte boundary
+ uint8_t buffer2[127];
+ for (int i = 0; i < (int)(sizeof buffer2); i++) {
+ buffer2[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer2, sizeof buffer2);
+
+ // 1 above 128 byte boundary
+ uint8_t buffer3[129];
+ for (int i = 0; i < (int)(sizeof buffer3); i++) {
+ buffer3[i] = i;
+ }
+ OC_LOG_BUFFER(DEBUG, tag, buffer3, sizeof buffer3);
+}
+#endif
+
+extern "C" void asyncDoResourcesCallback(OCStackResult result, OCRepresentationHandle representation) {
+ OC_LOG(INFO, TAG, PCF("Entering asyncDoResourcesCallback"));
+
+ EXPECT_EQ(OC_STACK_OK, result);
+ OCResource *resource = (OCResource *)representation;
+ OC_LOG_V(INFO, TAG, "URI = %s", resource->uri);
+ EXPECT_STREQ(SERVICE_URI, resource->uri);
+}
+
+void test0() {
+ OC_LOG(INFO, TAG, PCF("test0"));
+ EXPECT_EQ(OC_STACK_OK, OCInit(0, 5683, OC_SERVER));
+}
+
+void test1() {
+ OC_LOG(INFO, TAG, PCF("test1"));
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 0, OC_SERVER));
+}
+
+void test2() {
+ OC_LOG(INFO, TAG, PCF("test2"));
+ EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER));
+}
+
+void test3() {
+ OC_LOG(INFO, TAG, PCF("test3"));
+ EXPECT_EQ(OC_STACK_ERROR, OCInit(0, 0, (OCMode)10));
+}
+
+void test4() {
+ OC_LOG(INFO, TAG, PCF("test4"));
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER));
+}
+
+void test5() {
+ OC_LOG(INFO, TAG, PCF("test5"));
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback));
+ EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
+ EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+void test6() {
+ OC_LOG(INFO, TAG, PCF("test6"));
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
+ EXPECT_EQ(OC_STACK_OK, OCStop());
+ EXPECT_EQ(OC_STACK_ERROR, OCStop());
+}
+
+void test7() {
+ OC_LOG(INFO, TAG, PCF("test7"));
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback));
+ EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
+ EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+
+
+//The setup function is called once at startup of the sketch
+void setup()
+{
+ // Add your initialization code here
+ OC_LOG_INIT();
+
+ test0();
+ delay(2000);
+ test1();
+ delay(2000);
+ test2();
+ delay(2000);
+ test3();
+ delay(2000);
+ test4();
+ delay(2000);
+ test5();
+ delay(2000);
+ test6();
+ delay(2000);
+
+#if 1
+ test7();
+ delay(2000);
+#endif
+
+}
+
+// The loop function is called in an endless loop
+void loop()
+{
+ delay(2000);
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+// Only modify this file to include
+// - function definitions (prototypes)
+// - include files
+// - extern variable definitions
+// In the appropriate section
+
+#ifndef ArduinoStackTest_H_
+#define ArduinoStackTest_H_
+#include "Arduino.h"
+//add your includes for the project ArduinoDummyTestFramework here
+
+
+//end of add your includes here
+#ifdef __cplusplus
+extern "C" {
+#endif
+void loop();
+void setup();
+#ifdef __cplusplus
+} // extern "C"
+#endif
+
+//add your function definitions for the project ArduinoDummyTestFramework here
+
+
+
+
+//Do not add code below this line
+#endif /* ArduinoStackTest_H_ */
--- /dev/null
+ArduinoStackTest.cpp contains several logger tests and can be used in an
+Arduino sketch.
+
+On Arduino, the logger outputs to the serial port using Serial.print.
+
+Run a serial terminal program such as CuteCom at 115200,8,N,1 to view the
+log outputs.
+
+Note: to enable the logger for Arduino, TB_LOG should be defined in
+Properties|C/C++ Build|Settings|Tool Settings|AVR Compiler|Symbols
+and
+Properties|C/C++ Build|Settings|Tool Settings|AVR C++ Compiler|Symbols
+
+Copy logger.c/h, occoap.c/h, and ocstack.c/h, and ocstackinternal.h to the Arduino project
+Note: when building for Arduino, force the compiler to use avr-g++ to build logger.c, stack.c, and occoap.c
+
+Note: when building for Arduino, several warnings are generated when trying to place strings in
+PROGMEM
+"warning: only initialized variables can be placed into program memory area"
+This appears to be a known gcc bug - https://gcc.gnu.org/bugzilla/show_bug.cgi?id=34734
+
--- /dev/null
+VERSION:=4.1.1
+
+#other options are android, arduino
+PLATFORM=linux
+
+#peg_ccfl-core
+ROOT_DIR = ../../..
+LIBCOAP_DIR = $(ROOT_DIR)/libcoap-4.1.1
+OCSOCK_DIR = $(ROOT_DIR)/ocsocket
+OCCOAP_DIR = $(ROOT_DIR)/occoap
+OCSTACK_DIR = $(ROOT_DIR)/stack
+LOGGER_DIR = $(ROOT_DIR)/logger
+RANDOM_DIR = $(ROOT_DIR)/ocrandom
+JSON_DIR = $(ROOT_DIR)/../../../ccf-utilities/tb/cJSON
+
+OBJ_DIR = ./
+INC_DIRS = -I$(LOGGER_DIR)/include/ -I$(OCCOAP_DIR)/include/ \
+ -I$(OCSTACK_DIR)/include/ -I$(OCSTACK_DIR)/include/internal \
+ -I$(LIBCOAP_DIR)/ -I$(OCSOCK_DIR)/include -I$(RANDOM_DIR)/include \
+ -I$(JSON_DIR)
+
+ifeq ($(PLATFORM),android)
+ CCPLUS=arm-linux-androideabi-g++
+ CC=arm-linux-androideabi-gcc
+ AR=arm-linux-androideabi-ar
+ RANLIB=arm-linux-androideabi-ranlib
+ CFLAGS_ANDROID = -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16
+ LDFLAGS_ANDROID = -march=armv7-a -Wl,--fix-cortex-a8 -llog
+else ifeq ($(PLATFORM),linux)
+ CCPLUS=g++
+ CC=gcc
+ AR=ar
+ RANLIB=ranlib
+else
+ $(error Wrong value for PLATFORM !!)
+endif
+
+DEP_LIBS = $(LIBCOAP_DIR)/libcoap.a
+
+CFLAGS += -Os -Wall -Wno-write-strings -ffunction-sections -fdata-sections -fno-exceptions \
+ -Wextra -Wno-variadic-macros -pedantic -std=gnu99 -DWITH_POSIX -DTB_LOG
+
+VPATH = $(OCCOAP_DIR)/src:$(OCSTACK_DIR)/src
+
+PROGRAMS = ocserver occlient
+
+SOURCES:= occlient.c ocserver.c ocstack.c occoap.c occlientcb.c ocserverrequest.c
+
+OBJECTS:= $(patsubst %.c, %.o, $(SOURCES))
+
+all: $(PROGRAMS)
+
+%.o: %.c
+ $(CC) -c $(CFLAGS) $(CFLAGS_ANDROID) $(INC_DIRS) $< -o $@
+
+##Added -lm as needed by json calling floor()
+occlient: occlient.o ocstack.o occoap.o occlientcb.o ocserverrequest.o $(DEP_LIBS)
+ $(CC) -Os -Wl,--gc-sections $(LDFLAGS_ANDROID) $^ -o $@ -lm
+
+ocserver: ocserver.o ocstack.o occoap.o occlientcb.o ocserverrequest.o $(DEP_LIBS)
+ $(CC) -Os -Wl,--gc-sections $(LDFLAGS_ANDROID) $^ -o $@ -lm
+
+install: all
+ @echo "Installing for PLATFORM $(PLATFORM)"
+ifeq ($(PLATFORM),android)
+ adb push coap-client /data/local/tmp/
+ adb push coap-server /data/local/tmp/
+endif
+
+.PHONY: clean
+
+clean:
+ rm -f *.o $(PROGRAMS)
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <signal.h>
+#include <unistd.h>
+#include <ocstack.h>
+
+#define TAG PCF("occlient")
+
+int gQuitFlag = 0;
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum) {
+ if (signum == SIGINT) {
+ gQuitFlag = 1;
+ }
+}
+
+// This is a function called back when a device is discovered
+OCStackApplicationResult applicationDiscoverCB(
+ OCClientResponse * clientResponse) {
+ uint8_t remoteIpAddr[4];
+ uint16_t remotePortNu;
+ OC_LOG(INFO, TAG, "Entering applicationDiscoverCB (Application Layer CB)");
+ OCDevAddrToIPv4Addr((OCDevAddr *) clientResponse->addr, remoteIpAddr,
+ remoteIpAddr + 1, remoteIpAddr + 2, remoteIpAddr + 3);
+ OCDevAddrToPort((OCDevAddr *) clientResponse->addr, &remotePortNu);
+ OC_LOG_V(INFO, TAG, "Device =============> Discovered %s @ %d.%d.%d.%d:%d",clientResponse->resJSONPayload,remoteIpAddr[0], remoteIpAddr[1], remoteIpAddr[2], remoteIpAddr[3], remotePortNu);
+ //return OC_STACK_DELETE_TRANSACTION;
+ return OC_STACK_KEEP_TRANSACTION;
+}
+
+int main() {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+ OC_LOG_V(INFO, TAG, "Starting occlient on address %s",addr);
+
+ /* Initialize OCStack*/
+ if (OCInit((char *) addr, port, OC_CLIENT) != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ /* Start a discovery query*/
+ char szQueryUri[64] = { 0 };
+ strcpy(szQueryUri, OC_EXPLICIT_DEVICE_DISCOVERY_URI);
+ if (OCDoResource(OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE,
+ applicationDiscoverCB) != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "OCStack resource error");
+ return 0;
+ }
+
+ // Break from loop with Ctrl+C
+ OC_LOG(INFO, TAG, "Entering occlient main loop...");
+ signal(SIGINT, handleSigInt);
+ while (!gQuitFlag) {
+
+ if (OCProcess() != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+
+ sleep(1);
+ }OC_LOG(INFO, TAG, "Exiting occlient main loop...");
+
+ if (OCStop() != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "OCStack stop error");
+ }
+
+ return 0;
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <ocstack.h>
+
+#define TAG PCF("ocserver")
+
+int gQuitFlag = 0;
+void createLEDResource();
+
+typedef struct LEDRESOURCE{
+ OCResourceHandle handle;
+ bool power;
+} LEDResource;
+
+static LEDResource LED;
+
+/* SIGINT handler: set gQuitFlag to 1 for graceful termination */
+void handleSigInt(int signum) {
+ if (signum == SIGINT) {
+ gQuitFlag = 1;
+ }
+}
+
+int main() {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ if (OCInit((char *) addr, port, OC_SERVER) != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "OCStack init error");
+ return 0;
+ }
+
+ /*
+ * Declare and create the example resource: LED
+ */
+ createLEDResource();
+
+ // Break from loop with Ctrl-C
+ OC_LOG(INFO, TAG, "Entering ocserver main loop...");
+ signal(SIGINT, handleSigInt);
+ while (!gQuitFlag) {
+
+ if (OCProcess() != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ return 0;
+ }
+
+ sleep(1);
+ }
+
+ OC_LOG(INFO, TAG, "Exiting ocserver main loop...");
+
+ if (OCStop() != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "OCStack process error");
+ }
+
+ return 0;
+}
+
+void createLEDResource() {
+ LED.power = false;
+ OCStackResult res = OCCreateResource(&LED.handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE);
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+extern "C" {
+ #include "ocstack.h"
+ #include "ocstackinternal.h"
+ #include "logger.h"
+}
+
+#include "gtest/gtest.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+//-----------------------------------------------------------------------------
+// Includes
+//-----------------------------------------------------------------------------
+#include <stdio.h>
+#include <string.h>
+
+#include <iostream>
+#include <stdint.h>
+using namespace std;
+
+#define CTX_VAL 0x99
+//-----------------------------------------------------------------------------
+// Private variables
+//-----------------------------------------------------------------------------
+static const char TAG[] = "TestHarness";
+static const char *SERVICE_URI = "coap://127.0.0.1:5683/";
+
+//-----------------------------------------------------------------------------
+// Callback functions
+//-----------------------------------------------------------------------------
+extern "C" OCStackApplicationResult asyncDoResourcesCallback(void *ctx, OCClientResponse * clientResponse) {
+ OC_LOG(INFO, TAG, "Entering asyncDoResourcesCallback");
+
+ EXPECT_EQ(OC_STACK_OK, clientResponse->result);
+
+ if(ctx == (void*)CTX_VAL) {
+ OC_LOG_V(INFO, TAG, "Callback Context recvd successfully");
+ }
+ OC_LOG_V(INFO, TAG, "result = %d", clientResponse->result);
+}
+
+//-----------------------------------------------------------------------------
+// Resource creation stuff
+//-----------------------------------------------------------------------------
+// TODO - remove, temporarily kept for reference purposes
+#if 0
+const char *LEDrep[] = { "state;b", "power;i", (char *)NULL};
+CREATE_RESOURCE_TYPE(LED, "core.led", LEDrep);
+
+// Create the state and power attributes
+char stateValue[] = "0";
+CREATE_RESOURCE_ATTRIBUTE(stateAttr, "state", stateValue);
+
+char powerValue[] = "5";
+CREATE_RESOURCE_ATTRIBUTE(powerAttr, "power", powerValue);
+
+// Define the interface
+CREATE_RESOURCE_INTERFACE(LED, "core.rw", OC_REST_GET|OC_REST_PUT);
+
+// Define the resource; the space is allocated; but the resource has not been fully initialized
+CREATE_RESOURCE(LED, "/a/led", &LED_resourcetype, &LED_resourceinterface) ;
+
+
+// Define the entity handler for the resource
+void LED_ehandler(OCEntityHandlerFlag flag, const char *request, char *reponse, OCResourceHandle resource) {
+ /* Add code for entity handler */
+}
+#endif
+
+//-----------------------------------------------------------------------------
+// Tests
+//-----------------------------------------------------------------------------
+TEST(StackTest, StackInitNullAddr) {
+ EXPECT_EQ(OC_STACK_OK, OCInit(0, 5683, OC_SERVER));
+}
+
+TEST(StackTest, StackInitNullPort) {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 0, OC_SERVER));
+}
+
+TEST(StackTest, StackInitNullAddrAndPort) {
+ EXPECT_EQ(OC_STACK_OK, OCInit(0, 0, OC_SERVER));
+}
+
+TEST(StackTest, StackInitInvalidMode) {
+ EXPECT_EQ(OC_STACK_ERROR, OCInit(0, 0, (OCMode)10));
+}
+
+TEST(StackTest, StackStartSuccessClient) {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
+}
+
+TEST(StackTest, StackStartSuccessServer) {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
+}
+
+TEST(StackTest, StackStartSuccessClientServer) {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT_SERVER));
+}
+
+TEST(StackTest, StackStartSuccessiveInits) {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_SERVER));
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.2", 5683, OC_SERVER));
+}
+
+TEST(StackTest, DoResourceDeviceDiscovery) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+ OCCallbackData cbData;
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+ OC_LOG_V(INFO, TAG, "Starting DoResourceDeviceDiscovery test on address %s",addr);
+
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_CLIENT));
+ /* Start a discovery query*/
+ char szQueryUri[64] = { 0 };
+ strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
+ cbData.cb = asyncDoResourcesCallback;
+ cbData.context = (void*)CTX_VAL;
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData));
+ //EXPECT_EQ(OC_STACK_OK, OCUpdateResources(SERVICE_URI));
+ EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(StackTest, StackStopWithoutInit) {
+ EXPECT_EQ(OC_STACK_OK, OCInit("127.0.0.1", 5683, OC_CLIENT));
+ EXPECT_EQ(OC_STACK_OK, OCStop());
+ EXPECT_EQ(OC_STACK_ERROR, OCStop());
+}
+
+TEST(StackTest, UpdateResourceNullURI) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+ OCCallbackData cbData;
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+ OC_LOG_V(INFO, TAG, "Starting UpdateResourceNullURI test on address %s",addr);
+
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_CLIENT));
+ /* Start a discovery query*/
+ char szQueryUri[64] = { 0 };
+ strcpy(szQueryUri, OC_WELL_KNOWN_QUERY);
+ cbData.cb = asyncDoResourcesCallback;
+ cbData.context = (void*)CTX_VAL;
+ EXPECT_EQ(OC_STACK_OK, OCDoResource(OC_REST_GET, szQueryUri, 0, 0, OC_NON_CONFIRMABLE, &cbData));
+ //EXPECT_EQ(OC_STACK_INVALID_URI, OCUpdateResources(0));
+ EXPECT_EQ(OC_STACK_OK, OCStop());
+}
+
+TEST(StackTest, CreateResourceBadParams) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_ERROR, OCCreateResource(NULL, //&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ EXPECT_EQ(OC_STACK_ERROR, OCCreateResource(&handle,
+ NULL, //"core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ // Method bitmask out of range
+ EXPECT_EQ(OC_STACK_ERROR, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ 32, //OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ // OC_REST_NOMETHOD
+ EXPECT_EQ(OC_STACK_ERROR, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_NOMETHOD, //OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ // Property bitmask out of range
+ EXPECT_EQ(OC_STACK_ERROR, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ 16));//OC_DISCOVERABLE|OC_OBSERVABLE));
+}
+
+TEST(StackTest, CreateResourceSuccess) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ const char *url = OCGetResourceUri(handle);
+ EXPECT_STREQ("/a/led", url);
+}
+
+TEST(StackTest, CreateResourceFailDuplicateUri) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ const char *url = OCGetResourceUri(handle);
+ EXPECT_STREQ("/a/led", url);
+
+ EXPECT_EQ(OC_STACK_ERROR, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+}
+
+TEST(StackTest, CreateResourceMultipleResources) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle1;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led1",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ OCResourceHandle handle2;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led2",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ OCResourceHandle handle3;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle3,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led3",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ const char *url = OCGetResourceUri(handle1);
+ EXPECT_STREQ("/a/led1", url);
+
+ url = OCGetResourceUri(handle2);
+ EXPECT_STREQ("/a/led2", url);
+
+ url = OCGetResourceUri(handle3);
+ EXPECT_STREQ("/a/led3", url);
+
+}
+
+TEST(StackTest, CreateResourceBadResoureType) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_ERROR, OCCreateResource(&handle,
+ NULL, //"core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+}
+
+TEST(StackTest, CreateResourceGoodResourceType) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+}
+
+TEST(StackTest, ResourceTypeName) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceTypes;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes));
+ EXPECT_EQ(1, numResourceTypes);
+ const char *resourceTypeName = OCGetResourceTypeName(handle, 0);
+ EXPECT_STREQ("core.led", resourceTypeName);
+
+ // try getting resource type names with an invalid index
+ resourceTypeName = OCGetResourceTypeName(handle, 1);
+ EXPECT_STREQ(NULL, resourceTypeName);
+ // try getting resource type names with an invalid index
+ resourceTypeName = OCGetResourceTypeName(handle, 10);
+ EXPECT_STREQ(NULL, resourceTypeName);
+}
+
+TEST(StackTest, BindResourceTypeNameBad) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceTypes;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes));
+ EXPECT_EQ(1, numResourceTypes);
+ const char *resourceTypeName = OCGetResourceTypeName(handle, 0);
+ EXPECT_STREQ("core.led", resourceTypeName);
+
+ EXPECT_EQ(OC_STACK_ERROR, OCBindResourceTypeToResource(handle, NULL, "state:oc.bt.b;power:oc.bt.i"));
+}
+
+TEST(StackTest, BindResourceTypeNameGood) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceTypes;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes));
+ EXPECT_EQ(1, numResourceTypes);
+ const char *resourceTypeName = OCGetResourceTypeName(handle, 0);
+ EXPECT_STREQ("core.led", resourceTypeName);
+
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle, "core.brightled", "state:oc.bt.b;power:oc.bt.i"));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes));
+ EXPECT_EQ(2, numResourceTypes);
+ resourceTypeName = OCGetResourceTypeName(handle, 1);
+ EXPECT_STREQ("core.brightled", resourceTypeName);
+
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle, "core.reallybrightled", "state:oc.bt.b;power:oc.bt.i"));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes));
+ EXPECT_EQ(3, numResourceTypes);
+ resourceTypeName = OCGetResourceTypeName(handle, 2);
+ EXPECT_STREQ("core.reallybrightled", resourceTypeName);
+
+}
+
+TEST(StackTest, ResourceTypeAttrRepresentation) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceTypes;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes));
+ EXPECT_EQ(1, numResourceTypes);
+ const char *resourceTypeAttrRepresentation = OCGetResourceAttributeRepresentation(handle, 0);
+ EXPECT_STREQ("state:oc.bt.b;power:oc.bt.i", resourceTypeAttrRepresentation);
+
+ // try getting resource type attribute representations with an invalid index
+ resourceTypeAttrRepresentation = OCGetResourceAttributeRepresentation(handle, 1);
+ EXPECT_STREQ(NULL, resourceTypeAttrRepresentation);
+ // try getting resource type names with an invalid index
+ resourceTypeAttrRepresentation = OCGetResourceAttributeRepresentation(handle, 10);
+ EXPECT_STREQ(NULL, resourceTypeAttrRepresentation);
+}
+
+TEST(StackTest, BindResourceTypeAttribRepGood) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceTypes;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes));
+ EXPECT_EQ(1, numResourceTypes);
+ const char *resourceTypeAttrRepresentation = OCGetResourceAttributeRepresentation(handle, 0);
+ EXPECT_STREQ("state:oc.bt.b", resourceTypeAttrRepresentation);
+
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle, "core.brightled", "state:oc.bt.b;power:oc.bt.i"));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes));
+ EXPECT_EQ(2, numResourceTypes);
+ resourceTypeAttrRepresentation = OCGetResourceAttributeRepresentation(handle, 1);
+ EXPECT_STREQ("state:oc.bt.b;power:oc.bt.i", resourceTypeAttrRepresentation);
+
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle, "core.reallybrightled", "state:oc.bt.b;power:oc.bt.i;temp:oc.bt.i"));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceTypes(handle, &numResourceTypes));
+ EXPECT_EQ(3, numResourceTypes);
+ resourceTypeAttrRepresentation = OCGetResourceAttributeRepresentation(handle, 2);
+ EXPECT_STREQ("state:oc.bt.b;power:oc.bt.i;temp:oc.bt.i", resourceTypeAttrRepresentation);
+}
+
+TEST(StackTest, ResourceTypeInterface) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceInterfaces;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces));
+ EXPECT_EQ(1, numResourceInterfaces);
+ const char *resourceInterfaceName = OCGetResourceInterfaceName(handle, 0);
+ EXPECT_STREQ("core.rw", resourceInterfaceName);
+
+ // try getting resource interface names with an invalid index
+ resourceInterfaceName = OCGetResourceInterfaceName(handle, 1);
+ EXPECT_STREQ(NULL, resourceInterfaceName);
+ // try getting resource interface names with an invalid index
+ resourceInterfaceName = OCGetResourceInterfaceName(handle, 10);
+ EXPECT_STREQ(NULL, resourceInterfaceName);
+}
+
+TEST(StackTest, BindResourceInterfaceNameBad) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceInterfaces;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces));
+ EXPECT_EQ(1, numResourceInterfaces);
+ const char *resourceInterfaceName = OCGetResourceInterfaceName(handle, 0);
+ EXPECT_STREQ("core.rw", resourceInterfaceName);
+
+ EXPECT_EQ(OC_STACK_ERROR, OCBindResourceInterfaceToResource(handle, NULL, OC_REST_GET|OC_REST_PUT));
+}
+
+TEST(StackTest, BindResourceInterfaceNameGood) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceInterfaces;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces));
+ EXPECT_EQ(1, numResourceInterfaces);
+ const char *resourceInterfaceName = OCGetResourceInterfaceName(handle, 0);
+ EXPECT_STREQ("core.rw", resourceInterfaceName);
+
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle, "core.r", OC_REST_GET|OC_REST_PUT));
+
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces));
+ EXPECT_EQ(2, numResourceInterfaces);
+ resourceInterfaceName = OCGetResourceInterfaceName(handle, 1);
+ EXPECT_STREQ("core.r", resourceInterfaceName);
+}
+
+TEST(StackTest, ResourceTypeInterfaceMethods) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceInterfaces;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces));
+ EXPECT_EQ(1, numResourceInterfaces);
+ uint8_t resourceInterfaceMethods = OCGetResourceInterfaceAllowedMethods(handle, 0);
+ EXPECT_EQ(OC_REST_GET|OC_REST_PUT, resourceInterfaceMethods);
+
+ // try getting resource interface methods with an invalid index
+ resourceInterfaceMethods = OCGetResourceInterfaceAllowedMethods(handle, 1);
+ EXPECT_EQ(0, resourceInterfaceMethods);
+ // try getting resource interface methods with an invalid index
+ resourceInterfaceMethods = OCGetResourceInterfaceAllowedMethods(handle, 10);
+ EXPECT_EQ(0, resourceInterfaceMethods);
+}
+
+TEST(StackTest, BindResourceInterfaceMethodsBad) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceInterfaces;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces));
+ EXPECT_EQ(1, numResourceInterfaces);
+ uint8_t resourceInterfaceMethods = OCGetResourceInterfaceAllowedMethods(handle, 0);
+ EXPECT_EQ(OC_REST_GET|OC_REST_PUT, resourceInterfaceMethods);
+
+ EXPECT_EQ(OC_STACK_ERROR, OCBindResourceInterfaceToResource(handle, "core.rw", OC_REST_NOMETHOD));
+}
+
+TEST(StackTest, BindResourceInterfaceMethodsGood) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ uint8_t numResourceInterfaces;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces));
+ EXPECT_EQ(1, numResourceInterfaces);
+ uint8_t resourceInterfaceMethods = OCGetResourceInterfaceAllowedMethods(handle, 0);
+ EXPECT_EQ(OC_REST_GET|OC_REST_PUT, resourceInterfaceMethods);
+
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle, "core.r", OC_REST_PUT));
+
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle, &numResourceInterfaces));
+ EXPECT_EQ(2, numResourceInterfaces);
+ resourceInterfaceMethods = OCGetResourceInterfaceAllowedMethods(handle, 1);
+ EXPECT_EQ(OC_REST_PUT, resourceInterfaceMethods);
+}
+
+TEST(StackTest, BindContainedResourceBad) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle containerHandle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&containerHandle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/kitchen",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ OCResourceHandle handle0;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ EXPECT_EQ(OC_STACK_ERROR, OCBindContainedResourceToResource(containerHandle, containerHandle));
+
+ OCResourceHandle handle1;
+ EXPECT_EQ(OC_STACK_ERROR, OCBindContainedResourceToResource(handle1, handle0));
+}
+
+TEST(StackTest, BindContainedResourceGood) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ uint8_t numResources = 0;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(0, numResources);
+
+ OCResourceHandle containerHandle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&containerHandle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/kitchen",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(1, numResources);
+
+ OCResourceHandle handle0;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led0",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(2, numResources);
+
+ OCResourceHandle handle1;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led1",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(3, numResources);
+
+ OCResourceHandle handle2;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led2",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(4, numResources);
+
+ OCResourceHandle handle3;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle3,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led3",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(5, numResources);
+
+ OCResourceHandle handle4;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle4,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led4",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(6, numResources);
+
+ OCResourceHandle handle5;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle5,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led5",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(7, numResources);
+
+
+ EXPECT_EQ(OC_STACK_OK, OCBindContainedResourceToResource(containerHandle, handle0));
+ EXPECT_EQ(OC_STACK_OK, OCBindContainedResourceToResource(containerHandle, handle1));
+ EXPECT_EQ(OC_STACK_OK, OCBindContainedResourceToResource(containerHandle, handle2));
+ EXPECT_EQ(OC_STACK_OK, OCBindContainedResourceToResource(containerHandle, handle3));
+ EXPECT_EQ(OC_STACK_OK, OCBindContainedResourceToResource(containerHandle, handle4));
+ EXPECT_EQ(OC_STACK_ERROR, OCBindContainedResourceToResource(containerHandle, handle5));
+
+ EXPECT_EQ(handle0, OCGetContainedResourceHandle(containerHandle, 0));
+ EXPECT_EQ(handle1, OCGetContainedResourceHandle(containerHandle, 1));
+ EXPECT_EQ(handle2, OCGetContainedResourceHandle(containerHandle, 2));
+ EXPECT_EQ(handle3, OCGetContainedResourceHandle(containerHandle, 3));
+ EXPECT_EQ(handle4, OCGetContainedResourceHandle(containerHandle, 4));
+
+ EXPECT_EQ(NULL, OCGetContainedResourceHandle(containerHandle, 5));
+}
+
+TEST(StackTest, GetResourceByIndex) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ uint8_t numResources = 0;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(0, numResources);
+
+ OCResourceHandle containerHandle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&containerHandle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/kitchen",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(1, numResources);
+
+ OCResourceHandle handle0;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led0",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(2, numResources);
+
+ OCResourceHandle handle1;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led1",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(3, numResources);
+
+ OCResourceHandle handle2;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led2",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(4, numResources);
+
+ OCResourceHandle handle3;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle3,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led3",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(5, numResources);
+
+ OCResourceHandle handle4;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle4,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led4",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(6, numResources);
+
+ OCResourceHandle handle5;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle5,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led5",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(7, numResources);
+
+ EXPECT_EQ(containerHandle, OCGetResourceHandle(0));
+ EXPECT_EQ(handle0, OCGetResourceHandle(1));
+ EXPECT_EQ(handle1, OCGetResourceHandle(2));
+ EXPECT_EQ(handle2, OCGetResourceHandle(3));
+ EXPECT_EQ(handle3, OCGetResourceHandle(4));
+ EXPECT_EQ(handle4, OCGetResourceHandle(5));
+ EXPECT_EQ(handle5, OCGetResourceHandle(6));
+
+}
+
+TEST(StackTest, BindEntityHandlerBad) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ EXPECT_EQ(OC_STACK_ERROR, OCBindResourceHandler(handle, NULL));
+ EXPECT_EQ(OC_STACK_ERROR, OCBindResourceHandler(NULL, NULL));
+}
+
+
+void entityHandler(OCEntityHandlerFlag flag, OCEntityHandlerRequest * entityHandlerRequest) {
+ OC_LOG(INFO, TAG, "Entering entityHandler");
+}
+
+TEST(StackTest, BindEntityHandlerGood) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ OCEntityHandler myHandler = entityHandler;
+
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceHandler(handle, myHandler));
+
+ EXPECT_EQ(myHandler, OCGetResourceHandler(handle));
+}
+
+TEST(StackTest, DeleteHeadResource) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ uint8_t numResources = 0;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(0, numResources);
+
+ OCResourceHandle handle0;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led0",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(1, numResources);
+
+ EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle0));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(0, numResources);
+}
+
+TEST(StackTest, DeleteHeadResource2) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ uint8_t numResources = 0;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(0, numResources);
+
+ OCResourceHandle handle0;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led0",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(1, numResources);
+
+ OCResourceHandle handle1;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led1",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(2, numResources);
+
+ EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle0));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(1, numResources);
+
+ EXPECT_EQ(handle1, OCGetResourceHandle(0));
+}
+
+
+TEST(StackTest, DeleteLastResource) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ uint8_t numResources = 0;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(0, numResources);
+
+ OCResourceHandle handle0;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led0",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(1, numResources);
+
+ OCResourceHandle handle1;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led1",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(2, numResources);
+
+ EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle1));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(1, numResources);
+
+ EXPECT_EQ(handle0, OCGetResourceHandle(0));
+
+ OCResourceHandle handle2;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led2",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(2, numResources);
+}
+
+TEST(StackTest, DeleteMiddleResource) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ uint8_t numResources = 0;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(0, numResources);
+
+ OCResourceHandle handle0;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle0,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led0",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(1, numResources);
+
+ OCResourceHandle handle1;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led1",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(2, numResources);
+
+ OCResourceHandle handle2;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led2",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(3, numResources);
+
+ EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle1));
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(2, numResources);
+
+ EXPECT_EQ(handle0, OCGetResourceHandle(0));
+ EXPECT_EQ(handle2, OCGetResourceHandle(1));
+
+ // Make sure the resource elements are still correct
+ uint8_t numResourceInterfaces;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResourceInterfaces(handle2, &numResourceInterfaces));
+ EXPECT_EQ(1, numResourceInterfaces);
+ const char *resourceInterfaceName = OCGetResourceInterfaceName(handle2, 0);
+ EXPECT_STREQ("core.rw", resourceInterfaceName);
+}
+
+TEST(StackTest, GetResourceProperties) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+
+ EXPECT_EQ(OC_ACTIVE|OC_DISCOVERABLE|OC_OBSERVABLE, OCGetResourceProperties(handle));
+ EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle));
+}
+
+TEST(StackTest, StackTestResourceDiscoverOneResourceBad) {
+ // Setting URI to null which is an error
+ char uri[] = "";
+ char query[] = "";
+ char req[1024] = {};
+ char rsp[1024] = {};
+ //OCServerRequestResult res;
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a1/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ const char *url = OCGetResourceUri(handle);
+ EXPECT_STREQ("/a1/led", url);
+
+ //EXPECT_EQ(OC_STACK_INVALID_URI, OCHandleServerRequest(&res, uri, query, req, rsp));
+ EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle));
+ uint8_t numResources = 0;
+ EXPECT_EQ(OC_STACK_OK, OCGetNumberOfResources(&numResources));
+ EXPECT_EQ(0, numResources);
+
+}
+
+TEST(StackTest, StackTestResourceDiscoverOneResource) {
+ char uri[] = "/oc/core";
+ char query[] = "";
+ char req[1024] = {};
+ char rsp[1024] = {};
+ //OCServerRequestResult res;
+
+ OCResourceHandle handle;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ const char *url = OCGetResourceUri(handle);
+ EXPECT_STREQ("/a/led", url);
+
+ //EXPECT_EQ(OC_STACK_OK, OCHandleServerRequest(&res, uri, query, req, rsp));
+ EXPECT_EQ(OC_STACK_OK, OCDeleteResource(handle));
+}
+
+TEST(StackTest, StackTestResourceDiscoverManyResources) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+ char uri[] = "/oc/core";
+ char query[] = "";
+ char req[1024] = {};
+ char rsp[1024] = {};
+ //OCServerRequestResult res;
+
+ /*Get Ip address on defined interface and initialize coap on it with random port number
+ * this port number will be used as a source port in all coap communications*/
+ OCGetInterfaceAddress(ifname, sizeof(ifname), AF_INET, addr, sizeof(addr));
+
+ OC_LOG_V(INFO, TAG, "Starting ocserver on address %s:%d",addr,port);
+ EXPECT_EQ(OC_STACK_OK, OCInit((char *) addr, port, OC_SERVER));
+
+ OCResourceHandle handle1;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle1,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led1",
+ 0,
+ OC_DISCOVERABLE));
+ const char *url = OCGetResourceUri(handle1);
+ EXPECT_STREQ("/a/led1", url);
+
+ OCResourceHandle handle2;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle2,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led2",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ url = OCGetResourceUri(handle2);
+ EXPECT_STREQ("/a/led2", url);
+
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle2, "core.brightled",
+ "state:oc.bt.b;power:oc.bt.i"));
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle2, "core.colorled",
+ "state:oc.bt.b;power:oc.bt.i"));
+
+ OCResourceHandle handle3;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle3,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led3",
+ 0,
+ OC_DISCOVERABLE|OC_OBSERVABLE));
+ url = OCGetResourceUri(handle3);
+ EXPECT_STREQ("/a/led3", url);
+
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle3, "oc.mi.ll",
+ OC_REST_GET|OC_REST_PUT));
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle3, "oc.mi.b",
+ OC_REST_GET|OC_REST_PUT));
+
+ OCResourceHandle handle4;
+ EXPECT_EQ(OC_STACK_OK, OCCreateResource(&handle4,
+ "core.led",
+ "state:oc.bt.b;power:oc.bt.i",
+ "core.rw",
+ OC_REST_GET|OC_REST_PUT,
+ "/a/led4",
+ 0,
+ OC_DISCOVERABLE));
+ url = OCGetResourceUri(handle4);
+ EXPECT_STREQ("/a/led4", url);
+
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceTypeToResource(handle4, "core.brightled",
+ "state:oc.bt.b;power:oc.bt.i"));
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle4, "oc.mi.ll",
+ OC_REST_GET|OC_REST_PUT));
+ EXPECT_EQ(OC_STACK_OK, OCBindResourceInterfaceToResource(handle4, "oc.mi.b",
+ OC_REST_GET|OC_REST_PUT));
+
+ //EXPECT_EQ(OC_STACK_OK, OCHandleServerRequest(&res, uri, query, req, rsp));
+}
+
+TEST(StackTest, StackTestResourceDiscoverIfFilteringBad) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+ char uri[] = "/oc/core";
+ char query[] = "if";
+ char req[1024] = {};
+ char rsp[1024] = {};
+ //OCServerRequestResult res;
+
+ //EXPECT_EQ(OC_STACK_INVALID_QUERY, OCHandleServerRequest(&res, uri, query, req, rsp));
+}
+
+TEST(StackTest, StackTestResourceDiscoverRtFilteringBad) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+ char uri[] = "/oc/core";
+ char query[] = "rt";
+ char req[1024] = {};
+ char rsp[1024] = {};
+ //OCServerRequestResult res;
+
+ //EXPECT_EQ(OC_STACK_INVALID_QUERY, OCHandleServerRequest(&res, uri, query, req, rsp));
+}
+TEST(StackTest, StackTestResourceDiscoverIfFiltering) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+ char uri[] = "/oc/core";
+ char query[] = "if=oc.mi.ll";
+ char req[1024] = {};
+ char rsp[1024] = {};
+ //OCServerRequestResult res;
+
+ //EXPECT_EQ(OC_STACK_OK, OCHandleServerRequest(&res, uri, query, req, rsp));
+}
+
+TEST(StackTest, StackTestResourceDiscoverRtFiltering) {
+ uint8_t addr[20];
+ uint16_t port = USE_RANDOM_PORT;
+ uint8_t ifname[] = "eth0";
+ char uri[] = "/oc/core";
+ char query[] = "rt=core.brightled";
+ char req[1024] = {};
+ char rsp[1024] = {};
+ //OCServerRequestResult res;
+
+ //EXPECT_EQ(OC_STACK_OK, OCHandleServerRequest(&res, uri, query, req, rsp));
+}
--- /dev/null
+Build notes
+
+//-------------------------------------------------
+// Linux
+//-------------------------------------------------
+To build, run
+make
+
+To enable logging, ensure that
+-D TB_LOG
+is set in the compiler flags
+
+//-------------------------------------------------
+// Android
+//-------------------------------------------------
+To enable logging for Android, TB_LOG should be defined in the ./jni/Android.mk file as
+
+LOCAL_CFLAGS := -DTB_LOG
+
+
--- /dev/null
+//******************************************************************
+///
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef OCCORE_H_
+#define OCCORE_H_
+
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace oc {
+namespace ub {
+
+// ============================================================================
+// Enums
+// ============================================================================
+enum OCQueryResultType {
+ SUCCESS,
+ FAILURE
+};
+
+enum OCStackMode {
+ OC_CLIENT = 0,
+ OC_SERVER,
+ OC_CLIENT_SERVER
+};
+
+}
+}
+
+#ifdef CPPV11
+#include <mutex>
+ namespace oc {
+ namespace ub {
+ typedef std::mutex mutex;
+ typedef std::lock_guard<std::mutex> mutex_lock_guard;
+ }
+ }
+#else
+#include <boost/thread/mutex.hpp>
+#include <boost/thread/locks.hpp>
+ namespace oc {
+ namespace ub {
+ typedef boost::mutex mutex;
+ typedef boost::lock_guard<boost::mutex> mutex_lock_guard;
+ }
+ }
+#endif
+
+#endif /* OCCORE_H_ */
--- /dev/null
+//******************************************************************
+///
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef INTERNALUBAPI_H_
+#define INTERNALUBAPI_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <memory>
+#include <functional>
+#include <string>
+#include <list>
+#include <stdint.h>
+#include "occore.h"
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace oc {
+namespace ub {
+
+
+// ============================================================================
+// Class
+// ============================================================================
+class OCDiscoverServicesResult {
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~OCDiscoverServicesResult() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ virtual OCQueryResultType getResult() const = 0;
+ virtual const std::list<std::string>& getServiceList() const = 0;
+};
+
+typedef std::function<void (const OCDiscoverServicesResult&)> OCDiscoverServicesFunction;
+
+// ============================================================================
+// Class
+// ============================================================================
+class OCModel : public std::enable_shared_from_this<OCModel> {
+ // ============================================================
+ // Type Definition(s)
+ // ============================================================
+ public:
+ typedef std::shared_ptr<OCModel> SharedPtr;
+ typedef std::weak_ptr<OCModel> WeakPtr;
+
+ // ============================================================
+ // Factory
+ // ============================================================
+ public:
+ static SharedPtr createModel();
+
+ // ============================================================
+ // Destructor
+ // ============================================================
+ public:
+ virtual ~OCModel() {}
+
+ // ============================================================
+ // Public Method(s)
+ // ============================================================
+ public:
+ /**
+ * Start the OC Stack.
+ *
+ * @param ipAddr
+ * IP Address of host device
+ * @param port
+ * Port of host device
+ * @param mode
+ * Host device is client, server, or client-server
+ *
+ * @return
+ * true - successfully started the OC Stack
+ * false - error starting the OC Stack
+ */
+ virtual bool start(const std::string ipAddr, int16_t port, OCStackMode mode) = 0;
+
+ /**
+ * Get all services that have been discovered at time of call
+ *
+ * @param asyncReturnFunc - asynchronous callback function that is invoked
+ * by the OCModel when service discovery
+ * is complete. The callback will include
+ * status and a list of all discovered services
+ */
+ virtual void discoverServices(OCDiscoverServicesFunction& asyncReturnFunc) = 0;
+
+ /**
+ * Add a service to the OCModel
+ *
+ * @param url
+ * URL of the service
+ *
+ * @return
+ * Total number of services in the OCModel
+ */
+ virtual uint16_t addService(const std::string url) = 0;
+
+};
+
+
+}
+}
+
+#endif /* INTERNALUBAPI_H_ */
--- /dev/null
+# override with `make BUILD=release`
+# default to debug build
+BUILD := debug
+
+# You must create the file "local.properties" on your local machine which contains any local paths, etc
+# local_settings.mk should NOT be committed to repo
+include ./local.properties
+# GTEST_DIR contains the path to Google Test libs and must be defined in local.properties
+# Example:
+# GTEST_DIR := /home/johndoe/utils/gtest-1.7.0
+
+# NOTE: to run app, make sure that LD_LIBRARY_PATH env variable
+# contains $(GTEST_DIR)/lib/.libs
+
+CC := gcc
+CXX := g++
+
+PROG := ubstacktest
+
+SRC_DIR := ./src
+TEST_DIR:= ./test
+INC_DIR := ./include
+LOG_DIR := ../logger
+COAP_DIR := ../occoap
+STACK_DIR := ../stack
+
+CC_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c99 -fpic -D TB_LOG
+CC_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c99 -fpic
+CC_FLAGS := $(CC_FLAGS.$(BUILD))
+
+CXX_FLAGS.debug := -O0 -g3 -Wall -c -fmessage-length=0 -pedantic -std=c++0x -fpic -D TB_LOG
+CXX_FLAGS.release := -O0 -g3 -Wall -c -fmessage-length=0 -std=c++0x -fpic
+CXX_FLAGS := $(CXX_FLAGS.$(BUILD))
+
+INC := -I$(SRC_DIR)
+INC += -I$(TEST_DIR)
+INC += -I$(INC_DIR)
+INC += -I$(LOG_DIR)/include
+INC += -I$(COAP_DIR)/include
+INC += -I$(STACK_DIR)/include
+INC += -I$(STACK_DIR)/include/internal
+INC += -I$(GTEST_DIR)/include
+
+
+# using make's computed variables to select object and bin folders
+# depending on the build type
+OBJ_DIR.debug := ./obj/debug
+OBJ_DIR.release := ./obj/release
+OBJ_DIR := $(OBJ_DIR.$(BUILD))
+
+BIN_DIR.debug := ./bin/debug
+BIN_DIR.release := ./bin/release
+BIN_DIR := $(BIN_DIR.$(BUILD))
+
+C_FILES := $(wildcard $(LOG_DIR)/src/*.c)
+C_FILES += $(wildcard $(COAP_DIR)/src/*.c)
+C_FILES += $(wildcard $(STACK_DIR)/src/*.c)
+CPP_FILES := $(wildcard $(SRC_DIR)/*.cpp)
+CPP_FILES += $(wildcard $(TEST_DIR)/*.cpp)
+CPP_FILES += $(wildcard $(TEST_DIR)/*.cpp)
+
+OBJ_FILES := $(addprefix $(OBJ_DIR)/,$(notdir $(CPP_FILES:.cpp=.o) $(C_FILES:.c=.o)))
+H_FILES := $(wildcard $(TEST_DIR)/*.h)
+H_FILES += $(wildcard $(INC_DIR)/*.h)
+H_FILES += $(wildcard $(LOG_DIR)/include/*.h)
+LD_FLAGS := -L/usr/lib
+LD_FLAGS += -L$(GTEST_DIR)/lib/.libs
+
+
+LIBS := -lpthread
+LIBS += -lgtest
+LIBS += -lgtest_main
+
+
+all: $(PROG)
+ mkdir -p ./$(OBJ_DIR)
+ mkdir -p ./$(BIN_DIR)
+
+
+$(PROG): $(OBJ_FILES)
+ $(CXX) -o $@ $^ $(LD_FLAGS) $(LIBS)
+ mkdir -p ./$(BIN_DIR)
+ mv ./$(PROG) ./$(BIN_DIR)
+
+# UB Stack
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(SRC_DIR)/%.h $(H_FILES)
+ mkdir -p ./$(OBJ_DIR)
+ $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+# UB Stack
+$(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp $(INC_DIR)/%.h $(H_FILES)
+ mkdir -p ./$(OBJ_DIR)
+ $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+# UB Stack unit test
+$(OBJ_DIR)/%.o: $(TEST_DIR)/%.cpp $(H_FILES)
+ mkdir -p ./$(OBJ_DIR)
+ $(CXX) $(CXX_FLAGS) $(INC) -c -o $@ $<
+
+# Logger
+$(OBJ_DIR)/%.o: $(LOG_DIR)/src/%.c $(LOG_DIR)/include/%.h $(H_FILES)
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+# Stack
+$(OBJ_DIR)/%.o: $(STACK_DIR)/src/%.c $(STACK_DIR)/include/%.h $(H_FILES)
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+# OCCoAP
+$(OBJ_DIR)/%.o: $(COAP_DIR)/src/%.c $(COAP_DIR)/include/%.h $(H_FILES)
+ mkdir -p ./$(OBJ_DIR)
+ $(CC) $(CC_FLAGS) $(INC) -c -o $@ $<
+
+.PHONY: clean
+clean :
+ rm -rf ./obj/debug/*
+ rm -rf ./obj/release/*
+ rm -rf ./lib/*
+ rm -rf ./bin/debug/*
+ rm -rf ./bin/release/*
+
+
+.PHONY: print_vars
+
+print_vars:
+ @echo ""
+ @echo 'BUILD = '$(value BUILD)
+ @echo 'INC = '$(value INC)
+ @echo 'CPP_FILES = '$(value CPP_FILES)
+ @echo 'LIBS = '$(value LIBS)
+
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include "ocmodelimpl.h"
+extern "C" {
+ #include "logger.h"
+}
+
+#include <stdlib.h>
+#include <time.h>
+#include <cstdlib>
+
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace oc {
+namespace ub {
+
+static const char TAG[] = "OCModelImpl";
+
+// Global variable used by friend async callback function to access the OCModelImpl instance
+OCModelImpl *pModelImpl = 0;
+
+/**
+ * Asynchronous callback friend function invoked by the OC Stack upon service discovery
+ *
+ * @param result - OC stack result
+ * @param representation - handle to the representation of the resource
+ */
+void asyncDoResourcesCallback(OCStackResult result, OCRepresentationHandle representation) {
+ OC_LOG(INFO, TAG, "Entering asyncDoResourcesCallback");
+
+ if (representation && (result == OC_STACK_OK)) {
+ OCResource *resource = (OCResource *)representation;
+ OC_LOG_V(INFO, TAG, "URI = %s", resource->uri);
+
+ // If the pointer is valid, make a call to the OCModelImpl instance method
+ if (pModelImpl) {
+ pModelImpl->addService(resource->uri);
+ }
+ }
+}
+
+// ============================================================================
+// OCDiscoverServicesResult Implementation Class
+// ============================================================================
+class OCDiscoverServicesSuccess : public OCDiscoverServicesResult {
+public:
+ virtual ~OCDiscoverServicesSuccess() {}
+
+// ============================================================
+// Public Method(s)
+// ============================================================
+public:
+ virtual OCQueryResultType getResult() const {
+ return SUCCESS;
+ }
+
+ virtual const std::list<std::string>& getServiceList() const {
+ return serviceList;
+ }
+
+public:
+ std::list<std::string> serviceList;
+};
+
+
+// ============================================================================
+// Model Factory
+// ============================================================================
+OCModel::SharedPtr OCModel::createModel() {
+ OC_LOG(INFO, TAG, "Entering OCModel::createModel");
+ return OCModelImpl::createModel();
+}
+
+OCModelImpl::SharedPtr OCModelImpl::createModel() {
+ // Get singleton of ModelImpl.
+ OC_LOG(INFO, TAG, "Entering OCModelImpl::createModel");
+ static SharedPtr instance = std::make_shared<OCModelImpl>();
+
+ return instance;
+}
+// ============================================================================
+// Constructors & Destructors
+// ============================================================================
+OCModelImpl::OCModelImpl() {
+ OC_LOG(INFO, TAG, "Entering OCModel::OCModelImpl");
+
+ pModelImpl = this;
+ discoverCallback = 0;
+}
+
+OCModelImpl::~OCModelImpl() {
+ OC_LOG(INFO, TAG, "Entering OCModel::~OCModelImpl");
+ // Call OCStack layer
+ if (OCStop() != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "Stack shutdown error");
+ }
+
+ discoverCallback = 0;
+ serviceList.clear();
+}
+
+// ============================================================================
+// Public methods
+// ============================================================================
+/**
+ * Start the OC Stack.
+ *
+ * @param ipAddr
+ * IP Address of host device
+ * @param port
+ * Port of host device*
+ * @param mode
+ * Host device is client, server, or client-server
+ *
+ * @return
+ * true - successfully started the OC Stack
+ * false - error starting the OC Stack
+ */
+bool OCModelImpl::start(const std::string ipAddr, int16_t port, OCStackMode mode) {
+ OC_LOG_V(INFO, TAG, "Entering OCModelImpl::start, IP = %s, port = %d", ipAddr.c_str(), (int)port);
+
+ // Call OCStack layer - initialize stack
+ if (OCInit(ipAddr.c_str(), port, (OCMode)mode) != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "Stack initialization error");
+ return false;
+ }
+
+ // Call OCStack layer - enable device discovery and provide a callback
+ if (OCDoResource(OC_REST_GET, OC_EXPLICIT_DEVICE_DISCOVERY_URI, 0, 0, asyncDoResourcesCallback) != OC_STACK_OK) {
+ OC_LOG(ERROR, TAG, "Stack discovery error");
+ return false;
+ }
+ return true;
+}
+
+/**
+ * Get all services that have been discovered at time of call
+ *
+ * @param asyncReturnFunc - asynchronous callback function that is invoked
+ * by the OCModelImpl when service discovery
+ * is complete. The callback will include
+ * status and a list of all discovered services
+ */
+void OCModelImpl::discoverServices(OCDiscoverServicesFunction& asyncReturnFunc) {
+ OC_LOG(INFO, TAG, "Entering OCModelImpl::discoverServices");
+
+ mutex_lock_guard lock(serviceListMutex);
+
+ // Save the callback
+ discoverCallback = asyncReturnFunc;
+
+ // Invoke the callback immediately
+ invokeDiscoverCallback();
+}
+
+/**
+ * Add a service to the OCModelImpl
+ *
+ * @param url - URL of the service
+ * @return Total number of services in the OCModelImpl
+ */
+uint16_t OCModelImpl::addService(const std::string url) {
+ OC_LOG_V(INFO, TAG, "Entering OCModelImpl::addService, service = %s", url.c_str());
+ serviceList.push_back(url);
+
+ invokeDiscoverCallback();
+ return (uint16_t)serviceList.size();
+}
+
+/**
+ * Internal methods that invokes the client callback (if it was previously set via discoverServices)
+ * Called when a new service is discovered.
+ */
+void OCModelImpl::invokeDiscoverCallback() {
+ OC_LOG(INFO, TAG, "Entering OCModelImpl::invokeDiscoverCallback");
+ // Only invoke the callback if it has been set and and at least one service has been added
+ // to the service list
+ if (discoverCallback && (serviceList.size() > 0)) {
+ OC_LOG(INFO, TAG, "Invoking callback");
+
+ OCDiscoverServicesSuccess result;
+ // Insert from the model device list to the result device list
+ result.serviceList.insert(result.serviceList.end(), serviceList.begin(), serviceList.end());
+
+ // Invoke the callback
+ discoverCallback(result);
+ }
+}
+
+}
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#ifndef OCMODELIMPL_H_
+#define OCMODELIMPL_H_
+
+// ============================================================================
+// Includes
+// ============================================================================
+#include <memory>
+#include <map>
+#include <stdint.h>
+
+#include "ocinternalapi.h"
+
+extern "C" {
+ #include "ocstack.h"
+}
+// ============================================================================
+// Namespace
+// ============================================================================
+namespace oc {
+namespace ub {
+
+class OCModelImpl : public OCModel {
+public:
+ typedef std::shared_ptr<OCModelImpl> SharedPtr;
+ typedef std::weak_ptr<OCModelImpl> WeakPtr;
+
+public:
+ /**
+ * Factory pattern to create a OCModel singleton
+ * @return Shared pointer to the OCModel
+ */
+ static SharedPtr createModel();
+
+public:
+ /**
+ * Constructor
+ */
+ OCModelImpl();
+
+ /**
+ * Destructor
+ */
+ virtual ~OCModelImpl();
+
+ /**
+ * Start the OC Stack.
+ *
+ * @param ipAddr
+ * IP Address of host device
+ * @param port
+ * Port of host device*
+ * @param mode
+ * Host device is client, server, or client-server
+ *
+ * @return
+ * true - successfully started the OC Stack
+ * false - error starting the OC Stack
+ */
+ virtual bool start(const std::string ipAddr, int16_t port, OCStackMode mode);
+
+ /**
+ * Get all services that have been discovered at time of call
+ *
+ * @param asyncReturnFunc - asynchronous callback function that is invoked
+ * by the OCModelImpl when service discovery
+ * is complete. The callback will include
+ * status and a list of all discovered services
+ */
+ virtual void discoverServices(OCDiscoverServicesFunction& asyncReturnFunc);
+
+ /**
+ * Add a service to the OCModelImpl
+ *
+ * @param url - URL of the service
+ * @return Total number of services in the OCModelImpl
+ */
+ virtual uint16_t addService(const std::string url);
+
+private:
+ typedef std::list<std::string> ServiceList;
+
+private:
+ /**
+ * Internal methods that invokes the client callback (if it was previously set via discoverServices)
+ * Called when a new service is discovered.
+ */
+ virtual void invokeDiscoverCallback();
+
+ /**
+ * Asynchronous callback friend function invoked by the OC Stack upon service discovery
+ *
+ * @param result - OC stack result
+ * @param representation - handle to the representation of the resource
+ */
+ friend void asyncDoResourcesCallback(OCStackResult result, OCRepresentationHandle representation);
+private:
+ ServiceList serviceList;
+ mutex serviceListMutex;
+ OCDiscoverServicesFunction discoverCallback;
+};
+
+}
+}
+#endif /* OCMODELIMPL_H_ */
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include "ocinternalapi.h"
+extern "C" {
+ #include "logger.h"
+ #include "ocstack.h"
+ #include "ocstackinternal.h"
+}
+
+#include "gtest/gtest.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#include <iostream>
+#include <stdint.h>
+using namespace std;
+
+
+static const char TAG[] = "TestHarness";
+static const std::string SERVICE_URI_1 = "coap://127.0.0.1:5683/";
+static const std::string SERVICE_URI_2 = "coap://127.0.0.2:5683/";
+static const std::string SERVICE_URI_3 = "coap://127.0.0.3:5683/";
+
+void discoverServicesAsync(const oc::ub::OCDiscoverServicesResult& result) {
+ OC_LOG(INFO, TAG, "Entering discoverServicesAsync");
+
+ EXPECT_EQ(oc::ub::OCQueryResultType::SUCCESS, result.getResult());
+
+ if (result.getResult() == oc::ub::OCQueryResultType::SUCCESS) {
+ OC_LOG(INFO, TAG, "discoverServicesAsync, OCQueryResultType::SUCCESS");
+
+ std::list<std::string> serviceList = result.getServiceList();
+ EXPECT_GE((int)serviceList.size(), 1);
+
+ if (serviceList.size() > 0) {
+ for (auto iter = serviceList.begin(); iter != serviceList.end(); ++iter) {
+ OC_LOG_V(INFO, TAG, "discoverServicesAsync, Service = %s", iter->c_str());
+ }
+ }
+ }
+}
+//-----------------------------------------------------------------------------
+// Tests
+//-----------------------------------------------------------------------------
+TEST(UBStackTest, ServiceDiscovery) {
+ OC_LOG(INFO, TAG, "Running ServiceDiscovery");
+
+ oc::ub::OCModel::WeakPtr modelWeak = oc::ub::OCModel::createModel();
+ oc::ub::OCModel::SharedPtr modelShared = modelWeak.lock();
+ EXPECT_TRUE((modelShared != 0));
+ if (modelShared) {
+ // Start model
+ EXPECT_TRUE(modelShared->start("127.0.0.1", 5683, oc::ub::OC_CLIENT));
+
+ // Create an async discovery function
+ oc::ub::OCDiscoverServicesFunction serviceFunction = discoverServicesAsync;
+
+ // Discover
+ modelShared->discoverServices(serviceFunction);
+
+ // Add service
+ EXPECT_EQ(1, (int)modelShared->addService(SERVICE_URI_1));
+
+ // Add service
+ EXPECT_EQ(2, (int)modelShared->addService(SERVICE_URI_2));
+
+ // Add service via OC Stack
+ OCUpdateResources(SERVICE_URI_3.c_str());
+ }
+}
+
+
--- /dev/null
+/*
+ Copyright (c) 2009 Dave Gamble
+
+ 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.
+*/
+
+/* cJSON */
+/* JSON parser in C. */
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+#include <stdlib.h>
+#include <float.h>
+#include <limits.h>
+#include <ctype.h>
+#include "cJSON.h"
+
+static const char *ep;
+
+const char *cJSON_GetErrorPtr(void) {return ep;}
+
+static int cJSON_strcasecmp(const char *s1,const char *s2)
+{
+ if (!s1) return (s1==s2)?0:1;if (!s2) return 1;
+ for(; tolower(*s1) == tolower(*s2); ++s1, ++s2) if(*s1 == 0) return 0;
+ return tolower(*(const unsigned char *)s1) - tolower(*(const unsigned char *)s2);
+}
+
+static void *(*cJSON_malloc)(size_t sz) = malloc;
+static void (*cJSON_free)(void *ptr) = free;
+
+static char* cJSON_strdup(const char* str)
+{
+ size_t len;
+ char* copy;
+
+ len = strlen(str) + 1;
+ if (!(copy = (char*)cJSON_malloc(len))) return 0;
+ memcpy(copy,str,len);
+ return copy;
+}
+
+void cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+ if (!hooks) { /* Reset hooks */
+ cJSON_malloc = malloc;
+ cJSON_free = free;
+ return;
+ }
+
+ cJSON_malloc = (hooks->malloc_fn)?hooks->malloc_fn:malloc;
+ cJSON_free = (hooks->free_fn)?hooks->free_fn:free;
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(void)
+{
+ cJSON* node = (cJSON*)cJSON_malloc(sizeof(cJSON));
+ if (node) memset(node,0,sizeof(cJSON));
+ return node;
+}
+
+/* Delete a cJSON structure. */
+void cJSON_Delete(cJSON *c)
+{
+ cJSON *next;
+ while (c)
+ {
+ next=c->next;
+ if (!(c->type&cJSON_IsReference) && c->child) cJSON_Delete(c->child);
+ if (!(c->type&cJSON_IsReference) && c->valuestring) cJSON_free(c->valuestring);
+ if (c->string) cJSON_free(c->string);
+ cJSON_free(c);
+ c=next;
+ }
+}
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static const char *parse_number(cJSON *item,const char *num)
+{
+ double n=0,sign=1,scale=0;int subscale=0,signsubscale=1;
+
+ if (*num=='-') sign=-1,num++; /* Has sign? */
+ if (*num=='0') num++; /* is zero */
+ if (*num>='1' && *num<='9') do n=(n*10.0)+(*num++ -'0'); while (*num>='0' && *num<='9'); /* Number? */
+ if (*num=='.' && num[1]>='0' && num[1]<='9') {num++; do n=(n*10.0)+(*num++ -'0'),scale--; while (*num>='0' && *num<='9');} /* Fractional part? */
+ if (*num=='e' || *num=='E') /* Exponent? */
+ { num++;if (*num=='+') num++; else if (*num=='-') signsubscale=-1,num++; /* With sign? */
+ while (*num>='0' && *num<='9') subscale=(subscale*10)+(*num++ - '0'); /* Number? */
+ }
+
+ n=sign*n*pow(10.0,(scale+subscale*signsubscale)); /* number = +/- number.fraction * 10^+/- exponent */
+
+ item->valuedouble=n;
+ item->valueint=(int)n;
+ item->type=cJSON_Number;
+ return num;
+}
+
+/* Render the number nicely from the given item into a string. */
+static char *print_number(cJSON *item)
+{
+ char *str;
+ double d=item->valuedouble;
+ if (fabs(((double)item->valueint)-d)<=DBL_EPSILON && d<=INT_MAX && d>=INT_MIN)
+ {
+ str=(char*)cJSON_malloc(21); /* 2^64+1 can be represented in 21 chars. */
+ if (str) sprintf(str,"%d",item->valueint);
+ }
+ else
+ {
+ str=(char*)cJSON_malloc(64); /* This is a nice tradeoff. */
+ if (str)
+ {
+ if (fabs(floor(d)-d)<=DBL_EPSILON && fabs(d)<1.0e60)sprintf(str,"%.0f",d);
+ else if (fabs(d)<1.0e-6 || fabs(d)>1.0e9) sprintf(str,"%e",d);
+ else sprintf(str,"%f",d);
+ }
+ }
+ return str;
+}
+
+static unsigned parse_hex4(const char *str)
+{
+ unsigned h=0;
+ if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+ h=h<<4;str++;
+ if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+ h=h<<4;str++;
+ if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+ h=h<<4;str++;
+ if (*str>='0' && *str<='9') h+=(*str)-'0'; else if (*str>='A' && *str<='F') h+=10+(*str)-'A'; else if (*str>='a' && *str<='f') h+=10+(*str)-'a'; else return 0;
+ return h;
+}
+
+/* Parse the input text into an unescaped cstring, and populate item. */
+static const unsigned char firstByteMark[7] = { 0x00, 0x00, 0xC0, 0xE0, 0xF0, 0xF8, 0xFC };
+static const char *parse_string(cJSON *item,const char *str)
+{
+ const char *ptr=str+1;char *ptr2;char *out;int len=0;unsigned uc,uc2;
+ if (*str!='\"') {ep=str;return 0;} /* not a string! */
+
+ while (*ptr!='\"' && *ptr && ++len) if (*ptr++ == '\\') ptr++; /* Skip escaped quotes. */
+
+ out=(char*)cJSON_malloc(len+1); /* This is how long we need for the string, roughly. */
+ if (!out) return 0;
+
+ ptr=str+1;ptr2=out;
+ while (*ptr!='\"' && *ptr)
+ {
+ if (*ptr!='\\') *ptr2++=*ptr++;
+ else
+ {
+ ptr++;
+ switch (*ptr)
+ {
+ case 'b': *ptr2++='\b'; break;
+ case 'f': *ptr2++='\f'; break;
+ case 'n': *ptr2++='\n'; break;
+ case 'r': *ptr2++='\r'; break;
+ case 't': *ptr2++='\t'; break;
+ case 'u': /* transcode utf16 to utf8. */
+ uc=parse_hex4(ptr+1);ptr+=4; /* get the unicode char. */
+
+ if ((uc>=0xDC00 && uc<=0xDFFF) || uc==0) break; /* check for invalid. */
+
+ if (uc>=0xD800 && uc<=0xDBFF) /* UTF16 surrogate pairs. */
+ {
+ if (ptr[1]!='\\' || ptr[2]!='u') break; /* missing second-half of surrogate. */
+ uc2=parse_hex4(ptr+3);ptr+=6;
+ if (uc2<0xDC00 || uc2>0xDFFF) break; /* invalid second-half of surrogate. */
+ uc=0x10000 + (((uc&0x3FF)<<10) | (uc2&0x3FF));
+ }
+
+ len=4;if (uc<0x80) len=1;else if (uc<0x800) len=2;else if (uc<0x10000) len=3; ptr2+=len;
+
+ switch (len) {
+ case 4: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+ case 3: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+ case 2: *--ptr2 =((uc | 0x80) & 0xBF); uc >>= 6;
+ case 1: *--ptr2 =(uc | firstByteMark[len]);
+ }
+ ptr2+=len;
+ break;
+ default: *ptr2++=*ptr; break;
+ }
+ ptr++;
+ }
+ }
+ *ptr2=0;
+ if (*ptr=='\"') ptr++;
+ item->valuestring=out;
+ item->type=cJSON_String;
+ return ptr;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static char *print_string_ptr(const char *str)
+{
+ const char *ptr;char *ptr2,*out;int len=0;unsigned char token;
+
+ if (!str) return cJSON_strdup("");
+ ptr=str;while ((token=*ptr) && ++len) {if (strchr("\"\\\b\f\n\r\t",token)) len++; else if (token<32) len+=5;ptr++;}
+
+ out=(char*)cJSON_malloc(len+3);
+ if (!out) return 0;
+
+ ptr2=out;ptr=str;
+ *ptr2++='\"';
+ while (*ptr)
+ {
+ if ((unsigned char)*ptr>31 && *ptr!='\"' && *ptr!='\\') *ptr2++=*ptr++;
+ else
+ {
+ *ptr2++='\\';
+ switch (token=*ptr++)
+ {
+ case '\\': *ptr2++='\\'; break;
+ case '\"': *ptr2++='\"'; break;
+ case '\b': *ptr2++='b'; break;
+ case '\f': *ptr2++='f'; break;
+ case '\n': *ptr2++='n'; break;
+ case '\r': *ptr2++='r'; break;
+ case '\t': *ptr2++='t'; break;
+ default: sprintf(ptr2,"u%04x",token);ptr2+=5; break; /* escape and print */
+ }
+ }
+ }
+ *ptr2++='\"';*ptr2++=0;
+ return out;
+}
+/* Invote print_string_ptr (which is useful) on an item. */
+static char *print_string(cJSON *item) {return print_string_ptr(item->valuestring);}
+
+/* Predeclare these prototypes. */
+static const char *parse_value(cJSON *item,const char *value);
+static char *print_value(cJSON *item,int depth,int fmt);
+static const char *parse_array(cJSON *item,const char *value);
+static char *print_array(cJSON *item,int depth,int fmt);
+static const char *parse_object(cJSON *item,const char *value);
+static char *print_object(cJSON *item,int depth,int fmt);
+
+/* Utility to jump whitespace and cr/lf */
+static const char *skip(const char *in) {while (in && *in && (unsigned char)*in<=32) in++; return in;}
+
+/* Parse an object - create a new root, and populate. */
+cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated)
+{
+ const char *end=0;
+ cJSON *c=cJSON_New_Item();
+ ep=0;
+ if (!c) return 0; /* memory fail */
+
+ end=parse_value(c,skip(value));
+ if (!end) {cJSON_Delete(c);return 0;} /* parse failure. ep is set. */
+
+ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+ if (require_null_terminated) {end=skip(end);if (*end) {cJSON_Delete(c);ep=end;return 0;}}
+ if (return_parse_end) *return_parse_end=end;
+ return c;
+}
+/* Default options for cJSON_Parse */
+cJSON *cJSON_Parse(const char *value) {return cJSON_ParseWithOpts(value,0,0);}
+
+/* Render a cJSON item/entity/structure to text. */
+char *cJSON_Print(cJSON *item) {return print_value(item,0,1);}
+char *cJSON_PrintUnformatted(cJSON *item) {return print_value(item,0,0);}
+
+/* Parser core - when encountering text, process appropriately. */
+static const char *parse_value(cJSON *item,const char *value)
+{
+ if (!value) return 0; /* Fail on null. */
+ if (!strncmp(value,"null",4)) { item->type=cJSON_NULL; return value+4; }
+ if (!strncmp(value,"false",5)) { item->type=cJSON_False; return value+5; }
+ if (!strncmp(value,"true",4)) { item->type=cJSON_True; item->valueint=1; return value+4; }
+ if (*value=='\"') { return parse_string(item,value); }
+ if (*value=='-' || (*value>='0' && *value<='9')) { return parse_number(item,value); }
+ if (*value=='[') { return parse_array(item,value); }
+ if (*value=='{') { return parse_object(item,value); }
+
+ ep=value;return 0; /* failure. */
+}
+
+/* Render a value to text. */
+static char *print_value(cJSON *item,int depth,int fmt)
+{
+ char *out=0;
+ if (!item) return 0;
+ switch ((item->type)&255)
+ {
+ case cJSON_NULL: out=cJSON_strdup("null"); break;
+ case cJSON_False: out=cJSON_strdup("false");break;
+ case cJSON_True: out=cJSON_strdup("true"); break;
+ case cJSON_Number: out=print_number(item);break;
+ case cJSON_String: out=print_string(item);break;
+ case cJSON_Array: out=print_array(item,depth,fmt);break;
+ case cJSON_Object: out=print_object(item,depth,fmt);break;
+ }
+ return out;
+}
+
+/* Build an array from input text. */
+static const char *parse_array(cJSON *item,const char *value)
+{
+ cJSON *child;
+ if (*value!='[') {ep=value;return 0;} /* not an array! */
+
+ item->type=cJSON_Array;
+ value=skip(value+1);
+ if (*value==']') return value+1; /* empty array. */
+
+ item->child=child=cJSON_New_Item();
+ if (!item->child) return 0; /* memory fail */
+ value=skip(parse_value(child,skip(value))); /* skip any spacing, get the value. */
+ if (!value) return 0;
+
+ while (*value==',')
+ {
+ cJSON *new_item;
+ if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
+ child->next=new_item;new_item->prev=child;child=new_item;
+ value=skip(parse_value(child,skip(value+1)));
+ if (!value) return 0; /* memory fail */
+ }
+
+ if (*value==']') return value+1; /* end of array */
+ ep=value;return 0; /* malformed. */
+}
+
+/* Render an array to text */
+static char *print_array(cJSON *item,int depth,int fmt)
+{
+ char **entries;
+ char *out=0,*ptr,*ret;int len=5;
+ cJSON *child=item->child;
+ int numentries=0,i=0,fail=0;
+
+ /* How many entries in the array? */
+ while (child) numentries++,child=child->next;
+ /* Explicitly handle numentries==0 */
+ if (!numentries)
+ {
+ out=(char*)cJSON_malloc(3);
+ if (out) strcpy(out,"[]");
+ return out;
+ }
+ /* Allocate an array to hold the values for each */
+ entries=(char**)cJSON_malloc(numentries*sizeof(char*));
+ if (!entries) return 0;
+ memset(entries,0,numentries*sizeof(char*));
+ /* Retrieve all the results: */
+ child=item->child;
+ while (child && !fail)
+ {
+ ret=print_value(child,depth+1,fmt);
+ entries[i++]=ret;
+ if (ret) len+=strlen(ret)+2+(fmt?1:0); else fail=1;
+ child=child->next;
+ }
+
+ /* If we didn't fail, try to malloc the output string */
+ if (!fail) out=(char*)cJSON_malloc(len);
+ /* If that fails, we fail. */
+ if (!out) fail=1;
+
+ /* Handle failure. */
+ if (fail)
+ {
+ for (i=0;i<numentries;i++) if (entries[i]) cJSON_free(entries[i]);
+ cJSON_free(entries);
+ return 0;
+ }
+
+ /* Compose the output array. */
+ *out='[';
+ ptr=out+1;*ptr=0;
+ for (i=0;i<numentries;i++)
+ {
+ strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
+ if (i!=numentries-1) {*ptr++=',';if(fmt)*ptr++=' ';*ptr=0;}
+ cJSON_free(entries[i]);
+ }
+ cJSON_free(entries);
+ *ptr++=']';*ptr++=0;
+ return out;
+}
+
+/* Build an object from the text. */
+static const char *parse_object(cJSON *item,const char *value)
+{
+ cJSON *child;
+ if (*value!='{') {ep=value;return 0;} /* not an object! */
+
+ item->type=cJSON_Object;
+ value=skip(value+1);
+ if (*value=='}') return value+1; /* empty array. */
+
+ item->child=child=cJSON_New_Item();
+ if (!item->child) return 0;
+ value=skip(parse_string(child,skip(value)));
+ if (!value) return 0;
+ child->string=child->valuestring;child->valuestring=0;
+ if (*value!=':') {ep=value;return 0;} /* fail! */
+ value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
+ if (!value) return 0;
+
+ while (*value==',')
+ {
+ cJSON *new_item;
+ if (!(new_item=cJSON_New_Item())) return 0; /* memory fail */
+ child->next=new_item;new_item->prev=child;child=new_item;
+ value=skip(parse_string(child,skip(value+1)));
+ if (!value) return 0;
+ child->string=child->valuestring;child->valuestring=0;
+ if (*value!=':') {ep=value;return 0;} /* fail! */
+ value=skip(parse_value(child,skip(value+1))); /* skip any spacing, get the value. */
+ if (!value) return 0;
+ }
+
+ if (*value=='}') return value+1; /* end of array */
+ ep=value;return 0; /* malformed. */
+}
+
+/* Render an object to text. */
+static char *print_object(cJSON *item,int depth,int fmt)
+{
+ char **entries=0,**names=0;
+ char *out=0,*ptr,*ret,*str;int len=7,i=0,j;
+ cJSON *child=item->child;
+ int numentries=0,fail=0;
+ /* Count the number of entries. */
+ while (child) numentries++,child=child->next;
+ /* Explicitly handle empty object case */
+ if (!numentries)
+ {
+ out=(char*)cJSON_malloc(fmt?depth+4:3);
+ if (!out) return 0;
+ ptr=out;*ptr++='{';
+ if (fmt) {*ptr++='\n';for (i=0;i<depth-1;i++) *ptr++='\t';}
+ *ptr++='}';*ptr++=0;
+ return out;
+ }
+ /* Allocate space for the names and the objects */
+ entries=(char**)cJSON_malloc(numentries*sizeof(char*));
+ if (!entries) return 0;
+ names=(char**)cJSON_malloc(numentries*sizeof(char*));
+ if (!names) {cJSON_free(entries);return 0;}
+ memset(entries,0,sizeof(char*)*numentries);
+ memset(names,0,sizeof(char*)*numentries);
+
+ /* Collect all the results into our arrays: */
+ child=item->child;depth++;if (fmt) len+=depth;
+ while (child)
+ {
+ names[i]=str=print_string_ptr(child->string);
+ entries[i++]=ret=print_value(child,depth,fmt);
+ if (str && ret) len+=strlen(ret)+strlen(str)+2+(fmt?2+depth:0); else fail=1;
+ child=child->next;
+ }
+
+ /* Try to allocate the output string */
+ if (!fail) out=(char*)cJSON_malloc(len);
+ if (!out) fail=1;
+
+ /* Handle failure */
+ if (fail)
+ {
+ for (i=0;i<numentries;i++) {if (names[i]) cJSON_free(names[i]);if (entries[i]) cJSON_free(entries[i]);}
+ cJSON_free(names);cJSON_free(entries);
+ return 0;
+ }
+
+ /* Compose the output: */
+ *out='{';ptr=out+1;if (fmt)*ptr++='\n';*ptr=0;
+ for (i=0;i<numentries;i++)
+ {
+ if (fmt) for (j=0;j<depth;j++) *ptr++='\t';
+ strcpy(ptr,names[i]);ptr+=strlen(names[i]);
+ *ptr++=':';if (fmt) *ptr++='\t';
+ strcpy(ptr,entries[i]);ptr+=strlen(entries[i]);
+ if (i!=numentries-1) *ptr++=',';
+ if (fmt) *ptr++='\n';*ptr=0;
+ cJSON_free(names[i]);cJSON_free(entries[i]);
+ }
+
+ cJSON_free(names);cJSON_free(entries);
+ if (fmt) for (i=0;i<depth-1;i++) *ptr++='\t';
+ *ptr++='}';*ptr++=0;
+ return out;
+}
+
+/* Get Array size/item / object item. */
+int cJSON_GetArraySize(cJSON *array) {cJSON *c=array->child;int i=0;while(c)i++,c=c->next;return i;}
+cJSON *cJSON_GetArrayItem(cJSON *array,int item) {cJSON *c=array->child; while (c && item>0) item--,c=c->next; return c;}
+cJSON *cJSON_GetObjectItem(cJSON *object,const char *string) {cJSON *c=object->child; while (c && cJSON_strcasecmp(c->string,string)) c=c->next; return c;}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev,cJSON *item) {prev->next=item;item->prev=prev;}
+/* Utility for handling references. */
+static cJSON *create_reference(cJSON *item) {cJSON *ref=cJSON_New_Item();if (!ref) return 0;memcpy(ref,item,sizeof(cJSON));ref->string=0;ref->type|=cJSON_IsReference;ref->next=ref->prev=0;return ref;}
+
+/* Add item to array/object. */
+void cJSON_AddItemToArray(cJSON *array, cJSON *item) {cJSON *c=array->child;if (!item) return; if (!c) {array->child=item;} else {while (c && c->next) c=c->next; suffix_object(c,item);}}
+void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item) {if (!item) return; if (item->string) cJSON_free(item->string);item->string=cJSON_strdup(string);cJSON_AddItemToArray(object,item);}
+void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item) {cJSON_AddItemToArray(array,create_reference(item));}
+void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item) {cJSON_AddItemToObject(object,string,create_reference(item));}
+
+cJSON *cJSON_DetachItemFromArray(cJSON *array,int which) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return 0;
+ if (c->prev) c->prev->next=c->next;if (c->next) c->next->prev=c->prev;if (c==array->child) array->child=c->next;c->prev=c->next=0;return c;}
+void cJSON_DeleteItemFromArray(cJSON *array,int which) {cJSON_Delete(cJSON_DetachItemFromArray(array,which));}
+cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string) {int i=0;cJSON *c=object->child;while (c && cJSON_strcasecmp(c->string,string)) i++,c=c->next;if (c) return cJSON_DetachItemFromArray(object,i);return 0;}
+void cJSON_DeleteItemFromObject(cJSON *object,const char *string) {cJSON_Delete(cJSON_DetachItemFromObject(object,string));}
+
+/* Replace array/object items with new ones. */
+void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem) {cJSON *c=array->child;while (c && which>0) c=c->next,which--;if (!c) return;
+ newitem->next=c->next;newitem->prev=c->prev;if (newitem->next) newitem->next->prev=newitem;
+ if (c==array->child) array->child=newitem; else newitem->prev->next=newitem;c->next=c->prev=0;cJSON_Delete(c);}
+void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem){int i=0;cJSON *c=object->child;while(c && cJSON_strcasecmp(c->string,string))i++,c=c->next;if(c){newitem->string=cJSON_strdup(string);cJSON_ReplaceItemInArray(object,i,newitem);}}
+
+/* Create basic types: */
+cJSON *cJSON_CreateNull(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_NULL;return item;}
+cJSON *cJSON_CreateTrue(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_True;return item;}
+cJSON *cJSON_CreateFalse(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_False;return item;}
+cJSON *cJSON_CreateBool(int b) {cJSON *item=cJSON_New_Item();if(item)item->type=b?cJSON_True:cJSON_False;return item;}
+cJSON *cJSON_CreateNumber(double num) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_Number;item->valuedouble=num;item->valueint=(int)num;}return item;}
+cJSON *cJSON_CreateString(const char *string) {cJSON *item=cJSON_New_Item();if(item){item->type=cJSON_String;item->valuestring=cJSON_strdup(string);}return item;}
+cJSON *cJSON_CreateArray(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Array;return item;}
+cJSON *cJSON_CreateObject(void) {cJSON *item=cJSON_New_Item();if(item)item->type=cJSON_Object;return item;}
+
+/* Create Arrays: */
+cJSON *cJSON_CreateIntArray(const int *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+cJSON *cJSON_CreateFloatArray(const float *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+cJSON *cJSON_CreateDoubleArray(const double *numbers,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateNumber(numbers[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+cJSON *cJSON_CreateStringArray(const char **strings,int count) {int i;cJSON *n=0,*p=0,*a=cJSON_CreateArray();for(i=0;a && i<count;i++){n=cJSON_CreateString(strings[i]);if(!i)a->child=n;else suffix_object(p,n);p=n;}return a;}
+
+/* Duplication */
+cJSON *cJSON_Duplicate(cJSON *item,int recurse)
+{
+ cJSON *newitem,*cptr,*nptr=0,*newchild;
+ /* Bail on bad ptr */
+ if (!item) return 0;
+ /* Create new item */
+ newitem=cJSON_New_Item();
+ if (!newitem) return 0;
+ /* Copy over all vars */
+ newitem->type=item->type&(~cJSON_IsReference),newitem->valueint=item->valueint,newitem->valuedouble=item->valuedouble;
+ if (item->valuestring) {newitem->valuestring=cJSON_strdup(item->valuestring); if (!newitem->valuestring) {cJSON_Delete(newitem);return 0;}}
+ if (item->string) {newitem->string=cJSON_strdup(item->string); if (!newitem->string) {cJSON_Delete(newitem);return 0;}}
+ /* If non-recursive, then we're done! */
+ if (!recurse) return newitem;
+ /* Walk the ->next chain for the child. */
+ cptr=item->child;
+ while (cptr)
+ {
+ newchild=cJSON_Duplicate(cptr,1); /* Duplicate (with recurse) each item in the ->next chain */
+ if (!newchild) {cJSON_Delete(newitem);return 0;}
+ if (nptr) {nptr->next=newchild,newchild->prev=nptr;nptr=newchild;} /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+ else {newitem->child=newchild;nptr=newchild;} /* Set newitem->child and move to it */
+ cptr=cptr->next;
+ }
+ return newitem;
+}
+
+void cJSON_Minify(char *json)
+{
+ char *into=json;
+ while (*json)
+ {
+ if (*json==' ') json++;
+ else if (*json=='\t') json++; // Whitespace characters.
+ else if (*json=='\r') json++;
+ else if (*json=='\n') json++;
+ else if (*json=='/' && json[1]=='/') while (*json && *json!='\n') json++; // double-slash comments, to end of line.
+ else if (*json=='/' && json[1]=='*') {while (*json && !(*json=='*' && json[1]=='/')) json++;json+=2;} // multiline comments.
+ else if (*json=='\"'){*into++=*json++;while (*json && *json!='\"'){if (*json=='\\') *into++=*json++;*into++=*json++;}*into++=*json++;} // string literals, which are \" sensitive.
+ else *into++=*json++; // All other characters.
+ }
+ *into=0; // and null-terminate.
+}
\ No newline at end of file
--- /dev/null
+/*
+ Copyright (c) 2009 Dave Gamble
+
+ 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 cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/* cJSON Types: */
+#define cJSON_False 0
+#define cJSON_True 1
+#define cJSON_NULL 2
+#define cJSON_Number 3
+#define cJSON_String 4
+#define cJSON_Array 5
+#define cJSON_Object 6
+
+#define cJSON_IsReference 256
+
+/* The cJSON structure: */
+typedef struct cJSON {
+ struct cJSON *next,*prev; /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+ struct cJSON *child; /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+
+ int type; /* The type of the item, as above. */
+
+ char *valuestring; /* The item's string, if type==cJSON_String */
+ int valueint; /* The item's number, if type==cJSON_Number */
+ double valuedouble; /* The item's number, if type==cJSON_Number */
+
+ char *string; /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+} cJSON;
+
+typedef struct cJSON_Hooks {
+ void *(*malloc_fn)(size_t sz);
+ void (*free_fn)(void *ptr);
+} cJSON_Hooks;
+
+/* Supply malloc, realloc and free functions to cJSON */
+extern void cJSON_InitHooks(cJSON_Hooks* hooks);
+
+
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. Call cJSON_Delete when finished. */
+extern cJSON *cJSON_Parse(const char *value);
+/* Render a cJSON entity to text for transfer/storage. Free the char* when finished. */
+extern char *cJSON_Print(cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting. Free the char* when finished. */
+extern char *cJSON_PrintUnformatted(cJSON *item);
+/* Delete a cJSON entity and all subentities. */
+extern void cJSON_Delete(cJSON *c);
+
+/* Returns the number of items in an array (or object). */
+extern int cJSON_GetArraySize(cJSON *array);
+/* Retrieve item number "item" from array "array". Returns NULL if unsuccessful. */
+extern cJSON *cJSON_GetArrayItem(cJSON *array,int item);
+/* Get item "string" from object. Case insensitive. */
+extern cJSON *cJSON_GetObjectItem(cJSON *object,const char *string);
+
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+extern const char *cJSON_GetErrorPtr(void);
+
+/* These calls create a cJSON item of the appropriate type. */
+extern cJSON *cJSON_CreateNull(void);
+extern cJSON *cJSON_CreateTrue(void);
+extern cJSON *cJSON_CreateFalse(void);
+extern cJSON *cJSON_CreateBool(int b);
+extern cJSON *cJSON_CreateNumber(double num);
+extern cJSON *cJSON_CreateString(const char *string);
+extern cJSON *cJSON_CreateArray(void);
+extern cJSON *cJSON_CreateObject(void);
+
+/* These utilities create an Array of count items. */
+extern cJSON *cJSON_CreateIntArray(const int *numbers,int count);
+extern cJSON *cJSON_CreateFloatArray(const float *numbers,int count);
+extern cJSON *cJSON_CreateDoubleArray(const double *numbers,int count);
+extern cJSON *cJSON_CreateStringArray(const char **strings,int count);
+
+/* Append item to the specified array/object. */
+extern void cJSON_AddItemToArray(cJSON *array, cJSON *item);
+extern void cJSON_AddItemToObject(cJSON *object,const char *string,cJSON *item);
+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+extern void cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+extern void cJSON_AddItemReferenceToObject(cJSON *object,const char *string,cJSON *item);
+
+/* Remove/Detatch items from Arrays/Objects. */
+extern cJSON *cJSON_DetachItemFromArray(cJSON *array,int which);
+extern void cJSON_DeleteItemFromArray(cJSON *array,int which);
+extern cJSON *cJSON_DetachItemFromObject(cJSON *object,const char *string);
+extern void cJSON_DeleteItemFromObject(cJSON *object,const char *string);
+
+/* Update array items. */
+extern void cJSON_ReplaceItemInArray(cJSON *array,int which,cJSON *newitem);
+extern void cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+
+/* Duplicate a cJSON item */
+extern cJSON *cJSON_Duplicate(cJSON *item,int recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+need to be released. With recurse!=0, it will duplicate any children connected to the item.
+The item->next and ->prev pointers are always zero on return from Duplicate. */
+
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+extern cJSON *cJSON_ParseWithOpts(const char *value,const char **return_parse_end,int require_null_terminated);
+
+extern void cJSON_Minify(char *json);
+
+/* Macros for creating things quickly. */
+#define cJSON_AddNullToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateNull())
+#define cJSON_AddTrueToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateTrue())
+#define cJSON_AddFalseToObject(object,name) cJSON_AddItemToObject(object, name, cJSON_CreateFalse())
+#define cJSON_AddBoolToObject(object,name,b) cJSON_AddItemToObject(object, name, cJSON_CreateBool(b))
+#define cJSON_AddNumberToObject(object,name,n) cJSON_AddItemToObject(object, name, cJSON_CreateNumber(n))
+#define cJSON_AddStringToObject(object,name,s) cJSON_AddItemToObject(object, name, cJSON_CreateString(s))
+
+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object,val) ((object)?(object)->valueint=(object)->valuedouble=(val):(val))
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+
+CXX=g++
+#CXX=clang -lstdc++ -g
+
+CXX_FLAGS=-std=c++11 -Wall -pthread
+
+CXX_INC=-I../include/ -I./client/ -I../csdk/stack/include -I../csdk/ocsocket/include -I../csdk/ocrandom/include -I../csdk/logger/include
+
+LIB_SRC0=../OCLib/OCReflect.cpp ../OCLib/OCProperties.cpp ../OCLib/OCObserver.cpp ../OCLib/OCResource.cpp ./client/MyObserverHandler.cpp
+LIB_SRC1=../OCLib/OCReflect.cpp ../OCLib/OCObserver.cpp ./client/MyObserverHandler.cpp ../OCLib/OCResource.cpp ../OCLib/OCSecurityModel.cpp ../OCLib/InProcClientWrapper.cpp ../OCLib/OCPlatform.cpp ../OCLib/InProcServerWrapper.cpp ../csdk/liboctbstack.a
+
+all: ocreflect resources
+
+ocreflect: test_properties test_OCClient
+
+test_properties:
+ $(CXX) $(CXX_FLAGS) -o test_properties test_properties.cpp $(LIB_SRC0) $(CXX_INC)
+
+test_OCReflect:
+ $(CXX) $(CXX_FLAGS) -o test_OCReflect test_OCReflect.cpp ../OCLib/OCReflect.cpp ../OCLib/OCProperties.cpp $(CXX_INC)
+
+test_OCClient:
+ $(CXX) $(CXX_FLAGS) -o test_OCClient test_OCClient.cpp $(LIB_SRC0) $(CXX_INC)
+
+resources: single_resource multiple_resources
+
+single_resource:
+ $(CXX) $(CXX_FLAGS) -o single_resource ./server/single_resource.cpp $(LIB_SRC1) $(CXX_INC)
+
+multiple_resources:
+ #$(CXX) $(CXX_FLAGS) -o multiple_resources ./server/multiple_resources.cpp $(LIB_SRC1) $(CXX_INC)
+
+clean:
+ rm -f -v test_properties test_OCReflect test_OCClient single_resource multiple_resources
+
--- /dev/null
+CXX=g++
+CXX_FLAGS=-std=c++11 -Wall -pthread
+
+final: server client serverApp
+
+serverApp: InProcServerWrapper.o testServerApp.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o OCPlatform.o
+ $(CXX) $(CXX_FLAGS) -o serverApp InProcServerWrapper.o testServerApp.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o OCPlatform.o
+
+server: InProcServerWrapper.o testServer.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o
+ $(CXX) $(CXX_FLAGS) -o server InProcServerWrapper.o testServer.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o
+
+client: InProcServerWrapper.o testClient.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o
+ $(CXX) $(CXX_FLAGS) -o client InProcServerWrapper.o testClient.o ocstack_stub.o OCResource.o InProcClientWrapper.o OCReflect.o
+
+OCReflect.o: ../../../OCLib/OCReflect.cpp
+ $(CXX) $(CXX_FLAGS) -c ../../../OCLib/OCReflect.cpp -I../../../csdk/ -I../../../include -I../
+
+OCPlatform.o: ../../../OCLib/OCPlatform.cpp
+ $(CXX) $(CXX_FLAGS) -c ../../../OCLib/OCPlatform.cpp -I../../../csdk/ -I../../../include/ -I../ -I../client/ -I../server/
+
+OCResource.o: ../../../OCLib/OCResource.cpp
+ $(CXX) $(CXX_FLAGS) -c ../../../OCLib/OCResource.cpp -I../../../csdk/ -I../../../include/ -I../ -I../client/ -I../server/
+
+ocstack_stub.o : ../../../csdk/ocstack_stub.c
+ gcc -c ../../../csdk/ocstack_stub.c -I../../../csdk/
+
+InProcServerWrapper.o: ../server/InProcServerWrapper.cpp
+ $(CXX) $(CXX_FLAGS) -c ../server/InProcServerWrapper.cpp -I../../../csdk/ -I../../../include -I../
+
+InProcClientWrapper.o: ../client/InProcClientWrapper.cpp
+ $(CXX) $(CXX_FLAGS) -c ../client/InProcClientWrapper.cpp -I../../../csdk/ -I../../../include -I../
+
+testServer.o : testServer.cpp
+ $(CXX) $(CXX_FLAGS) -c testServer.cpp -I../../../csdk/ -I../../../include -I../ -I../client/ -I../server/
+
+testServerApp.o : testServerApp.cpp
+ $(CXX) $(CXX_FLAGS) -c testServerApp.cpp -I../../../csdk/ -I../../../include -I../ -I../client/ -I../server/
+
+testClient.o : testClient.cpp
+ $(CXX) $(CXX_FLAGS) -c testClient.cpp -I../../../csdk/ -I../../../include -I../ -I../client/ -I../server/
+
+clean:
+ rm *.o server client serverApp
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <iostream>
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/json_parser.hpp>
+
+using namespace std;
+using namespace boost::property_tree;
+
+void parseResource(ptree resource)
+{
+ cout<<"\t\tParsing Resource with "<< resource.size() <<" facts:"<<endl;
+ cout << "\t\tAddress is "<< resource.get<std::string>("href", "") <<endl;
+ cout << "\t\tIs Observable? : "<< (resource.get<int>("obs",0)==1)<<endl;
+
+ // types:
+ cout << "\t\tResource Type Count : "<<resource.get_child("rt", ptree()).size()<<endl;
+ for(auto resourceItr : resource.get_child("rt", ptree()))
+ {
+ cout << "\t\t\tResource Type: "<< resourceItr.second.data()<<endl;
+ }
+
+ // interfaces:
+ cout << "\t\tInterface Count : "<<resource.get_child("if", ptree()).size()<<endl;
+ for(auto resourceItr : resource.get_child("if", ptree()))
+ {
+ cout << "\t\t\tInterface: "<< resourceItr.second.data()<<endl;
+ }
+
+ cout<<endl;
+}
+
+void parseTest(const char* data)
+{
+
+ std::stringstream requestStream;
+ requestStream << data;
+
+ ptree root;
+ boost::property_tree::read_json(requestStream, root);
+
+ ptree payload = root.get_child("oc.payload", ptree());
+ cout << "\tResource Count:" << payload.size()<<endl;
+
+ for(auto itr : payload)
+ {
+ parseResource(itr.second);
+ }
+
+// cout << "PTree Size: " << requestTree.size() << " DATA: "<<requestTree.get_value<string>() <<endl;
+ //cout << "\t Child:"<<requestTree.front().first.data()<<" " << requestTree.front().second.data()<<endl;
+}
+
+
+int main()
+{
+ const char* data1 = "{\"oc\": {\
+ \"payload\": [{\
+ \"href\":\"/a/tube\",\
+ \"rt\":[\"alpha.act.tb\"],\
+ \"if\":[\"oc.mi.a\"]\
+ },\
+ {\
+ \"href\":\"/b/tube\",\
+ \"rt\":[\"alpha.act.tb\"],\
+ \"if\":[\"oc.mi.a\"],\
+ \"obs\" : 1\
+ }\
+ ]\
+ }\
+}";
+
+ const char* data2 = "{\"oc\": {\
+ \"payload\": [{\
+ \"href\":\"/temp-sensor\",\
+ \"rt\":[\"beta.sensor.temp\"],\
+ \"if\":[\"oc.mi.s\"],\
+ \"obs\" : 1\
+ }\
+ ]\
+ }\
+} ";
+
+ const char* data3 = "{\"oc\": {\
+ \"payload\": [{\
+ \"href\":\"/room-lights\",\
+ \"rt\":[\"gamma.lights\"],\
+ \"if\":[\"oc.mi.ll\", \"oc.mi.b\"]\
+ }\
+ ]\
+ }\
+} ";
+
+ cout<<"Data1:\n";
+ parseTest(data1);
+ cout<<"Data2:\n";
+ parseTest(data2);
+ cout<<"Data3:\n";
+ parseTest(data3);
+
+ return 0;
+}
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <WrapperFactory.h>
+#include <OCApi.h>
+#include <IServerWrapper.h>
+#include <IClientWrapper.h>
+
+using namespace OC;
+
+void testClient()
+{
+ PlatformConfig cfg;
+ cfg.ipAddress = "192.168.1.5";
+ cfg.port = 8080;
+ cfg.mode = ModeType::Client;
+ cfg.serviceType = ServiceType::InProc;
+
+ IWrapperFactory::Ptr pFactory = std::make_shared<WrapperFactory>();
+ IClientWrapper::Ptr pWrapper = pFactory->CreateClientWrapper(cfg);
+}
+
+int main()
+{
+ testClient();
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <WrapperFactory.h>
+#include <OCApi.h>
+#include <IServerWrapper.h>
+#include <IClientWrapper.h>
+#include <OCReflect.h>
+
+#include <algorithm>
+#include <cstring>
+#include <cstdlib>
+
+using namespace OC;
+using namespace OC::OCReflect;
+
+// Demo of how to generate OCStack stuff:
+void rep_test()
+{
+ using OC::OCReflect::property_type;
+ using OC::OCReflect::named_property_binding;
+
+ named_property_binding_vector sigs {
+ named_property_binding("state", property_type::boolean),
+ named_property_binding("power", property_type::integer),
+ };
+
+ using namespace OC::OCReflect::to_OCStack;
+
+ std::vector<std::string> reps { convert(sigs) };
+
+ for(const auto& r : reps)
+ std::cout << r << '\n';
+
+ char **LEDrep = convert(reps);
+
+ std::for_each(LEDrep, LEDrep + length(LEDrep), [](const char *s) { std::cout << s << '\n'; });
+
+
+
+
+ OCEntityHandler entityHandler;
+ OCResourceHandle resourceHandle;
+
+ OCCreateResource( &resourceHandle, // OCResourceHandle *handl
+ "core.led", // const char * resourceTypeName
+ "state:oc.bt.b;power:oc.bt.i", //const char * resourceTypeRepresentation
+ "core.rw", //const char * resourceInterfaceName
+ OC_REST_GET | OC_REST_PUT, // uint8_t allowedMethods
+ "/a/led", // const char * uri
+ entityHandler, // OCEntityHandler entityHandler
+ OC_DISCOVERABLE | OC_OBSERVABLE // uint8_t resourceProperties
+ );
+
+
+
+ release(LEDrep);
+}
+
+void testServer()
+{
+ PlatformConfig cfg;
+ cfg.ipAddress = "192.168.1.5";
+ cfg.port = 8080;
+ cfg.mode = ModeType::Server;
+ cfg.serviceType = ServiceType::InProc;
+
+ IWrapperFactory::Ptr pFactory= std::make_shared<WrapperFactory>();
+
+ IServerWrapper::Ptr pServer = pFactory->CreateServerWrapper(cfg);
+
+ //pServer->bindTo
+}
+
+int main()
+{
+ rep_test();
+ testServer();
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+///
+/// This sample provides steps to define an interface for a resource
+/// (properties and methods) and host this resource on the server.
+///
+
+#include <functional>
+
+#include <OCServer.h>
+#include <OCReflect.h>
+#include <OCPlatform.h>
+#include <OCApi.h>
+#include <iostream>
+
+using namespace std;
+
+using namespace OC;
+using namespace OC::OCReflect;
+
+/// This class represents a single resource named 'light'. This resource has
+/// two simple properties named 'state' and 'power' and they have respective setter
+/// and getter methods.
+
+class light
+{
+private:
+ /// Access this property from a TB client
+ bool m_state;
+ int m_power;
+
+public:
+ light()
+ : m_power(0),
+ m_state(false)
+ {}
+
+public:
+ /// Setter method for the setting the power of this light resource
+ void setPower(int powerValue)
+ {
+ m_power = powerValue;
+ }
+
+ /// Getter method for the getting the power of this light resource
+ int getPower() const
+ {
+ return m_power;
+ }
+
+ /// Setter method for the setting the state of this light resource
+ void setState(bool state)
+ {
+ m_state = state;
+ }
+
+ /// Getter method for the getting the state of this light resource
+ bool getState() const
+ {
+ return m_state;
+ }
+
+public:
+ /* Note that this does not need to be a member function: for classes you do not have
+ access to, you can accomplish this with a free function: */
+
+ /// This function binds the properties and methods to the server.
+ void bindTo(OC::OCPlatform& platform)
+ {
+ using OC::OCReflect::property_type;
+ using OC::OCReflect::named_property_binding;
+
+ named_property_binding_vector properties {
+ named_property_binding("state", property_type::boolean),
+ named_property_binding("power", property_type::integer)
+ };
+
+ std::string resourceURI = "/a/light";
+ std::string resourceTypeName = "light";
+ platform.registerResource(resourceURI, resourceTypeName, properties);
+ }
+};
+
+int main()
+{
+ // Step1: Create a OCPlatform instance.
+ // Step1.1: The constructor of OCPlatform class takes PlatformConfig object.
+ // Note: Platform creation is synchronous call.
+
+ PlatformConfig cfg;
+ cfg.ipAddress = "192.168.1.5";
+ cfg.port = 8080;
+ cfg.mode = ModeType::Server;
+ cfg.serviceType = ServiceType::InProc;
+
+ cout << "Creating OCPlatform .. \n";
+
+ OCPlatform platform(cfg);
+
+ // Step2: Create the instance of the resource class (in this case instance of class 'light').
+ // Step2.1: Invoke bindTo function of class light.
+
+ light myLight;
+ myLight.bindTo(platform);
+
+ while(true)
+ {
+ //some tasks
+ }
+
+ // No explicit call to stop the platform.
+ // When OCPlatform destructor is invoked, internally we do platform cleanup
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include <iostream>
+
+#include "ocapi.h"
+#include "OCReflect.h"
+#include "OCObserver.h"
+#include "OCException.h"
+#include "MyMultiResourceHandler.h"
+
+namespace {
+
+void log(const std::string& msg)
+{
+ std::cerr << msg << '\n';
+}
+
+} // namespace
+
+void OC::MyMultiResourceHandler::onFoundResource(OCResourceResult *update, void *params){
+
+ //Step1: Find a specific resource that also contains OCReflect byte stream of methods and properties
+ for( auto &resource : update->resources )
+ {
+ if(resource.getURI() == "/garage/dimmer/a")
+ {
+ performDimmerOperations(resource, update);
+ }
+ else if(resource.getURI() == "/garage/door/a")
+ {
+ performDoorOperations(resource, update);
+ }
+ }
+}
+
+void OC::MyMultiResourceHandler::performDimmerOperations(OC::OCResource myResource, OC::OCResourceResult *update)
+{
+ using OC::OCReflect::entity;
+ using OC::OCReflect::method;
+ using OC::OCReflect::remote_resource;
+
+ using OC::bind_observer;
+ using OC::unbind_observer;
+
+ try
+ {
+ // Perform resource operation
+ // Note that this resource dimmer has
+ // 'manufacturer' as a property
+ // 'powerState' as a observable property
+ // 'setPowered' as a method
+ // 'getPowered' as a method
+
+ //Step1: Find a specific method and invoke it. or Find a specific property and use it.
+
+ // Canonical one-step approach to get a callable function object:
+ // OCReflect::method throw OC::OCReflect::reflect_exception if there is no setLevel method in the myResource
+ auto setPowered = OCReflect::method(myResource, "setPowered");
+
+ // invoke the remote method,
+ // invalid arguments return as an OC::OCReflect::reflect_exception
+ setPowered(true);
+
+ // Canonical one-step approach to get a callable function object:
+ // OCReflect::method throw OC::OCReflect::reflect_exception if there is no setLevel method in the myResource
+ auto getPowered = OCReflect::method(myResource, "getPowered");
+
+ // invoke the remote method,
+ // invalid arguments return as an OC::OCReflect::reflect_exception
+ // bool power = getPowered(); // Use power variable to do other operations
+
+ // Canonical one-step approach to access a property:
+ std::string manufacturer = update->property<std::string>("manufacturer");
+
+ //Example to observe a property
+ bind_observer(&myObserverHandler, myResource, "powerState");
+
+ //Example to unobserve a property
+ unbind_observer(&myObserverHandler, myResource, "powerState");
+ }
+ catch(OC::OCReflect::reflection_exception& e)
+ {
+ log(e.what());
+ }
+ catch(std::exception& e)
+ {
+ log(e.what());
+ }
+}
+
+void OC::MyMultiResourceHandler::performDoorOperations(OC::OCResource myResource, OC::OCResourceResult *update)
+{
+ // Perform resource operation
+ // Note that this resource door has
+ // 'manufacturer' as a property
+ // 'setLockState' as a method
+ // 'getLockState' as a method
+
+ try
+ {
+ // Step1: Find a specific method and invoke it or find a specific property and use it.
+
+ // Canonical one-step approach to get a callable function object:
+ // OCReflect::method throw OC::OCReflect::reflect_exception if there is no setLevel method in the myResource
+ auto setLockState = OCReflect::method(myResource, "setLockState");
+
+ // invoke the remote method,
+ // invalid arguments return as an OC::OCReflect::reflect_exception
+ setLockState(true);
+
+ // Canonical one-step approach to get a callable function object:
+ // OCReflect::method throw OC::OCReflect::reflect_exception if there is no setLevel method in the myResource
+ auto getLockState = OCReflect::method(myResource, "getLockState");
+
+ // invoke the remote method,
+ // invalid arguments return as an OC::OCReflect::reflect_exception
+ // bool lockState = getLockState(); // use lockState variable for any other operations
+
+ // Canonical one-step approach to access a property
+ std::string manufacturer = update->property<std::string>("manufacturer");
+ }
+ catch(OC::OCReflect::reflection_exception& e)
+ {
+ log(e.what());
+ }
+ catch(std::exception& e)
+ {
+ log(e.what());
+ }
+}
+
+void OC::MyMultiResourceHandler::MyMultiResourceHandler::onCompleted()
+{
+
+}
+
+void OC::MyMultiResourceHandler::MyMultiResourceHandler::onFailed()
+{
+
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "ocapi.h"
+#include "OCResourceHandler.h"
+#include "MyObserverHandler.h"
+
+namespace OC {
+
+class MyMultiResourceHandler :
+ public OCResourceHandler
+{
+public:
+ void onFoundResource(OCResourceResult *update, void *params);
+ void onCompleted();
+ void onFailed();
+
+private:
+ MyObserverHandler myObserverHandler;
+
+ /// This is a private function to perform operations related to dimmer resource
+ void performDimmerOperations(OCResource myResource, OCResourceResult *update);
+
+ /// This is a private function to perform operations related to door resource
+ void performDoorOperations(OCResource myResource, OCResourceResult *update);
+};
+
+} // namespace OC
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "MyObserverHandler.h"
+
+void OC::MyObserverHandler::onObserverUpdate(std::string propertyName, void *value)
+{
+
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "OCApi.h"
+#include "OCObserverHandler.h"
+
+namespace OC {
+
+class MyObserverHandler :
+ public OC::OCObserverHandler
+{
+public:
+ void onObserverUpdate(std::string propertyName, void *value);
+};
+
+} // namespace OC
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <iostream>
+
+#include "ocapi.h"
+#include "OCReflect.h"
+#include "OCObserver.h"
+#include "OCException.h"
+#include "MyResourceHandler.h"
+
+void log(const std::string& msg)
+{
+ std::cerr << msg << '\n';
+}
+
+MyResourceHandler::MyResourceHandler(void)
+{
+}
+
+
+MyResourceHandler::~MyResourceHandler(void)
+{
+}
+
+void MyResourceHandler::onFoundResource(OCResourceResult *update, void *params){
+ using OC::OCReflect::entity;
+ using OC::OCReflect::method;
+ using OC::OCReflect::remote_resource;
+
+ using OC::bind_observer;
+ using OC::unbind_observer;
+
+ try
+ {
+ //Step1: Find a specific resource that also contains OCReflect byte stream of methods and properties
+ OCResource myResource;
+ for ( auto &resource : update->resources ) {
+ if(resource.getURI() == "/light/a"){
+ myResource = resource;
+ break;
+ }
+ }
+
+ //Step2: Find a specific method and invoke it. or Find a specific property and use it.
+
+ // Canonical one-step approach to get a callable function object:
+ // OCReflect::method throw OC::OCReflect::reflect_exception if there is no setLevel method in the myResource
+ auto setLevel = OC::OCReflect::method(myResource, "setLevel");
+
+ setLevel(75, 255);
+
+ // Individual steps-- each may throw on failure:
+ remote_resource myLight(myResource, "lights/a"); // JFW: this may be subsumed by type OCResource
+
+ entity e_setPowered = myLight("setPowered");
+
+ method setPowered = OC::OCReflect::narrow<OCReflect::method>(e_setPowered);
+
+ setPowered(true);
+
+ // Canonical one-step approach to access a property:
+ std::string manufacturer = update->property<std::string>("manufacturer");
+
+ // Individual steps:
+ entity e_manufacturer = myResource.property("manufacturer");
+ std::string manufacturer_2 = OC::OCReflect::narrow<std::string>(e_manufacturer);
+
+ //Example to observe a property
+ bind_observer(&myObserverHandler, myResource, "PowerState");
+
+ //Example to unobserve a property
+ unbind_observer(&myObserverHandler, myResource, "PowerState");
+ }
+ catch(OC::OCReflect::reflection_exception& e)
+ {
+ log(e.what());
+ }
+ catch(std::exception& e)
+ {
+ log(e.what());
+ }
+}
+
+void MyResourceHandler::onCompleted(){
+}
+
+void MyResourceHandler::onFailed(){
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#include "ocapi.h"
+#include "OCResourceHandler.h"
+#include "MyObserverHandler.h"
+
+using namespace OC;
+
+class MyResourceHandler :
+ public OCResourceHandler
+{
+public:
+ MyResourceHandler(void);
+ virtual ~MyResourceHandler(void);
+ void onFoundResource(OCResourceResult *update, void *params);
+ void onCompleted();
+ void onFailed();
+
+private:
+ MyObserverHandler myObserverHandler;
+
+};
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+// OCClient.cpp : Defines the entry point for the console application.
+//
+#include <string>
+
+#include "OCPlatform.h"
+
+using namespace OC;
+
+void foundResource(std::shared_ptr<OCResource> resource){
+
+ try
+ {
+ // Do some operations with resource object.
+ if(resource)
+ {
+ std::cout << "URI of the resource: " << resource->uri() << std::endl;
+
+ std::cout << "Host address of the resource: " << resource->host() << std::endl;
+ }
+
+ else
+ {
+ std::cout << "Resource invalid" << std::endl;
+ }
+
+ }
+ catch(OC::OCReflect::reflection_exception& e)
+ {
+ //log(e.what());
+ }
+ catch(std::exception& e)
+ {
+ //log(e.what());
+ }
+}
+
+
+int main()
+{
+ // Create PlatformConfig object
+
+ PlatformConfig cfg;
+ cfg.ipAddress = "134.134.161.166";
+ cfg.port = 5683;
+ cfg.mode = ModeType::Client;
+ cfg.serviceType = ServiceType::InProc;
+
+ // Create a OCPlatform instance.
+ // Note: Platform creation is synchronous call.
+
+ try
+ {
+ OCPlatform platform(cfg);
+
+ // Find all resources
+ platform.findResource("", "coap://224.0.1.187/oc/core", &foundResource);
+
+ while(1)
+ {
+ }
+
+ }catch(OCException e)
+ {
+ //log(e.what());
+ }
+
+ return 0;
+}
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+///
+/// This sample provides steps to define an interface for multiple resources
+/// (properties and methods) and host these resources on the server.
+///
+#include <functional>
+
+#include "OCServer.h"
+#include "OCReflect.h"
+
+using namespace OC::OCReflect;
+
+class dimmer
+{
+private:
+ int m_level;
+ int m_color;
+
+public:
+ bool m_powered; // This is an observable property
+ std::string manufacturer; // This is a non-observable property
+
+public:
+ dimmer()
+ : m_level(0),
+ m_color(0),
+ m_powered(false),
+ manufacturer("Integrated Electronics")
+ {}
+
+public:
+ /// Setter method for the setting the power state of this dimmer resource
+ void setPowered(const bool newState)
+ {
+ m_powered = newState;
+ }
+
+ /// Getter method for the setting the power state of this dimmer resource
+ bool getPowered() const
+ {
+ return m_powered;
+ }
+
+ /// Setter method for the setting the intensity level of this dimmer resource
+ /// Along with above basic method, this method takes two arguments
+ /// with first argument as intensity level and second level as color.
+ void setLevel(const int newLevel, int color)
+ {
+ m_level = newLevel;
+ m_color = color;
+ }
+
+ /// Getter method for getting the intensity level of the dimmer resoruce
+ int getLevel() const
+ {
+ return m_level;
+ }
+
+ /// Note that this does not need to be a member function: for classes you do not have
+ /// access to, you can accomplish this with a free function:
+public:
+ void bindTo(OC::OCServer& server, const std::string& base_URI)
+ {
+ /*using OC::OCReflect::method_signature;
+ using OC::OCReflect::method_binding;
+ using OC::OCReflect::property_signature;
+ using OC::OCReflect::property_binding;
+ using OC::OCReflect::bind_service;
+ using OC::OCReflect::bind_property;
+
+ using OC::OCReflect::property_type;*/
+
+ // Register the URI with the server
+ server.registerResource(this, base_URI);
+
+ // Steps to map the property
+
+ // The canonical way to bind a property to a server in one step:
+ bind_property(
+ server, // server to bind to
+ this->manufacturer, // pointer to property
+ "manufacturer", // property binding name
+ OC::OCReflect::property_type::string, // property
+ OC::OCReflect::property_attribute::r // type decoration
+ );
+
+ // The canonical way to bind a property to a server in one step:
+ bind_property(
+ server, // server to bind to
+ this->m_powered, // pointer to property
+ "powerState", // property binding name
+ OC::OCReflect::property_type::boolean, // property
+ OC::OCReflect::property_attribute::r // type decoration
+ );
+
+ // Steps to map the methods
+
+ // Example to map getPowered method using the canonical way in one step:
+ bind_service(server, // server to bind to
+ this, // instance (ourself) to bind
+ &dimmer::getPowered, // address of the method to bind
+ "getPowered", // name to bind with service URL
+ property_type::boolean); // return type of the method
+
+ // Example to map setPowered method using the canonical way in one step:
+ bind_service(server, // server to bind to
+ this, // instance (ourself) to bind
+ &dimmer::setPowered, // address of the method to bind
+ "setPowered", // name to bind with service URL
+ property_type::nil, // return type of the method
+ property_type::boolean); // parameter type for setPowered method
+
+ // Example to map setLevel method using the canonical way in one step:
+ bind_service(
+ server, // server to bind with
+ this, // instance to bind
+ &dimmer::setLevel, // method to bind
+ "setLevel", // service name
+ property_type::nil, // input type
+ property_type::integer, // parameter list starts (parameter type for level)
+ property_type::integer); // parameter list (parameter type for color)
+
+ // Example to map getLevel method using the canonical way in one step:
+ bind_service(server, this, &dimmer::getLevel, "getLevel", property_type::integer);
+ }
+};
+
+class door
+{
+ bool m_locked;
+
+public:
+ std::string manufacturer;
+
+public:
+ door()
+ : m_locked(true),
+ manufacturer("Integrated Electronics")
+ {}
+
+public:
+ /// Setter method for the setting the lock state of this door resource
+ void setLockState(const bool lockState)
+ {
+ m_locked = lockState;
+ }
+
+ /// Getter method for the setting the lock state of this door resource
+ bool getLockState() const
+ {
+ return m_locked;
+ }
+
+ /* Note that this does not need to be a member function: for classes you do not have
+ access to, you can accomplish this with a free function: */
+public:
+ void bindTo(OC::OCServer& server, const std::string& base_URI)
+ {
+ /*using OC::OCReflect::method_signature;
+ using OC::OCReflect::method_binding;
+ using OC::OCReflect::property_signature;
+ using OC::OCReflect::property_binding;
+ using OC::OCReflect::bind_service;
+ using OC::OCReflect::bind_property;
+
+ using OC::OCReflect::property_type;*/
+
+ // Register the URI with the server
+ server.registerResource(this, base_URI);
+
+ // Steps to map the property
+
+ // The canonical way to bind a property to a server in one step:
+ bind_property(
+ server, // server to bind to
+ this->manufacturer, // pointer to property
+ "manufacturer", // property binding name
+ OC::OCReflect::property_type::string, // property
+ OC::OCReflect::property_attribute::r // type decoration
+ );
+
+ // Steps to map the methods
+
+ // Example to map getPowered method using the canonical way in one step:
+ bind_service(server, // server to bind to
+ this, // instance (ourself) to bind
+ &door::getLockState, // address of the method to bind
+ "getLockState", // name to bind with service URL
+ property_type::boolean); // return type of the method
+
+ // Example to map setPowered method using the canonical way in one step:
+ bind_service(server, // server to bind to
+ this, // instance (ourself) to bind
+ &door::setLockState, // address of the method to bind
+ "setLockState", // name to bind with service URL
+ property_type::nil, // return type of the method
+ property_type::boolean); // parameter type for setPowered method
+ }
+};
+
+class garage
+{
+private:
+ dimmer myDimmer;
+ door myDoor;
+
+public:
+ void bindTo(OC::OCServer& server, const std::string& base_URI)
+ {
+ // Register the URI with the server
+ server.registerResource(this, base_URI);
+
+ // Bind child resource 'dimmer' to the server
+ myDimmer.bindTo(server, base_URI + "/dimmer/a");
+
+ // Bind child resource 'door' to the server
+ myDoor.bindTo(server, base_URI + "/door/a");
+ }
+};
+
+int main()
+{
+ //Step1: create a server
+ OC::OCSecurityModel securityModel;
+ OC::OCServer server;
+ server.setSecurityModel(securityModel);
+
+ //Step2: Create a Garage resource
+ garage myGarage;
+
+ //Step3: Bind garage resource to the server
+ //Note: Garage resource has child resources -- dimmer and door.
+ myGarage.bindTo(server, "/garage/");
+
+ //Step4: Start the server
+ server.start();
+
+ while(true)
+ {
+ //do something here
+ }
+
+ //Step4: Stop the server
+ server.stop();
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+///
+/// This sample provides steps to define an interface for a resource
+/// (properties and methods) and host this resource on the server.
+///
+
+#include <functional>
+
+#include "OCReflect.h"
+#include "OCPlatform.h"
+#include "OCApi.h"
+
+using namespace OC;
+using namespace OC::OCReflect;
+
+/// This class represents a single resource named 'lightResource'. This resource has
+/// two simple properties named 'state' and 'power' and they have respective setter
+/// and getter methods.
+
+class LightResource
+{
+private:
+ /// Access this property from a TB client
+ bool m_state;
+ int m_power;
+
+public:
+ LightResource()
+ : m_state(false), m_power(0)
+ {}
+
+public:
+ /// Setter method for the setting the power of this light resource
+ void setPower(int powerValue)
+ {
+ m_power = powerValue;
+ }
+
+ /// Getter method for the getting the power of this light resource
+ int getPower() const
+ {
+ return m_power;
+ }
+
+ /// Setter method for the setting the state of this light resource
+ void setState(bool state)
+ {
+ m_state = state;
+ }
+
+ /// Getter method for the getting the state of this light resource
+ bool getState() const
+ {
+ return m_state;
+ }
+
+public:
+ /* Note that this does not need to be a member function: for classes you do not have
+ access to, you can accomplish this with a free function: */
+
+ /// This function binds the properties and methods to the server.
+ void createResourceWithPropeties(OC::OCPlatform& platform)
+ {
+ using OC::OCReflect::property_type;
+ using OC::OCReflect::named_property_binding;
+
+ named_property_binding_vector properties {
+ named_property_binding("state", property_type::boolean),
+ named_property_binding("power", property_type::integer)
+ };
+
+ std::string resourceURI = "/a/light";
+ std::string resourceTypeName = "light";
+
+ // This will internally invoke registerResource method (which would eventually create
+ // resource).
+
+ platform.registerResource(resourceURI, resourceTypeName, properties);
+ }
+};
+
+int main()
+{
+ // Create PlatformConfig object
+
+ PlatformConfig cfg;
+ //cfg.ipAddress = "192.168.1.5";
+ cfg.ipAddress = "134.134.161.166";
+ cfg.port = 5683;
+ cfg.mode = ModeType::Server;
+ cfg.serviceType = ServiceType::InProc;
+
+ // Create a OCPlatform instance.
+ // Note: Platform creation is synchronous call.
+ try
+ {
+ OCPlatform platform(cfg);
+
+ // Create the instance of the resource class (in this case instance of class 'LightResource').
+ // Invoke bindTo function of class light.
+
+ LightResource myLightResource;
+ myLightResource.createResourceWithPropeties(platform);
+
+ // Perform app tasks
+ while(true)
+ {
+ // some tasks
+ }
+ }
+ catch(OCException e)
+ {
+ //log(e.what());
+ }
+
+
+ // No explicit call to stop the platform.
+ // When OCPlatform destructor is invoked, internally we do platform cleanup
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <string>
+
+#include "OCPlatform.h"
+
+int main()
+{
+ //MyResourceHandler mrh;
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+
+#include <iostream>
+#include <functional>
+
+#include "OCServer.h"
+#include "OCReflect.h"
+#include "OCException.h"
+#include "OCProperties.h"
+
+namespace OC { namespace OCReflect {
+
+// JFW:
+/*
+template <class BoundF>
+struct call_through
+{
+ BoundF& f;
+
+ const property_type return_type;
+ const property_type_vector param_types;
+
+ call_through(BoundF& f_, const property_type& return_type_, const property_type_vector param_types_)
+ : f(f_), return_type(return_type_), param_types(param_types_)
+ {}
+
+ property operator()()
+ {
+ return make_property(f(), "return value"); // JFW: need a version of this for anonymous properties
+ }
+
+ template <class ...XS>
+ property operator()(const XS& ...params)
+ {
+ // switch(p0_type)
+ //return make_property(f(), "foo");
+
+ f(params...);
+
+// return make_property(f(params...), "fancy result name");
+
+ return make_property("Hello, World!", "fancy result name");
+ }
+};
+*/
+
+template <typename InstanceT, typename MethodT>
+OC::OCReflect::bound_function bind_function(InstanceT *self, MethodT const& method)
+{
+ return [self, method](const property_vector& args) -> property
+ {
+ auto b = std::bind(method, self);
+ return OC::OCReflect::make_property::apply(b(args), "_ret_");
+ };
+}
+
+template <typename InstanceT, typename MethodT, typename ...ParameterT>
+void bind_service(OC::OCServer& server, InstanceT *self, MethodT const& method, const std::string& binding_name, const property_type& return_type, const ParameterT& ...param_types)
+{
+ OC::OCReflect::bound_function f {
+ [method, self](const property_vector& args) -> property
+ {
+ // JFW: auto b = std::bind(method, self);
+
+/* JFW: eventually, map parameters in to e return OC::OCReflect::make_property::apply(b(args), "_ret_");
+ ...this is tricky, so we' punting on it for the Tuesday release. */
+
+ return OC::OCReflect::make_property::apply("hello from your friendly neighborhood lambda", "return value");
+ }
+ };
+
+ OC::OCReflect::method_binding fmb(binding_name, f,
+ return_type, property_type_vector { param_types... });
+
+ server.bind(fmb);
+
+/*
+ call_through<decltype(b)> ct(b, return_type, ptypes);
+
+ // then, at the call site...
+ auto r = ct(1); // call the function
+
+ std::function<property_type(ParameterT...)> f = ct;
+*/
+}
+
+template <typename PropertyT>
+void bind_property(OC::OCServer& server, PropertyT& property, const std::string& binding_name, const property_type& pt, const property_attribute& pas)
+{
+}
+
+}} // namespace OC::OCReflect
+
+class light
+{
+ bool m_powered;
+ int m_level;
+ int m_color;
+
+ public:
+ std::string manufacturer;
+
+ public:
+ light()
+ : m_powered(false),
+ m_level(0),
+ m_color(0),
+ manufacturer("Integrated Electronics")
+ {}
+
+ public:
+ void update_things() { std::cout << "light::update_things()\n"; }
+
+ void set_powered(const bool new_state) { m_powered = new_state; }
+ bool get_powered() const { return m_powered; }
+
+ void set_level(const int new_level, int color) { m_level = new_level; m_color = color; }
+ int get_level() const { return m_level; }
+
+ /* An example of server-side service binding. Note that this does not need to be a
+ member function: for classes you do not have access to, you can accomplish this with
+ a free function: */
+ public:
+ void bindTo(OC::OCServer& server, const std::string& base_URI)
+ {
+ using OC::OCReflect::method_signature;
+ using OC::OCReflect::method_binding;
+ using OC::OCReflect::property_signature;
+ using OC::OCReflect::property_binding;
+ using OC::OCReflect::bind_service;
+ using OC::OCReflect::bind_property;
+
+ using OC::OCReflect::property_type;
+
+ server.registerResource(this, base_URI);
+
+ // Bind a nullary method:
+ bind_service( server,
+ this,
+ &light::update_things,
+ "updateThings",
+ property_type::nil,
+ property_type::nil);
+
+ // Bind an unary method:
+ bind_service( server,
+ this, &light::set_powered,
+ "setPowered",
+ property_type::nil,
+ property_type::boolean);
+
+ // Example to map setLevel method using the canonical way in one step:
+ bind_service(
+ server, // server to bind with
+ this, // instance to bind
+ &light::set_level, // method to bind
+ "setLevel", // service name
+ property_type::nil, // input type
+ property_type::integer, // parameter list starts (level)
+ property_type::integer); // parameter list (color)
+
+
+ bind_service(server, this, &light::get_level, "getLevel",
+ property_type::integer);
+
+ bind_service(server, this, &light::get_powered, "isPowered",
+ property_type::boolean);
+
+ bind_service(server, this, &light::set_powered, "setPowered",
+ property_type::nil,
+ property_type::boolean);
+
+ // Map powered() as a service:
+ method_signature m_setPowered(
+ property_type::nil, // return type
+ property_type::boolean // parameter list (here, just arity 1)
+ );
+
+ // JFW: below is to say a wrapper for: std::bind(&light::set_powered, this); we'll need
+ // to pretty these up:
+ OC::OCReflect::bound_function f =
+ [](const OC::OCReflect::property_vector& args) -> OC::OCReflect::property
+ { return OC::OCReflect::make_property::apply(nullptr, "ret"); };
+
+ method_binding b_setPowered(
+ "setPowered", // name to bind with service URL
+ f, // function to bind to the service
+ m_setPowered); // method signature (metadata)
+
+ server.bind(b_setPowered); // request binding
+/*
+ // Example to bind a read-only property in individual steps:
+ property_signature p_manufacturer_signature(property_type::string, OC::OCReflect::property_attribute::r); // read-only
+
+ OC::OCReflect::named_property_binding p_manufacturer("manufacturer", p_manufacturer_signature);
+
+ property_binding b_manufacturer(
+ this->manufacturer,
+ p_manufacturer);
+
+ server.bind(b_manufacturer);
+
+ // The canonical way to bind a property to a server in one step:
+ bind_property(
+ server, // server to bind to
+ this->manufacturer, // pointer to property
+ "manufacturer", // property binding name
+ OC::OCReflect::property_type::string, // property
+ OC::OCReflect::property_attribute::r // type decoration
+ );
+*/
+ }
+};
+
+void show_bindings(const OC::OCServer& server)
+{
+ using namespace std;
+
+ const auto& methods = server.methods();
+
+ cout << "Bound methods:\n";
+ for(const auto& m : methods)
+ {
+ cout << m.first << ':' << m.second << '\n';
+ }
+}
+
+int main()
+{
+ OC::OCServer server;
+
+ try
+ {
+ light l;
+ l.bindTo(server, "/foo/");
+ }
+ catch(OC::OCReflect::reflection_exception& e)
+ {
+ std::cerr << "Oops: " << e.what() << '\n';
+ }
+
+ show_bindings(server);
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/* To avoid confusion: These are not unit tests, these are "test programs". */
+
+#include <map>
+#include <string>
+#include <cassert>
+#include <cstring>
+#include <cstdlib>
+#include <iostream>
+#include <algorithm>
+#include <stdexcept>
+
+#include "OCReflect.h"
+
+using namespace OC::OCReflect;
+
+// Convert a native type to a property:
+void convert_test()
+{
+ using std::cout;
+ using namespace OC::OCReflect;
+/*
+ // Nil (JSON: null):
+ {
+ property_signature ps(property_type::nil);
+ named_property_binding npb("nil_property", ps);
+ }
+*/
+
+ // Boolean:
+ {
+ OC::OCReflect::property my_bool = OC::OCReflect::make_property::apply(true, "my_bool");
+ OC::OCReflect::property my_bool_too = make_property::apply(false, "my_bool_too");
+
+ cout << my_bool << '\n' << my_bool_too << '\n';
+
+ auto x = concretize<bool>(my_bool);
+ auto y = concretize<bool>(my_bool_too);
+
+ cout << "got back: " << x << '\n';
+ cout << "got back: " << y << '\n';
+
+ assert(x == true);
+ assert(y == false);
+ }
+
+ // Integer:
+ {
+ const int64_t input { 1024 };
+ auto my_int = make_property::apply(input, "my int");
+
+ cout << my_int << '\n';
+
+ auto x = concretize<int64_t>(my_int);
+
+ cout << x << '\n';
+
+ assert(input == x);
+ }
+
+ // Rational (JSON: number):
+ {
+ const double input { 1024.0 };
+ auto my_float = make_property::apply(input, "my float");
+
+ cout << my_float << '\n';
+
+ auto x = concretize<double>(my_float);
+
+ cout << x << '\n';
+
+ assert(input == x);
+ }
+
+ // String:
+ {
+ const std::string input { "Hello, World!" };
+
+ auto my_string = make_property::apply(input, "my string");
+
+ cout << my_string << '\n';
+
+ auto x = concretize<std::string>(my_string);
+
+ cout << x << '\n';
+
+ assert(input == x);
+ }
+
+/*
+ // List (JSON: array):
+ {
+ property_signature(property_type::list);
+ }
+*/
+/* JFW:
+ // Dictionary (JSON: object):
+ {
+ property_signature(property_type::dictionary);
+ }
+*/
+
+ // test with attributes:
+}
+
+typedef property return_property;
+
+template <class InT>
+return_property make_return_property(const InT& in)
+{
+ return OC::OCReflect::make_property::apply(in, "__RETURN_VALUE__"); // ugly-- avert your eyes!
+}
+
+typedef std::function<return_property(const property_vector&)> bound_call;
+
+struct server
+{
+ std::map<std::string, bound_call> methods;
+};
+
+std::string test_fn(const std::string s0, const std::string s1)
+{
+ return s0 + " " + s1;
+}
+
+/*
+template <class ...ParamsT>
+void check_signature(const property_signature_vector& param_types, ParamsT ...params)
+{
+
+}
+
+struct call
+{
+ template <class ...ParamsT>
+ static return_property operator()(bound_call& f, const property_signature return_type, const property_signature_vector& param_types, ParamsT ...params)
+ {
+ check_signature(param_types, params...);
+
+ auto result = f(params...);
+
+ check_signature(return_type, result);
+
+ return result;
+ }
+*/
+
+/* - match type
+ - if type is concrete type
+ - return curried function for that thing
+ - this binds eventually to property(property_list), but calls underlying fn
+*/
+
+OC::OCReflect::property_signature head(const OC::OCReflect::property_signature_vector& psv)
+{
+ return psv[0];
+}
+
+// sloooow, but it will suit our purpose:
+OC::OCReflect::property_signature_vector tail(const OC::OCReflect::property_signature_vector psv)
+{
+ return OC::OCReflect::property_signature_vector(1 + psv.begin(), psv.end());
+}
+
+bool type_matches(const OC::OCReflect::property_type& expected_pt, const OC::OCReflect::property_data& in)
+{
+ auto begin = in.begin();
+
+ auto found_pt = static_cast<OC::OCReflect::property_type>(*begin);
+
+ std::cout << "val ept=" << (int)expected_pt << ", ept: " << (int)found_pt << '\n';
+
+ return expected_pt == found_pt;
+}
+
+bool type_matches(const OC::OCReflect::property_type expected_pt, const OC::OCReflect::property& in)
+{
+ return type_matches(expected_pt, std::get<1>(in));
+}
+
+bool signature_matches(const OC::OCReflect::property_signature&)
+{
+ return true;
+}
+
+/* JFW: tmp
+template <class X>
+bool signature_matches(const OC::OCReflect::property_signature& expected, X x)
+{
+ return type_matches(expected.type, OC::OCReflect::make_property::apply(x, "_"));
+}
+
+template <class X, class ...XS>
+bool signature_matches(const OC::OCReflect::property_signature_vector expected, X x, XS ...xs)
+{
+ return signature_matches(head(expected), x) && signature_matches(tail(expected), xs...);
+}
+
+template <class ...XS>
+bool signature_matches(const OC::OCReflect::property_signature_vector expected, XS ...xs)
+{
+ return signature_matches(head(expected), x) && signature_matches(tail(expected), xs...);
+ // return signature_matches(expected, xs...);
+}
+*/
+
+void call_test()
+{
+ server s;
+
+ s.methods["test_fn"] =
+ [](const property_vector& in) -> return_property
+ {
+ for(const auto& p : in)
+ std::cout << p << '\n';
+
+ auto s0 = concretize<std::string>(in[0]);
+ auto s1 = concretize<std::string>(in[1]);
+
+ return make_return_property(test_fn(s0, s1));
+ };
+
+ property_vector pv;
+ pv.emplace_back(make_property::apply("Hello", "s0"));
+ pv.emplace_back(make_property::apply("World", "s1"));
+
+ std::cout << "INPUT:\n" << pv << '\n';
+
+ auto result = s.methods["test_fn"](pv);
+
+ std::cout << concretize<std::string>(std::get<1>(result));
+
+ using namespace OC::OCReflect;
+
+ // typechecking:
+ {
+ auto foo = make_property::apply("Hi there", "s0");
+ assert(false == type_matches(property_type::boolean, foo));
+ assert(true == type_matches(property_type::string, foo));
+ }
+
+/* JFW: tmp
+ // signature typechecking:
+ {
+ property_signature_vector sig {
+ { property_type::string },
+ { property_type::integer }
+ };
+
+ assert(false == signature_matches(sig, 5, "Hello"));
+ assert(true == signature_matches(sig, "Hello", 5));
+ }
+*/
+
+/*
+ auto sig = make_fun_sig(property_type::string, // result
+ property_type::string, property_type::string); // params
+ std::cout << sig << '\n';
+*/
+/*
+ auto f = make_fun(test_fn,
+ property_type::string, // result
+ property_type::string, property_type::string); // params
+*/
+}
+
+// Demo of how to generate OCStack stuff:
+void rep_test()
+{
+ using OC::OCReflect::property_type;
+ using OC::OCReflect::named_property_binding;
+
+ named_property_binding_vector sigs {
+ named_property_binding("state", property_type::boolean),
+ named_property_binding("power", property_type::integer)
+ };
+
+ using namespace OC::OCReflect::to_OCStack;
+
+ /* JFW: note:
+ char *LEDrep[] = { "state;b", "power;i", NULL};
+
+ char **LEDrep = convert(convert(sigs));
+
+ if(0 == LEDrep)
+ error();
+
+ CREATE_RESOURCE_TYPE(LED, "core.led", LEDrep);
+ */
+std::vector<std::string> reps { convert(sigs) };
+ for(const auto& r : reps)
+ std::cout << r << '\n';
+
+ // Example of flattening to a single string:
+ char *flattened = flatten(reps);
+ std::cout << "FLATTENED: " << flattened << '\n';
+
+ // Example of converting to an array of char*s:
+ char **handle = convert(reps);
+
+ if(nullptr == handle)
+ throw std::runtime_error("handle is a nullptr");
+
+ std::for_each(handle, handle + length(handle), [](const char *s) { std::cout << s << '\n'; });
+
+ /* ...or, you could do it this way (sad panda!):
+ for(char **cursor = handle; nullptr != *cursor; ++cursor)
+ printf("%s\n", *cursor);
+ */
+
+ release(handle); // remember to free the memory!
+}
+
+void from_rep_test()
+{
+ using std::cout;
+
+ std::cout << "from_rep_test() doesn't do much yet :-)\n";
+/*
+ const char *LEDrep[] = { "state;b", "power;i", NULL };
+
+ named_property_binding_vector npbv(LEDrep);
+
+ cout << npbv << '\n';
+*/
+}
+
+int main()
+{
+ using namespace OC::OCReflect;
+
+ convert_test();
+
+ call_test();
+
+ rep_test();
+
+ from_rep_test();
+}
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _I_CLIENT_WRAPPER_H_
+#define _I_CLIENT_WRAPPER_H_
+
+#include <memory>
+#include <string>
+
+#include <OCApi.h>
+#include <OCResource.h>
+
+namespace OC
+{
+ class OCResource;
+ class IClientWrapper
+ {
+ public:
+ typedef std::shared_ptr<IClientWrapper> Ptr;
+
+ virtual int ListenForResource(const std::string& serviceUrl, const std::string& resourceType,
+ std::function<void(OCResource::Ptr)>& callback) = 0;
+ virtual ~IClientWrapper(){}
+
+ private:
+ };
+}
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _I_SERVER_WRAPPER_H_
+#define _I_SERVER_WRAPPER_H_
+
+#include <memory>
+#include <string>
+
+#include <OCReflect.h>
+
+using namespace OC::OCReflect;
+
+namespace OC
+{
+ class IServerWrapper
+ {
+ public:
+ typedef std::shared_ptr<IServerWrapper> Ptr;
+
+ virtual ~IServerWrapper(){};
+
+ // TODO: SASHI : parameters by reference???
+ virtual void registerResource( const std::string& resourceURI,
+ const std::string& resourceTypeName,
+ named_property_binding_vector properties) = 0;
+ };
+}
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _IN_PROC_CLIENT_WRAPPER_H_
+#define _IN_PROC_CLIENT_WRAPPER_H_
+
+#include <thread>
+#include <mutex>
+#include <sstream>
+#include <iostream>
+
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/json_parser.hpp>
+
+#include <OCApi.h>
+#include <ocstack.h>
+#include <IClientWrapper.h>
+#include <InitializeException.h>
+#include <ResourceInitException.h>
+
+namespace OC
+{
+ class InProcClientWrapper : public IClientWrapper
+ {
+ public:
+ InProcClientWrapper(PlatformConfig cfg);
+ virtual ~InProcClientWrapper();
+
+ virtual int ListenForResource(const std::string& serviceUrl, const std::string& resourceType, std::function<void(OCResource::Ptr)>& callback);
+
+ private:
+ void listeningFunc();
+ std::thread m_listeningThread;
+ bool m_threadRun;
+ std::mutex m_resourceListenerLock;
+ std::mutex m_csdkLock;
+ std::vector<std::function<void(OCClientResponse*)>> callbackList;
+ };
+}
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _IN_PROC_SERVER_WRAPPER_H_
+#define _IN_PROC_SERVER_WRAPPER_H_
+
+#include <thread>
+#include <mutex>
+#include <ocstack.h>
+#include <OCApi.h>
+#include <IServerWrapper.h>
+#include <OCReflect.h>
+
+using namespace OC::OCReflect;
+
+namespace OC
+{
+ class InProcServerWrapper : public IServerWrapper
+ {
+ public:
+ InProcServerWrapper(PlatformConfig cfg);
+ virtual ~InProcServerWrapper();
+
+ void registerResource( const std::string& resourceURI,
+ const std::string& resourceTypeName,
+ named_property_binding_vector properties);
+
+ private:
+ void processFunc();
+ std::thread m_processThread;
+ bool m_threadRun;
+ std::mutex m_csdkLock;
+ };
+}
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _INITIALIZE_EXCEPTION_H_
+#define _INITIALIZE_EXCEPTION_H_
+
+#include <stdexcept>
+#include <ocstack.h>
+
+namespace OC
+{
+ class InitializeException : public std::exception
+ {
+ public:
+ InitializeException(const std::string& msg, OCStackResult reasonCode): m_errorMessage(msg), m_reason(reasonCode)
+ {
+ }
+
+ OCStackResult ReasonCode()
+ {
+ return m_reason;
+ }
+
+ std::string Message()
+ {
+ return m_errorMessage;
+ }
+
+ std::string Reason()
+ {
+ switch(m_reason)
+ {
+ case OC_STACK_OK:
+ return "No Error";
+ case OC_STACK_INVALID_URI:
+ return "Invalid URI";
+ case OC_STACK_INVALID_IP:
+ return "Invalid IP";
+ case OC_STACK_INVALID_PORT:
+ return "Invalid Port";
+ case OC_STACK_INVALID_CALLBACK:
+ return "Invalid Callback";
+ case OC_STACK_INVALID_METHOD:
+ return "Invalid Method";
+ case OC_STACK_ERROR:
+ return "General Fault";
+ default:
+ return "Unknown Error";
+ }
+ }
+
+ private:
+ const std::string& m_errorMessage;
+ OCStackResult m_reason;
+ };
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef __INTEL_OCAPI_H_2014_07_10
+ #define __INTEL_OCAPI_H_2014_07_10
+
+#include <string>
+#include <vector>
+
+namespace OC {
+
+class OCResource;
+
+} // namespace OC
+
+namespace OC { namespace OCReflect {
+
+struct entity;
+
+}} // namespace OC::OCReflect
+
+namespace OC {
+
+ enum class OCPlatformStatus {
+ PlatformUp,
+ PlatformDown
+ };
+
+ enum class OCAdvertisementStatus{
+ None
+ };
+
+ typedef std::string URI;
+
+ enum class ServiceType
+ {
+ InProc,
+ OutOfProc
+ };
+
+ enum class ModeType
+ {
+ Server,
+ Client,
+ Both
+ };
+
+ struct PlatformConfig
+ {
+ ServiceType serviceType; // This will indicate whether it is InProc or OutOfProc
+ ModeType mode; // This will indicate whether we want to do server, client or both
+ std::string ipAddress; // This is the ipAddress of the server to connect to
+ uint16_t port; // Port of the server
+ };
+
+} // namespace OC
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef __INTEL_OCEXCEPTION_H_2014_07_10
+ #define __INTEL_OCEXCEPTION_H_2014_07_10
+
+#include <stdexcept>
+
+namespace OC { namespace OCReflect {
+
+typedef std::runtime_error reflection_exception;
+
+class OCException : public std::exception
+{
+
+};
+
+}} // namespace OC::OCReflect
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCObject.h
+
+/// @brief This file contains the declaration of classes and its members related to
+/// OCObject.
+
+#ifndef __OCOBJECT_H
+#define __OCOBJECT_H
+
+namespace OC
+{
+ /**
+ * @brief The OCObject is the root abstract class from which many of the OC related objects derive from.
+ * It implements a common set of functionality supported by all the OC classes in the
+ * SDK such as object naming, ID, natural sort order and comparison.
+ */
+ class OCObject
+ {
+ public:
+ OCObject(void);
+
+ virtual ~OCObject(void);
+
+ /**
+ * @fn Determines if the resource should be listed in the well-known core list.
+ *
+ * NOTE: This may be better handled at a different location.
+ *
+ * @return Returns true if resource should be listed.
+ */
+ virtual bool isVisible() = 0;
+ };
+}
+
+#endif //__OCOBJECT_H
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCObserver.h
+
+/// @brief This file contains the declaration of classes and its members related to
+/// OCObserver.
+
+#ifndef __OCOBSERVER_H
+#define __OCOBSERVER_H
+
+#include <string>
+
+#include "OCObserver.h"
+
+namespace OC
+{
+ /* It allows an app to register a method handler to monitor for
+ state changes on a resource. Not all resource attributes are observable.
+ */
+ class OCObserver
+ {
+ public:
+ OCObserver(void);
+
+ virtual ~OCObserver(void);
+ };
+
+ /* It is likely that these signatures will change somewhat: */
+ template <typename HandlerT, typename ResourceT>
+ void bind_observer(HandlerT handler, ResourceT& resource, const std::string& name)
+ {};
+
+ // unbind the specified handler:
+ template <typename HandlerT, typename ResourceT>
+ void unbind_observer(HandlerT handler, ResourceT& resource)
+ {};
+
+ // unbind by name:
+ template <typename HandlerT, typename ResourceT>
+ void unbind_observer(HandlerT handler, ResourceT& resource, const std::string& name)
+ {};
+
+} // namespace OC
+
+#endif //__OCOBSERVER_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCObserverHandler.h
+
+/// @brief This file contains the declaration of classes and its members related to
+/// ObserverHandler.
+
+#ifndef __OCOBSERVERHANDLER_H
+#define __OCOBSERVERHANDLER_H
+
+#include "OCApi.h"
+
+namespace OC
+{
+ /**
+ * @brief OCObserverHandler is a pure abstract class and it can be used for
+ * observer related callbacks
+ */
+
+ class OCObserverHandler
+ {
+ public:
+ virtual ~OCObserverHandler(void)
+ {}
+
+ /**
+ * @fn This function is called when the property gets updated
+ *
+ * @param propertyName name of the property
+ * @param value value of the property
+ */
+ virtual void onObserverUpdate(std::string propertyName, void *value) = 0;
+ };
+
+}
+#endif //__OCOBSERVERHANDLER_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCPlatform.h
+
+/// @brief This file contains the declaration of classes and its members related to
+/// OCPlatform.
+
+#ifndef __OCPLATFORM_H
+#define __OCPLATFORM_H
+
+#include <map>
+
+#include "OCApi.h"
+#include "OCResource.h"
+#include "OCPlatformHandler.h"
+#include "WrapperFactory.h"
+#include <OCReflect.h>
+
+using namespace OC::OCReflect;
+
+namespace OC
+{
+ using OC::OCReflect::property_type;
+ using OC::OCReflect::named_property_binding;
+
+ /**
+ * @brief The core OC platform object initialized by the application or service via a static accessor.
+ * On successful initialization an instance of the OCPlatform is returned.
+ * Handler registered that receives various platform/stack updates. The stack object
+ * also provides methods for managing advertisement and discovery.
+ */
+ class OCPlatform
+ {
+ public:
+ /**
+ * @fn Constructor for OCPlatform. Constructs a new OCPlatform from a given PlatformConfig with
+ * appropriate fields
+ * @param config - PlatformConfig struct which has details such as modeType (server/client/both),
+ * in-proc/out-of-proc etc.
+ */
+ OCPlatform(const PlatformConfig& config);
+
+ /**
+ * @fn Virtual destructor
+ */
+ virtual ~OCPlatform(void);
+
+ /**
+ * @fn API for Service and Resource Discovery
+ *
+ * @param host - Host IP Address of a service to direct resource discovery query. If null or
+ * empty, performs service discovery OR resource discovery query to ALL group members.
+ * @param filter<std::string FilterType, std::string Value> - Filter Type - Can be one of two of the link
+ * format equivalent attribute types declared in table 7 of the
+ * OC-Lite-Product-Specification-V1 Document. Either "n" (i.e. Resource Name) or "rt"
+ * (i.e. Resource Type). Value - Can be any valid std::string that's defined to work with CoRE
+ * Link Attributes as defined in the RFC6690.
+ * @param handler - Handles callbacks, success states and failure states.
+ *
+ * Four modes of discovery defined as follows:
+ * (NULL/Empty, NULL/Empty) - Performs ALL service discovery AND ALL resource discovery.
+ * (NULL/Empty, Not Empty) - Performs query for a filtered/scoped/particular resource(s)
+ * from ALL services.
+ * (Not Empty, NULL/Empty) - Performs ALL resource discovery on a particular service.
+ * (Not Empty, Not Empty) - Performs query for a filtered/scoped/particular resource(s)
+ * from a particular service.
+ *
+ * Thread-Safety: TODO Determine if it is going to be safe to call in a UI thread
+ */
+ void findResource(const std::string& host, const std::string& resourceName,
+ std::function<void(OCResource::Ptr)> resourceHandler);
+
+ /**
+ * @fn Queries the network for available resources.
+ *
+ * NOTE: This gets posted to a new thread so it doesn't hold the UI or network thread.
+ *
+ * @param serviceURL - The URL to the service. NULL for a broadcast/multicast.
+ * @param resourceType - The resource type filter. NULL for match any.
+ *
+ * @throws This may throw if the service is not started, network is bad, etc.
+ *
+ * Thread-Safety: TODO Determine if it is going to be safe to call in a UI thread
+ */
+ void findResourceByType(const std::string& serviceURL, const std::string& resourceType,
+ std::function<void(OCResource::Ptr)> resourceHandler);
+
+ /**
+ * @fn Registers the resource with its name, type and list of properties
+ *
+ * NOTE: Properties are prepared prior to this call using generic functions from OCReflect
+ *
+ * @param resourceURI - The URI of the resoruce.
+ * @param resourceTypeName - The resource type.
+ * @param properties - vector of properties for this resource
+ *
+ */
+ void registerResource(const std::string& resourceURI, const std::string& resourceTypeName,
+ named_property_binding_vector properties);
+
+ private:
+ std::unique_ptr<WrapperFactory> m_WrapperInstance;
+ IServerWrapper::Ptr m_server;
+ IClientWrapper::Ptr m_client;
+
+ /**
+ * @fn Private function to initalize the platfrom
+ */
+ void init(const PlatformConfig& config);
+
+ /**
+ * @fn Private function cleanup the platform
+ */
+ void cleanup();
+ };
+}
+
+#endif //__OCPLATFORM_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCPlatformHandler.h
+
+/// @brief This file contains the declaration of classes and its members related to
+/// OCPlatformHandler.
+
+#ifndef __OCPLATFORMHANDLER_H
+#define __OCPLATFORMHANDLER_H
+
+#include "OCApi.h"
+
+namespace OC
+{
+ class OCPlatform;
+
+ /**
+ * @brief OCPlatformHandler is a pure abstract class and it can be used for
+ * registering and getting callbacks
+ */
+ class OCPlatformHandler
+ {
+ public:
+ OCPlatformHandler(void);
+
+ virtual ~OCPlatformHandler(void);
+
+ /**
+ * @fn This function is called when the platform gets initialzed
+ *
+ * @param platform pointer to OCPlatform object
+ */
+ virtual void onPlatformInitialized(OCPlatform *platform) = 0;
+
+ /**
+ * @fn This function is called when platform status is changed
+ *
+ * @param platform - pointer to OCPlatform object
+ * @param status - OCPlatform status
+ */
+ virtual void onPlatformStatusChanged(OCPlatform *platform, OCPlatformStatus status) = 0;
+ };
+}
+
+#endif // __OCPLATFORMHANDLER_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef __INTEL_OCPROPERTIES_H_20140708
+ #define __INTEL_OCPROPERTIES_H_20140708
+
+#include <list>
+#include <array>
+#include <deque>
+#include <vector>
+#include <algorithm>
+#include <functional>
+
+#include <sstream>
+#include <ostream>
+#include <iostream>
+
+#include <iterator>
+#include <type_traits>
+
+#include "OCException.h"
+
+namespace OC { namespace OCReflect {
+
+enum class property_type : uint8_t {
+ nil = 1,
+ boolean,
+ integer,
+ rational,
+ string,
+ list,
+
+ INVALID
+};
+
+enum class property_attribute : uint8_t {
+ r,
+ w,
+ rw
+};
+
+struct property_signature
+{
+ OC::OCReflect::property_type type;
+ OC::OCReflect::property_attribute attribute;
+
+ public:
+ property_signature()
+ : type(OC::OCReflect::property_type::nil),
+ attribute(OC::OCReflect::property_attribute::rw)
+ {}
+
+ property_signature(const OC::OCReflect::property_type& type_)
+ : type(type_),
+ attribute(OC::OCReflect::property_attribute::rw)
+ {}
+
+ property_signature(const OC::OCReflect::property_type type_, const OC::OCReflect::property_attribute attribute_)
+ : type(type_),
+ attribute(attribute_)
+ {}
+};
+
+typedef std::vector<property_type> property_type_vector;
+
+typedef std::vector<property_signature> property_signature_vector;
+
+typedef std::vector<char> property_data;
+
+typedef std::tuple<std::string, property_signature> named_property_binding;
+typedef std::vector<named_property_binding> named_property_binding_vector;
+
+typedef std::tuple<named_property_binding, property_data> property;
+typedef std::tuple<property_signature, property_data> tagged_property; // eg. a return value
+
+typedef std::vector<property> property_vector;
+
+typedef std::function<property(property_vector)> bound_function;
+
+namespace detail {
+
+// Great name, huh? Must be late in the day:
+inline property_signature_vector typev2signaturev(const property_type_vector& ptv, const property_attribute pa = property_attribute::rw)
+{
+ property_signature_vector psv(ptv.size());
+
+ std::transform(std::begin(ptv), std::end(ptv), std::back_inserter(psv),
+ [&pa](const property_type& pt) -> property_signature { return property_signature(pt, pa); });
+
+ return psv;
+}
+
+}
+
+namespace detail {
+
+// Helper for constructing sequences (like vector<property>) from a parameter pack:
+template <typename SeqT, typename T>
+SeqT make_seq(const T& x)
+{
+ return SeqT { x };
+}
+
+template <typename SeqT, typename T, typename ...TS>
+SeqT make_seq(const T& x, const TS&... xs)
+{
+ SeqT s { x };
+
+ auto vs = make_seq<SeqT>(xs...);
+
+ s.insert(s.end(), std::make_move_iterator(vs.begin()), std::make_move_iterator(vs.end()));
+
+ return s;
+}
+
+} // namespace OC::OCReflect::detail
+
+}} // namespace OC::OCReflect
+
+// Prettyprinters:
+namespace OC { namespace OCReflect {
+
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_type& pt);
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_attribute& pa);
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_signature& ps);
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property& p);
+
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_type_vector& pv);
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::property_vector& p);
+
+std::ostream& operator<<(std::ostream& os, const OC::OCReflect::method_binding& mb);
+
+}} // namespace OC::OCReflect
+
+/* JFW: I wonder if I can do this...
+constexpr OC::OCReflect::property_type map_property_type(bool)
+{
+ return OC::OCReflect::property_type::boolean;
+}
+*/
+
+// Map concerete to property type enumerations:
+namespace OC { namespace OCReflect {
+
+template <typename T>
+struct map_property_type
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::INVALID);
+};
+
+template <>
+struct map_property_type<bool>
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::boolean);
+};
+
+template <>
+struct map_property_type<int64_t>
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::integer);
+};
+
+template <>
+struct map_property_type<double>
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::rational);
+};
+
+template <>
+struct map_property_type<std::string>
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::string);
+};
+
+template <>
+struct map_property_type<const char *>
+{
+ static const uint8_t value = static_cast<const uint8_t>(OC::OCReflect::property_type::string);
+};
+
+}} // namespace OC::OCReflect
+
+/*
+// Sequence containers:
+template <>
+struct map_property_type< template <class T, class A> >
+{
+ static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
+};
+
+template <>
+struct map_property_type<std::vector>
+{
+ static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
+};
+
+template <>
+struct map_property_type<std::list>
+{
+ static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
+};
+
+template <>
+struct map_property_type<std::forward_list>
+{
+ static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
+};
+
+template <>
+struct map_property_type<std::deque>
+{
+ static const uint8_t value = static_const<const uint8_t>(OC::OCReflect::property_type::list);
+};
+*/
+
+namespace OC { namespace OCReflect { namespace to_property {
+
+OC::OCReflect::tagged_property convert(const bool& in);
+OC::OCReflect::tagged_property convert(const int& in);
+OC::OCReflect::tagged_property convert(const int64_t& in);
+OC::OCReflect::tagged_property convert(const double& in);
+OC::OCReflect::tagged_property convert(const std::string& in);
+
+}}} // namespace OC::OCReflect::to_property
+
+typedef std::tuple<OC::OCReflect::property_data::const_iterator, OC::OCReflect::property_data::const_iterator> pd_iter_tuple;
+
+pd_iter_tuple consume_typecheck(const OC::OCReflect::property_type expected_pt, const OC::OCReflect::property_data& in);
+
+namespace OC { namespace OCReflect { namespace from_property {
+
+typedef OC::OCReflect::property_data::const_iterator pdci;
+typedef std::tuple<pdci, pdci> pd_iter_pair;
+
+/* We need to use a struct to get around the fact that we can't partially specialize against a
+free function's signature-- nothing else special happening here: */
+struct conversion {
+
+static void convert(const pd_iter_pair& in, bool& out)
+{
+ out = static_cast<bool>(static_cast<int>(*(std::get<0>(in))));
+}
+
+static void convert(const pd_iter_pair& in, int64_t& out)
+{
+ std::copy(std::get<0>(in), std::get<1>(in), reinterpret_cast<char *>(&out));
+}
+
+static void convert(const pd_iter_pair& in, double& out)
+{
+ std::copy(std::get<0>(in), std::get<1>(in), reinterpret_cast<char *>(&out));
+}
+
+static void convert(const pd_iter_pair& in, std::string& out)
+{
+ out.assign(std::get<0>(in), std::get<1>(in));
+}
+
+/*
+template <template <class T, class AllocT> class SeqT>
+static void convert(const pd_iter_pair& in, SeqT& out)
+{
+ std::copy(std::get<0>(in), std::get<1>(in), std::back_inserter(out));
+}
+*/
+
+};
+
+}}} // namespace OC::OCReflect::from_property
+
+namespace OC { namespace OCReflect {
+
+inline OC::OCReflect::named_property_binding make_named_property_binding(const std::string& name, const OC::OCReflect::property_type pt, const OC::OCReflect::property_attribute pa = OC::OCReflect::property_attribute::rw)
+{
+ return OC::OCReflect::named_property_binding { name, { pt, pa } };
+}
+
+}} // namespace OC::OCReflect
+
+// ...probably not-so-efficent, but we want it "working" for now:
+namespace OC { namespace OCReflect {
+
+// ...a class just to facilitate the usual ADL trick:
+struct make_property {
+
+// ...work around array->bool conversion:
+static OC::OCReflect::property apply(const char *in, const std::string& name)
+{
+ return apply(std::string(in), name);
+}
+
+template <class InT>
+static OC::OCReflect::property apply(const InT& in, const std::string& name)
+{
+/* JFW:
+ static_assert(property_valid(InT, OC::OCReflect::property_type::INVALID),
+ "invalid input type for make_property()");
+*/
+
+ OC::OCReflect::tagged_property tp { OC::OCReflect::to_property::convert(in) };
+ OC::OCReflect::named_property_binding npb { name, { std::get<0>(tp) } };
+
+ OC::OCReflect::property_data& tp_data = std::get<1>(tp);
+
+ // Encode the type, followed by the data:
+ OC::OCReflect::property_data encoded_data;
+
+ encoded_data.push_back(OC::OCReflect::map_property_type<InT>::value);
+ std::copy(std::begin(tp_data), std::end(tp_data), std::back_inserter(encoded_data));
+
+ return OC::OCReflect::property(npb, encoded_data);
+}
+
+/*
+// Pretend you didn't see this, and I won't tell anyone where you hide the bodies:
+template <class InT>
+make_property(const InT& in, const std::string& name, OC::OCReflect::property& out)
+{
+ out = detail::make_property::apply(in, name, out);
+}
+*/
+
+}; // struct make_property
+
+}} // namespace OC::OCReflect
+
+namespace OC { namespace OCReflect {
+
+template <class OutT>
+OutT concretize(const OC::OCReflect::property_data& pd)
+{
+ OutT ret;
+
+ OC::OCReflect::from_property::conversion::convert(
+ consume_typecheck(
+ static_cast<OC::OCReflect::property_type>(
+ OC::OCReflect::map_property_type<OutT>::value), pd), ret);
+
+ return ret;
+}
+
+template <class OutT>
+OutT concretize(const OC::OCReflect::tagged_property& tp)
+{
+ return concretize<OutT>(std::get<1>(tp));
+}
+
+template <class OutT>
+OutT concretize(const OC::OCReflect::property& p)
+{
+ return concretize<OutT>(std::get<1>(p));
+}
+
+}} // namespace OC::OCReflect
+
+namespace OC { namespace OCReflect {
+
+// Runtime dynamic cast from entities to concrete types:
+template <class OutT>
+OutT narrow(const entity& e)
+{
+ return OutT(); // placeholder
+}
+
+struct method_signature
+{
+ property_signature ret_signature;
+ property_signature_vector param_signatures;
+
+ public:
+ method_signature(const property_type& return_type, const property_signature_vector& param_types_)
+ : ret_signature(return_type, OC::OCReflect::property_attribute::r),
+ param_signatures(param_types_)
+ {}
+
+ method_signature(const property_type& return_type, const property_type_vector& param_types_)
+ : ret_signature(return_type, OC::OCReflect::property_attribute::r),
+ param_signatures(detail::typev2signaturev(param_types_))
+ {}
+
+ template <typename ...ParameterT>
+ method_signature(const property_type& return_type, const ParameterT& ...params_)
+ : ret_signature(return_type, OC::OCReflect::property_attribute::r),
+ param_signatures { detail::make_seq<property_signature_vector>(params_...) }
+ {}
+};
+
+}} // namespace OC::OCReflect
+
+namespace OC { namespace OCReflect {
+
+struct method_binding
+{
+ friend std::ostream& operator<<(std::ostream& os, const OC::OCReflect::method_binding& mb);
+
+ public:
+ std::string name;
+ bound_function f;
+ method_signature signature;
+
+ private:
+ static unsigned long long anon;
+
+ public:
+ method_binding()
+ : name("__ANONYMOUS__"),
+ signature { property_type::nil, {{ property_type::nil, property_attribute::r }} }
+ {}
+
+ method_binding(bound_function& f,
+ method_signature& signature_)
+ : signature(signature_)
+ {}
+
+ method_binding(const std::string& name_, bound_function& f_,
+ const property_type& return_type_, const property_type_vector& param_types_)
+ : name(name_),
+ f(f_),
+ signature { return_type_, param_types_ }
+ {}
+
+ method_binding(const std::string& name_, bound_function& f_,
+ const method_signature& signature_)
+ : name(name_),
+ f(f_),
+ signature(signature_)
+ {}
+};
+
+struct property_binding
+{
+ template <typename PropertyT>
+ property_binding(PropertyT& property, const named_property_binding& pb)
+ {
+ }
+};
+
+}} // namespace OC::OCReflect
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef __INTEL_OCREFLECT_H_20140708
+ #define __INTEL_OCREFLECT_H_20140708
+
+#include <iostream>
+
+/* Runtime reflection support. */
+
+#include <tuple>
+#include <string>
+#include <vector>
+#include <memory>
+#include <cstring>
+#include <cstdlib>
+#include <functional>
+
+#include "OCServer.h"
+#include "OCProperties.h"
+
+namespace OC { namespace OCReflect {
+
+struct service;
+class remote_resource;
+struct entity;
+class method;
+
+struct service
+{
+ template <typename NarrowT>
+ NarrowT property(const OC::OCReflect::entity& entity);
+
+ OC::OCReflect::method method(const std::string& name);
+};
+
+/* This type originally represented a binding to a server-- I think it can probably
+be factored out soon: */
+class remote_resource
+{
+ OC::OCResource& resource;
+
+ std::string resource_location;
+
+ public:
+ remote_resource(OC::OCResource& resource_, const std::string& resource_location_)
+ : resource(resource_),
+ resource_location(resource_location_)
+ {}
+
+ public:
+ OC::OCReflect::entity operator()(const std::string& name);
+};
+
+struct entity
+{
+ // underlying type; data buffer; ctor may only be invoked from a remote resource
+};
+
+class method
+{
+ OC::OCResource *resource; // observing ptr
+
+ std::string name;
+
+ public:
+ /* This default ctor will go away once real narrowing is functional-- here to placate the compiler for now.
+ - Ultimately, you should never be able to construct one of these in an invalid state. */
+ method()
+ : resource { nullptr }
+ {}
+
+ method(OC::OCResource& resource_, const std::string& name_)
+ : resource(&resource_),
+ name(name_)
+ {}
+
+ public:
+ /* Note that this declaration will likely change in the near future: */
+ template <class ...TS>
+ OC::OCReflect::tagged_property operator()(TS ...xs)
+ {
+ return OC::OCReflect::tagged_property();
+ };
+};
+
+}} // namespace OC::OCReflect
+
+// Convert to underlying OCStack C API (and, some handy C-wrangling utilities):
+namespace OC { namespace OCReflect { namespace to_OCStack {
+
+void release(char **in);
+char *strdup(const char *s);
+char *strdup(const std::string& s);
+size_t length(char **in);
+char **convert(const std::vector<std::string>& vs);
+std::string convert(const named_property_binding& npb);
+std::vector<std::string> convert(const named_property_binding_vector& psv);
+
+char *flatten(const std::vector<std::string>& input, const std::string& delim = ";");
+
+}}} // namespace OC::OCReflect::to_OCStack
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCResource.h
+
+/// @brief This file contains the declaration of classes and its members related to
+/// Resource.
+
+#ifndef __OCRESOURCE_H
+#define __OCRESOURCE_H
+
+#include <memory>
+#include <random>
+
+#include <boost/property_tree/ptree.hpp>
+#include <boost/property_tree/json_parser.hpp>
+
+#include <OCApi.h>
+#include <ResourceInitException.h>
+
+namespace OC
+{
+ /**
+ * @brief OCResource represents an OC resource. A resource could be a light controller,
+ * temperature sensor, smoke detector, etc. A resource comes with a well-defined
+ * contract or interface onto which you can perform different operations, such as
+ * turning on the light, getting the current temperature or subscribing for event
+ * notifications from the smoke detector. A resource can be composed of one or
+ * more resources.
+ */
+ class OCResource
+ {
+ public:
+ typedef std::shared_ptr<OCResource> Ptr;
+
+ OCResource(std::string host, boost::property_tree::ptree& resourceNode);
+ virtual ~OCResource(void);
+
+ // Gets the device host URI
+ std::string host() const {return m_host;}
+ // Gets the device-relative URI for this resource
+ std::string uri() const {return m_uri;}
+ // bool whether it is possible to attach an observer to this resource
+ bool isObservable() const {return m_isObservable;}
+ // bool whether this is a collection type, and will have children that can be queried
+ bool isCollection() const {return m_isCollection;}
+ // a collection of the resource-type names
+ const std::vector<std::string> resourceTypes() const {return m_resourceTypes;}
+ // a collection of the interfaces supported by this resource
+ const std::vector<std::string> interfaces() const { return m_interfaces;}
+ // a collection of property objects that allow calling of properties on this Resource
+ const std::vector<std::string> properties() const { return m_properties;}
+ // a collection of the names of the children of this resource, assuming it supports a collection interface
+ const std::vector<std::string> children() const {return m_children;}
+
+
+ // a method which allows
+ private:
+ std::string m_uri;
+ std::string m_host;
+ bool m_isObservable;
+ bool m_isCollection;
+ std::vector<std::string> m_resourceTypes;
+ std::vector<std::string> m_interfaces;
+ std::vector<std::string> m_properties; // TODO: give a better type once we have the ability to call one!
+ std::vector<std::string> m_children;
+ };
+
+} // namespace OC
+
+#endif //__OCRESOURCE_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCResourceHandler.h
+
+/// @brief This file contains the declaration of classes and its members related to
+/// ResourceHandler.
+
+#ifndef _OCRESOURCEHANDLER_H
+#define _OCRESOURCEHANDLER_H
+
+#include "ocapi.h"
+#include "OCResource.h"
+
+namespace OC
+{
+ /**
+ * @brief OCResourceHandler is a pure abstract class and it can be used for
+ * resource related callbacks
+ */
+ class OCResourceHandler
+ {
+ public:
+ virtual ~OCResourceHandler(void){}
+ /**
+ * @fn This function is called when it finds the resource
+ *
+ * @param update resource result information
+ * @param params reserved
+ */
+ virtual void onFoundResource(OCResourceResult *update, void *params) = 0;
+ /**
+ * @fn This function is called when the find is completed
+ *
+ * @param propertyName name of the property
+ * @param value value of the property
+ */
+ virtual void onCompleted() = 0;
+ /**
+ * @fn This function is called when the find is failed
+ *
+ */
+ virtual void onFailed() = 0;
+
+ };
+}
+#endif //_OCRESOURCEHANDLER_H
+
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCSecurityModel.h
+
+/// @brief This file contains the declaration of classes and its members required to provide
+/// security model support.
+
+#ifndef __OCSECURITYMODEL_H
+#define __OCSECURITYMODEL_H
+
+#include "OCApi.h"
+
+namespace OC
+{
+ /**
+ * @brief This class provides the required security model to
+ * access a service or a particular resource.
+ */
+ class OCSecurityModel
+ {
+ public:
+ OCSecurityModel(void);
+
+ virtual ~OCSecurityModel(void);
+
+ /**
+ * @fn checks the security access
+ *
+ * @param sourceURI - source URI
+ * @param destinationURI - destination URI of the resoruce to access
+ * @param encryptionLevel - Encryption level
+ * @param remoteIdentity - remote identity
+ */
+ void checkAccess(URI sourceURI, URI destinationURI, int encryptionLevel, int remoteIdentity);
+ };
+}
+
+#endif //__OCSECURITYMODEL_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+/// @file OCServer.h
+
+/// @brief This file contains the declaration of classes and its members required to provide
+/// functionality of a server. A server role supports resoruce registration, binding
+/// and advertisement.
+
+#ifndef __OCSERVER_H
+#define __OCSERVER_H
+
+#include <map>
+#include <string>
+
+#include "OCObject.h"
+#include "OCSecurityModel.h"
+
+namespace OC { namespace OCReflect {
+
+struct method_binding;
+struct property_binding;
+
+}} // namespace OC::OCReflect
+
+namespace OC
+{
+ /**
+ @brief A server instance which is the starting point for a UB device that wishes to host a
+ set of resource(s) for other devices.
+ */
+ class OCServer
+ {
+ private:
+ std::map<std::string, OC::OCReflect::method_binding> method_bindings;
+
+ public:
+ OCServer(void);
+ virtual ~OCServer(void);
+
+ /**
+ * @fn This registers a security model for access control to resources under this service.
+ *
+ * @param model - Security Model required for access to this service and control/view of it's
+ * services.
+ */
+ void setSecurityModel(OCSecurityModel model) ;
+
+ /**
+ * @fn Registers a resource with the service.
+ *
+ * @param object - The OCObject that handles the resource requests
+ * @param url - The URL under the resource.
+ * @param accessControl - The access control handler that determines whether the remote device is
+ * allowed to access this resource. If NULL, all access is granted.
+ */
+ void registerResource(OCObject *object, std::string url/* TODO: , AccessControl accessControl */);
+
+ /**
+ * @fn Unregisters a resource with the service.
+ *
+ * @param object - The OCObject to be unregistered.
+ */
+ void unregisterResource(OCObject *object);
+
+ /**
+ * @fn Starts the open connectivity service.
+ *
+ * Thread-Safety: TODO Determine if it is going to be safe to call in a UI thread
+ */
+ void start();
+
+ /**
+ * Stops the open connectivity service.
+ *
+ * Thread-Safety: TODO Determine if it is going to be safe to call in a UI thread
+ */
+ void stop();
+
+ public:
+ void bind(const OC::OCReflect::method_binding& mb);
+
+ void bind(const OC::OCReflect::property_binding& pb)
+ {}
+
+ template <class T>
+ void registerResource(T *object, const std::string& base_URI)
+ {}
+
+ public:
+ const std::map<std::string, OC::OCReflect::method_binding>& methods() const { return method_bindings; }
+ };
+}
+
+#endif //__OCSERVER_H
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _OUT_OF_PROC_CLIENT_WRAPPER_H_
+#define _OUT_OF_PROC_CLIENT_WRAPPER_H_
+
+#include <OCApi.h>
+
+namespace OC
+{
+ class OutOfProcClientWrapper : public IClientWrapper
+ {
+ public:
+ OutOfProcClientWrapper(PlatformConfig cfg) { }
+ virtual int ListenForResource(const std::string& serviceUrl, const std::string& resourceType, std::function<void(OCResource::Ptr)>& callback) {return 0;}
+ };
+}
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _OUT_OF_PROC_SERVER_WRAPPER_H_
+#define _OUT_OF_PROC_SERVER_WRAPPER_H_
+
+#include <OCApi.h>
+
+#include <OCReflect.h>
+
+using namespace OC::OCReflect;
+
+namespace OC
+{
+ class OutOfProcServerWrapper : public IServerWrapper
+ {
+ public:
+ OutOfProcServerWrapper(PlatformConfig cfg) {};
+
+ void registerResource( const std::string& resourceURI,
+ const std::string& resourceTypeName,
+ named_property_binding_vector properties)
+ {
+ }
+
+ };
+}
+
+#endif
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _RESOURCE_INIT_EXCEPTION_H_
+#define _RESOURCE_INIT_EXCEPTION_H_
+
+#include <stdexcept>
+#include <ocstack.h>
+
+namespace OC
+{
+ class ResourceInitException : public std::exception
+ {
+ public:
+ ResourceInitException(bool missingUri, bool missingType, bool missingInterface)
+ : m_missingUri(missingUri), m_missingType(missingType), m_missingInterface(missingInterface)
+ {
+ }
+
+ bool isUriMissing()
+ {
+ return m_missingUri;
+ }
+
+ bool isTypeMissing()
+ {
+ return m_missingType;
+ }
+
+ bool isInterfaceMissing()
+ {
+ return m_missingInterface;
+ }
+
+ std::string Reason()
+ {
+ std::string ret;
+
+ if(isUriMissing())
+ {
+ ret += "Missing URI;";
+ }
+
+ if(isTypeMissing())
+ {
+ ret += "Missing Resource Type;";
+ }
+
+ if(isInterfaceMissing())
+ {
+ ret += "Missing Interface;";
+ }
+
+ return ret;
+ }
+
+ private:
+ bool m_missingUri;
+ bool m_missingType;
+ bool m_missingInterface;
+ };
+}
+
+#endif
\ No newline at end of file
--- /dev/null
+//******************************************************************
+//
+// Copyright 2014 Intel Corporation All Rights Reserved.
+//-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
+
+#ifndef _WRAPPER_FACTORY_H_
+#define _WRAPPER_FACTORY_H_
+
+#include <memory>
+#include <OCApi.h>
+#include "IClientWrapper.h"
+#include "IServerWrapper.h"
+#include <OutOfProcClientWrapper.h>
+#include <InProcClientWrapper.h>
+#include <OutOfProcServerWrapper.h>
+#include <InProcServerWrapper.h>
+
+namespace OC
+{
+ // Interface to permit easier mocking/unit testing later
+ class IWrapperFactory
+ {
+ public:
+ typedef std::shared_ptr<IWrapperFactory> Ptr;
+
+ virtual IClientWrapper::Ptr CreateClientWrapper(PlatformConfig cfg) =0;
+ virtual IServerWrapper::Ptr CreateServerWrapper(PlatformConfig cfg) =0;
+ virtual ~IWrapperFactory(){}
+ };
+
+ // Class to create the client/server object!
+ class WrapperFactory : public IWrapperFactory
+ {
+ public:
+ WrapperFactory(){}
+
+ virtual IClientWrapper::Ptr CreateClientWrapper(PlatformConfig cfg)
+ {
+ switch(cfg.serviceType)
+ {
+ case ServiceType::InProc:
+ return std::make_shared<InProcClientWrapper>(cfg);
+ break;
+ case ServiceType::OutOfProc:
+ return std::make_shared<OutOfProcClientWrapper>(cfg);
+ break;
+ }
+ return nullptr;
+ }
+
+ virtual IServerWrapper::Ptr CreateServerWrapper(PlatformConfig cfg)
+ {
+ switch(cfg.serviceType)
+ {
+ case ServiceType::InProc:
+ return std::make_shared<InProcServerWrapper>(cfg);
+ break;
+ case ServiceType::OutOfProc:
+ // return std::make_shared<OutOfProcServerWrapper>(cfg);
+ break;
+ }
+ return nullptr;
+ }
+
+ virtual ~WrapperFactory(){}
+ };
+}
+
+#endif