Commit 0320cf9a authored by jgladish's avatar jgladish

Added AllJoynService, AllJoynProvider

parent ece7c961
#include "AllJoynProvider.h"
#include "AllJoynService.h"
#include <alljoyn/BusAttachment.h>
#include <alljoyn/Init.h>
#include <algorithm>
namespace
{
template<class T>
class IsSamePointer
{
public:
IsSamePointer(T* p) : m_ptr(p) { }
bool operator()(shared_ptr<T> const& rhs)
{ return m_ptr == rhs.get(); }
private:
T* m_ptr;
};
}
void AllJoynProvider::AboutListener::Announced(
char const* serviceName,
uint16_t version,
ajn::SessionPort port,
ajn::MsgArg const& objectDescriptionArg,
ajn::MsgArg const& aboutDataArg)
{
m_parent->AnnounceDiscovery(serviceName, version, port, objectDescriptionArg,
aboutDataArg);
}
AllJoynProvider::AllJoynProvider(std::string const& appname)
: m_bus(NULL)
, m_alljoynInitialized(false)
, m_isRegistered(false)
, m_isListening(false)
, m_applicationName(appname)
, m_aboutListener(NULL)
, m_aboutQueueRun(false)
{
pthread_mutex_init(&m_mutex, NULL);
pthread_cond_init(&m_cond, NULL);
}
AllJoynProvider::~AllJoynProvider()
{
Shutdown();
}
AllJoynStatus AllJoynProvider::Start()
{
QStatus status = ER_OK;
#define AJ_CHECK(ST) { status = ST; if (status != ER_OK) goto leave; }
if (m_bus != NULL)
goto leave;
if (!m_alljoynInitialized)
{
AJ_CHECK( AllJoynInit() );
m_alljoynInitialized = true;
}
m_bus = new ajn::BusAttachment(m_applicationName.c_str(), true);
AJ_CHECK( m_bus->Start() );
AJ_CHECK( m_bus->Connect() );
pthread_create(&m_thread, NULL, RunAboutHandlerProcessing, this);
m_aboutListener = new AboutListener(this);
m_bus->RegisterAboutListener(*m_aboutListener);
m_isRegistered = true;
AJ_CHECK( m_bus->WhoImplements(NULL) );
m_isListening = true;
leave:
if (status != ER_OK)
Shutdown();
return AllJoynStatus(status);
}
void AllJoynProvider::Shutdown()
{
pthread_mutex_lock(&m_mutex);
m_aboutQueueRun = false;
pthread_mutex_unlock(&m_mutex);
pthread_cond_signal(&m_cond);
pthread_join(m_thread, NULL);
if (m_isListening)
{
m_bus->CancelWhoImplements(NULL);
m_isListening = false;
}
if (m_aboutListener)
{
if (m_isRegistered)
{
m_bus->UnregisterAboutListener(*m_aboutListener);
m_isRegistered = false;
}
delete m_aboutListener;
m_aboutListener = NULL;
}
m_servicesVector.clear();
m_servicesMap.clear();
if (m_bus)
{
m_bus->Stop();
m_bus->Join();
delete m_bus;
m_bus = NULL;
}
if (m_alljoynInitialized)
{
AllJoynShutdown();
m_alljoynInitialized = false;
}
}
void AllJoynProvider::ProcessAboutAnnouncementQueue()
{
typedef std::map<std::string, shared_ptr<AllJoynService> > service_map_type;
WorkItem item;
while (true)
{
item.Reset();
pthread_mutex_lock(&m_mutex);
while (m_aboutQueueRun && m_aboutHandlerQueue.empty())
pthread_cond_wait(&m_cond, &m_mutex);
if (m_aboutQueueRun)
{
item = m_aboutHandlerQueue.front();
m_aboutHandlerQueue.pop();
}
pthread_mutex_unlock(&m_mutex);
if (!m_aboutQueueRun)
return;
pthread_mutex_lock(&m_mutex);
service_map_type::iterator itr = m_servicesMap.find(item.ServiceName);
if (itr != m_servicesMap.end())
{
itr->second->Initialize(item.AboutDataArg, item.ObjectDescriptionArg);
}
else
{
shared_ptr<AllJoynService> service(AllJoynService::Create(shared_from_this(), item.ServiceName, item.Port));
m_servicesMap[item.ServiceName] = service;
m_servicesVector.push_back(service);
}
pthread_mutex_unlock(&m_mutex);
}
}
void AllJoynProvider::RemoveSession(shared_ptr<AllJoynService> const& service)
{
// TODO: Does this need to be on another thread?
service_vector_type::iterator itr;
pthread_mutex_lock(&m_mutex);
itr = std::find_if(m_servicesVector.begin(), m_servicesVector.end(), IsSamePointer<AllJoynService>(service.get()));
if (itr != m_servicesVector.end())
m_servicesVector.erase(itr);
m_servicesMap.erase(service->GetName());
pthread_mutex_unlock(&m_mutex);
service->Shutdown();
}
void AllJoynProvider::AnnounceDiscovery(char const* serviceName, uint16_t /*version*/, ajn::SessionPort port,
ajn::MsgArg const& objectDescriptionArg, ajn::MsgArg const& aboutDataArg)
{
pthread_mutex_lock(&m_mutex);
WorkItem item;
item.ObjectDescriptionArg = objectDescriptionArg;
item.AboutDataArg = aboutDataArg;
item.ServiceName = serviceName;
item.Port = port;
m_aboutHandlerQueue.push(item);
pthread_mutex_unlock(&m_mutex);
pthread_cond_signal(&m_cond);
}
#pragma once
#include "defines.h"
#include "AllJoynStatus.h"
#include <alljoyn/AboutListener.h>
#include <map>
#include <string>
#include <vector>
#include <queue>
class AllJoynService;
class AllJoynProvider : enable_shared_from_this<AllJoynProvider>
{
friend class AboutListener;
public:
AllJoynProvider(std::string const& appname);
virtual ~AllJoynProvider();
AllJoynStatus Start();
void Shutdown();
inline ajn::BusAttachment* GetBusAttachment() const
{ return m_bus; }
void RemoveSession(shared_ptr<AllJoynService> const& service);
private:
void AnnounceDiscovery(char const* serviceName, uint16_t version, ajn::SessionPort port,
ajn::MsgArg const& objectDescriptionArg, ajn::MsgArg const& aboutDataArg);
class AboutListener : public ajn::AboutListener
{
public:
AboutListener(AllJoynProvider* provider)
: m_parent(provider) { }
virtual ~AboutListener() { }
virtual void Announced(char const* busName, uint16_t version, ajn::SessionPort port,
ajn::MsgArg const& objectDescriptionArg, ajn::MsgArg const& aboutDataArg);
private:
AllJoynProvider* m_parent;
};
void ProcessAboutAnnouncementQueue();
static void* RunAboutHandlerProcessing(void* argp)
{ ((AllJoynProvider *) argp)->ProcessAboutAnnouncementQueue(); return 0;}
private:
ajn::BusAttachment* m_bus;
bool m_alljoynInitialized;
bool m_isRegistered;
bool m_isListening;
std::string m_applicationName;
AboutListener* m_aboutListener;
struct WorkItem
{
ajn::MsgArg ObjectDescriptionArg;
ajn::MsgArg AboutDataArg;
ajn::SessionPort Port;
std::string ServiceName;
void Reset()
{
ObjectDescriptionArg.Clear();
AboutDataArg.Clear();
Port = 0;
ServiceName.clear();
}
};
bool m_aboutQueueRun;
pthread_t m_thread;
pthread_mutex_t m_mutex;
pthread_cond_t m_cond;
std::queue<WorkItem> m_aboutHandlerQueue;
typedef std::vector< shared_ptr<AllJoynService> > service_vector_type;
typedef std::map< std::string, shared_ptr<AllJoynService> > service_map_type;
service_map_type m_servicesMap;
service_vector_type m_servicesVector;
};
#include "AllJoynService.h"
#include "AllJoynProvider.h"
#include <alljoyn/Session.h>
#include <pthread.h>
AllJoynService::AllJoynService(shared_ptr<AllJoynProvider> const& provider, std::string const& serviceName, ajn::SessionPort port)
: m_provider(provider)
, m_name(serviceName)
, m_sessionPort(port)
, m_sessionListener(NULL)
{
pthread_mutex_init(&m_mutex, NULL);
m_sessionListener = new SessionListener(this);
ajn::SessionOpts sessionOpts(ajn::SessionOpts::TRAFFIC_MESSAGES, false, ajn::SessionOpts::PROXIMITY_ANY,
ajn::TRANSPORT_ANY);
ajn::BusAttachment* bus = GetProvider()->GetBusAttachment();
if (bus)
{
bus->JoinSession(m_name.c_str(), m_sessionPort, m_sessionListener, m_sessionId,
sessionOpts);
}
}
AllJoynService::~AllJoynService()
{
Shutdown();
}
void AllJoynService::Initialize(ajn::MsgArg const& aboutDataArg, ajn::MsgArg const& objectDescriptionArg)
{
m_aboutDataArg = aboutDataArg;
m_objectDescriptionArg = objectDescriptionArg;
}
void AllJoynService::Shutdown()
{
if (m_sessionId != 0)
{
ajn::BusAttachment* bus = GetProvider()->GetBusAttachment();
if (bus)
bus->LeaveSession(m_sessionId);
m_sessionId = 0;
}
if (m_sessionListener)
{
delete m_sessionListener;
m_sessionListener = NULL;
}
pthread_mutex_lock(&m_mutex);
m_objectsMap.clear();
pthread_mutex_unlock(&m_mutex);
}
shared_ptr<AllJoynBusObject> AllJoynService::GetBusObject(std::string const& path)
{
shared_ptr<AllJoynBusObject> busObject;
pthread_mutex_lock(&m_mutex);
object_map_type::iterator itr = m_objectsMap.find(path);
if (itr != m_objectsMap.end())
{
busObject = itr->second.lock();
if (busObject)
m_objectsMap.erase(itr);
}
pthread_mutex_unlock(&m_mutex);
return busObject;
}
ajn::BusAttachment* AllJoynService::GetBusAttachment() const
{
return GetProvider()->GetBusAttachment();
}
void AllJoynService::OnSessionLost(ajn::SessionId /*sessionId*/, ajn::SessionListener::SessionLostReason /*reason*/)
{
shared_ptr<AllJoynProvider> provider = GetProvider();
if (provider)
{
provider->RemoveSession(shared_from_this());
}
}
void AllJoynService::OnSessionMemberAdded(ajn::SessionId /*sessionId*/, char const* /*uniqueName*/)
{
}
void AllJoynService::OnSessionMemberRemoved(ajn::SessionId /*sessionId*/, char const* /*uniqueName*/)
{
}
void AllJoynService::SessionListener::SessionLost(ajn::SessionId sessionId, ajn::SessionListener::SessionLostReason reason)
{
m_parent->OnSessionLost(sessionId, reason);
}
void AllJoynService::SessionListener::SessionMemberAdded(ajn::SessionId sessionId, char const* uniqueName)
{
m_parent->OnSessionMemberAdded(sessionId, uniqueName);
}
void AllJoynService::SessionListener::SessionMemberRemoved(ajn::SessionId sessionId, char const* uniqueName)
{
m_parent->OnSessionMemberRemoved(sessionId, uniqueName);
}
#pragma once
#include "defines.h"
#include <alljoyn/BusAttachment.h>
#include <alljoyn/ProxyBusObject.h>
#include <alljoyn/SessionListener.h>
#include <map>
class AllJoynBusObject;
class AllJoynProvider;
class AllJoynService : public enable_shared_from_this<AllJoynService>
{
public:
static shared_ptr<AllJoynService> Create(shared_ptr<AllJoynProvider> const& provider,
std::string const& serviceName, ajn::SessionPort port)
{
return shared_ptr<AllJoynService>(new AllJoynService(provider, serviceName, port));
}
public:
AllJoynService(shared_ptr<AllJoynProvider> const& provider, std::string const& serviceName, ajn::SessionPort port);
~AllJoynService();
void Initialize(ajn::MsgArg const& aboutDataArg, ajn::MsgArg const& objectDescriptionArg);
void Shutdown();
shared_ptr<AllJoynBusObject> GetBusObject(std::string const& path);
shared_ptr<AllJoynProvider> GetProvider() const
{ return m_provider.lock(); }
ajn::BusAttachment* GetBusAttachment() const;
inline ajn::SessionId GetSessionId() const
{ return m_sessionId; }
inline std::string GetName() const
{ return m_name; }
inline uint16_t GetSessionPort() const
{ return m_sessionPort; }
private:
class SessionListener : public ajn::SessionListener
{
public:
SessionListener(AllJoynService* parent)
: m_parent(parent) { }
virtual ~SessionListener() { }
virtual void SessionLost(ajn::SessionId sessionId, SessionLostReason reason);
virtual void SessionMemberAdded(ajn::SessionId sessionId, char const* uniqueName);
virtual void SessionMemberRemoved(ajn::SessionId sessionId, char const* uniqueName);
private:
AllJoynService* m_parent;
};
void ParseObjectData();
void OnSessionLost(ajn::SessionId sessionId, ajn::SessionListener::SessionLostReason reason);
void OnSessionMemberAdded(ajn::SessionId sessionId, char const* uniqueName);
void OnSessionMemberRemoved(ajn::SessionId sessionId, char const* uniqueName);
private:
typedef std::map<std::string, weak_ptr<AllJoynBusObject> > object_map_type;
weak_ptr<AllJoynProvider> m_provider;
std::string m_name;
ajn::SessionPort m_sessionPort;
shared_ptr<AllJoynBusObject> m_busObject;
ajn::SessionId m_sessionId;
object_map_type m_objectsMap;
pthread_mutex_t m_mutex;
SessionListener* m_sessionListener;
ajn::MsgArg m_aboutDataArg;
ajn::MsgArg m_objectDescriptionArg;
};
#pragma once
#include <string>
#include <alljoyn/Status.h>
class AllJoynStatus
{
public:
AllJoynStatus(QStatus statusCode)
: m_statusCode(statusCode)
{ }
inline QStatus GetCode() const
{ return m_statusCode; }
inline std::string GetText() const
{ return QCC_StatusText(m_statusCode); }
inline bool IsSuccess() const
{ return m_statusCode == QStatus::ER_OK; }
inline bool IsFailure() const
{ return m_statusCode != QStatus::ER_OK; }
private:
QStatus m_statusCode;
};
SRCS=AllJoynProvider.cpp \
AllJoynService.cpp \
dsb.cpp
ALLJOYN_INSTALL_DIR=/Users/jgladi200/Work/alljoyn/alljoyn-15.04.00-src/build/darwin/x86/debug/dist/cpp
CXXFLAGS=-Wall -Wextra -g -std=c++0x -I$(ALLJOYN_INSTALL_DIR)/inc
LDFLAGS=-L $(ALLJOYN_INSTALL_DIR)/lib -lalljoyn -lcrypto
OBJS=$(patsubst %.cpp,%.o,$(SRCS))
all: dsb
clean:
$(RM) dsb core *.o
dsb: $(OBJS)
$(CXX) -o $@ $^ $(LDFLAGS)
#pragma once
#ifdef __APPLE__
#define QCC_OS_GROUP_POSIX
#include <memory>
using std::shared_ptr;
using std::weak_ptr;
using std::enable_shared_from_this;
#else
#include <tr1/memory>
using std::tr1::shared_ptr;
using std::tr1::weak_ptr;
using std::tr1::enable_shared_from_this;
#endif
class AllJoynBusObject;
#include "AllJoynProvider.h"
#include "AllJoynService.h"
#include "AllJoynStatus.h"
int main(int /*argc*/, char* /*argv*/[])
{
return 0;
}
# portabledsb
A portable c++ version of the AllJoyn DSB
https://git.allseenalliance.org/cgit/dsb.git/
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment