From 837cb69583d8be07d5d9bed3739ef75bcfa15da3 Mon Sep 17 00:00:00 2001 From: Luo Jinghua Date: Sat, 26 Nov 2011 18:37:27 +0800 Subject: SexyAppFramework: Added a very simple service resolver --- osframework/source/SexyAppFramework/SConscript | 4 +- .../source/SexyAppFramework/SexyServiceManager.cpp | 362 +++++++++++++++++++++ .../source/SexyAppFramework/SexyServiceManager.h | 77 +++++ 3 files changed, 441 insertions(+), 2 deletions(-) create mode 100644 osframework/source/SexyAppFramework/SexyServiceManager.cpp create mode 100644 osframework/source/SexyAppFramework/SexyServiceManager.h diff --git a/osframework/source/SexyAppFramework/SConscript b/osframework/source/SexyAppFramework/SConscript index 96343a5..b93ff49 100644 --- a/osframework/source/SexyAppFramework/SConscript +++ b/osframework/source/SexyAppFramework/SConscript @@ -35,7 +35,7 @@ srcs = ["Buffer.cpp", "ButtonWidget.cpp", "Checkbox.cpp", 'SexyLang.cpp', 'Find.cpp', 'TextLayout.cpp', 'SexyString.cpp', 'AndroidLogListener.cpp', 'DefaultLogListener.cpp', 'SexyLog.cpp', 'SexyLogListener.cpp', 'SexyLogManager.cpp', 'SelectableWidget.cpp', - 'SexySocket.cpp', 'SimpleUdpLogListener.cpp'] + 'SexySocket.cpp', 'SimpleUdpLogListener.cpp', 'SexyServiceManager.cpp'] ### uniconv srcs += map(lambda f:os.path.join ('uniconv', f), @@ -313,7 +313,7 @@ headers = ['FlashWidget.h', 'Font.h', 'ImageFont.h', 'SexyVector.h', 'NativeFont.h', 'SexyThread.h', 'XMLWriter.h', 'SexyI18n.h', 'SexyLang.h', 'SexyTimer.h', 'Find.h', 'TextLayout.h', 'SexyString.h', 'SelectableWidget.h', - 'SexySocket.h' + 'SexySocket.h', 'SexyServiceManager.h' ] sexyapp_sdk = env.Install (header_dir, headers) diff --git a/osframework/source/SexyAppFramework/SexyServiceManager.cpp b/osframework/source/SexyAppFramework/SexyServiceManager.cpp new file mode 100644 index 0000000..561069c --- /dev/null +++ b/osframework/source/SexyAppFramework/SexyServiceManager.cpp @@ -0,0 +1,362 @@ +#include "SexyServiceManager.h" +#include "Common.h" + +#if defined(WIN32) || defined(_WIN32) +#include +#else +#include +#include +#include +#include +#endif + +#include +#include + +using namespace Sexy; + +static inline char* writel(char *buf, unsigned int l) +{ + buf[0] = l >> 24; + buf[1] = (l >> 16) & 0xff; + buf[2] = (l >> 8) & 0xff; + buf[3] = (l >> 0) & 0xff; + + return buf + 4; +} + +static inline char* writes(char *buf, unsigned short s) +{ + buf[0] = (s >> 8) & 0xff; + buf[1] = (s >> 0) & 0xff; + + return buf + 2; +} + +static inline char* writestr(char *buf, const char* str, unsigned short len) +{ + buf = writes(buf, len); + memcpy(buf, str, len); + return buf + len; +} + +static inline char* readl(char *buf, unsigned int& l) +{ + l = buf[0] << 24 | buf[1] << 16 | + buf[2] << 8 | buf[3]; + + return buf + 4; +} + +static inline char* reads(char *buf, unsigned short& s) +{ + s = buf[2] << 8 | buf[3]; + return buf + 2; +} + +ServiceManager::ServiceManager() +{ + mSock = 0; + mValid = true; + mInitialized = false; + mDone = true; + mCookie = 0; +} + +ServiceManager::~ServiceManager() +{ + release(); +} + +void ServiceManager::release() +{ + if (!mValid) + return; + + mValid = false; + if (mInitialized) + { + mDone = true; + mThread.Join(); + } + mInitialized = false; + delete mSock; + mSock = 0; +} + +ServiceManager& ServiceManager::getInstance() +{ + static ServiceManager mgr; + return mgr; +} + +void ServiceManager::serverProc(void* arg) +{ + ServiceManager* mgr = (ServiceManager*)arg; + mgr->server(); +} + +void ServiceManager::processEchoPacket(char* buf, + int buflen, + const std::string& addr, + unsigned short port) +{ + char outbuf[16]; + char* ptr = outbuf; + + ptr[0] = 'E'; + ptr[1] = 'C'; + ptr[2] = 'R'; + ptr[3] = 'P'; + ptr += 4; + + memcpy(ptr, &buf[4], 4); + ptr += 4; + + ptr = writel(ptr, 4); + ptr = writel(ptr, mCookie); + mSock->sendTo(outbuf, sizeof(outbuf), addr, port); +} + +void ServiceManager::processQueryPacket(char* buf, + int buflen, + const std::string& addr, + unsigned short port) +{ + size_t count = mServiceInfoMap.size(); + if (!count) + { + char outbuf[20]; + char* ptr = outbuf; + + ptr[0] = 'Q'; + ptr[1] = 'R'; + ptr[2] = 'R'; + ptr[3] = 'P'; + ptr += 4; + + memcpy(ptr, &buf[4], 4); + ptr += 4; + + ptr = writel(ptr, 8); + ptr = writel(ptr, mCookie); + ptr = writel(ptr, 0); + + printf("ServiceManager: Sending a query reply packet(max: %d: size: %d) to %s\n", + (int)count, (int)sizeof(outbuf), addr.c_str()); + + mSock->sendTo(outbuf, sizeof(outbuf), addr, port); + return; + } + + char outbuf[512]; + int i = 0; + + ServiceInfoMap::iterator it = mServiceInfoMap.begin(); + + while (it != mServiceInfoMap.end()) + { + ServiceInfo& si = it->second; + + char* ptr = outbuf; + + ptr[0] = 'Q'; + ptr[1] = 'R'; + ptr[2] = 'R'; + ptr[3] = 'P'; + ptr += 4; + + memcpy(ptr, &buf[4], 4); + ptr += 4; + + // skip the payload size; + ptr += 4; + + ptr = writel(ptr, mCookie); + ptr = writel(ptr, count); + ptr = writel(ptr, i); + ptr = writestr(ptr, "name", 4); + ptr = writestr(ptr, si.mName.data(), si.mName.length()); + + ptr = writestr(ptr, "desc", 4); + ptr = writestr(ptr, si.mDesc.data(), si.mDesc.length()); + + ptr = writestr(ptr, "type", 4); + ptr = writestr(ptr, si.mType.data(), si.mType.length()); + + ptr = writestr(ptr, "addr", 4); + ptr = writestr(ptr, si.mAddr.data(), si.mAddr.length()); + + ptr = writestr(ptr, "port", 4); + ptr = writestr(ptr, si.mPort.data(), si.mPort.length()); + + size_t size = ptr - outbuf; + writel(outbuf + 8, size - 12); + + assert(size < sizeof(outbuf)); + + printf("ServiceManager: Sending a query reply packet(max: %d: index:%d size: %d) to %s\n", + (int)count, i, (int)size, addr.c_str()); + + mSock->sendTo(outbuf, size, addr, port); + + i++; + it++; + } +} + +void ServiceManager::processQueryInfoPacket(char* buf, + int buflen, + const std::string& addr, + unsigned short port) +{ + char outbuf[512]; + char* ptr = outbuf; + + ptr[0] = 'Q'; + ptr[1] = 'I'; + ptr[2] = 'R'; + ptr[3] = 'P'; + ptr += 4; + + memcpy(ptr, &buf[4], 4); + ptr += 4; + + ptr += 4; + ptr = writel(ptr, mCookie); + + size_t count = mServiceInfoMap.size(); + ptr = writel(ptr, count); + ptr = writestr(ptr, "name", 4); + ptr = writestr(ptr, mName.data(), mName.length()); + + size_t size = ptr - outbuf; + assert(size < sizeof(outbuf)); + + // payload size + writel(outbuf + 8, size - 12); + + printf("ServiceManager: Sending a query info reply packet(size: %d) to %s\n", + (int)size, addr.c_str()); + + mSock->sendTo(outbuf, size, addr, port); +} + +void ServiceManager::processPacket(char* buf, + int buflen, + const std::string& addr, + unsigned short port) +{ + if (buflen < 12) + return; + + std::string tag(&buf[0], &buf[4]); + + printf ("ServiceManager: Received a packet(%s) from %s.\n", tag.c_str(), addr.c_str()); + + if (tag == "ECHO") + processEchoPacket(buf, buflen, addr, port); + else if (tag == "QURY") + processQueryPacket(buf, buflen, addr, port); + else if (tag == "QRIF") + processQueryInfoPacket(buf, buflen, addr, port); +} + +void ServiceManager::server() +{ + while (!mDone && mSock) + { + int sock = mSock->getSocket(); + + fd_set rfds; + fd_set wfds; + fd_set efds; + + FD_ZERO(&rfds); + FD_SET(sock, &rfds); + FD_ZERO(&efds); + FD_SET(sock, &efds); + FD_ZERO(&wfds); + + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 100000; + + int ret = select(sock + 1, &rfds, &wfds, &efds, &tv); + if (ret < 0 && errno == EINTR) + continue; + if (ret < 0) + break; + + if (!FD_ISSET(sock, &rfds)) + continue; + + char buf[512]; + std::string addr; + unsigned short port; + + ret = mSock->recvFrom(buf, 512, addr, port); + if (ret <= 0) + continue; + processPacket(buf, ret, addr, port); + } +} + +bool ServiceManager::initialize() +{ + if (mInitialized) + return true; + + + mSock = new UDPSocket("", 11053); + if (mSock->hasError()) + { + delete mSock; + mSock = 0; + return false; + } + mSock->joinGroup("224.0.0.251"); + + mDone = false; + mThread = Thread::Create(serverProc, this); + mInitialized = true; + return true; +} + +bool ServiceManager::registerService(const ServiceInfo& info) +{ + if (!mValid || !initialize()) + return true; + + ServiceInfoMap::iterator it = mServiceInfoMap.find(info.mName); + if (it != mServiceInfoMap.end()) + return false; + + const size_t MAX_SIZE = 450; + if (info.mName.length() + info.mType.length() + info.mDesc.length() + + info.mAddr.length() + info.mPort.length() > MAX_SIZE) + return false; + + mServiceInfoMap.insert(ServiceInfoMap::value_type(info.mName, info)); + mCookie++; + return true; +} + +void ServiceManager::unregisterService(const ServiceInfo& info) +{ + if (!mValid) + return; + + + ServiceInfoMap::iterator it = mServiceInfoMap.find(info.mName); + if (it == mServiceInfoMap.end()) + return; + + mServiceInfoMap.erase(it); + mCookie++; +} + +void ServiceManager::setName(const std::string& name) +{ + mName = name; +} diff --git a/osframework/source/SexyAppFramework/SexyServiceManager.h b/osframework/source/SexyAppFramework/SexyServiceManager.h new file mode 100644 index 0000000..e928893 --- /dev/null +++ b/osframework/source/SexyAppFramework/SexyServiceManager.h @@ -0,0 +1,77 @@ +#ifndef __SEXY_SERVICE_MANAGER_H__ +#define __SEXY_SERVICE_MANAGER_H__ + +#include "SexyAppFramework/SexySocket.h" +#include "SexyAppFramework/SexyThread.h" + +#include +#include + +namespace Sexy { + + struct ServiceInfo + { + std::string mName; + std::string mType; + std::string mDesc; + std::string mAddr; + std::string mPort; + }; + + class ServiceManager + { + private: + ServiceManager(); + ServiceManager(const ServiceManager&); + ~ServiceManager(); + + public: + static ServiceManager& getInstance(); + + bool initialize(); + void release(); + bool registerService(const ServiceInfo& info); + void unregisterService(const ServiceInfo& info); + void setName(const std::string& name); + + private: + static void serverProc(void*); + void server(); + + void processEchoPacket(char* buf, + int buflen, + const std::string& addr, + unsigned short port); + + void processQueryPacket(char* buf, + int buflen, + const std::string& addr, + unsigned short port); + + + void processQueryInfoPacket(char* buf, + int buflen, + const std::string& addr, + unsigned short port); + + void processPacket(char* buf, + int buflen, + const std::string& addr, + unsigned short port); + + private: + UDPSocket* mSock; + bool mValid; + bool mInitialized; + bool mDone; + Thread mThread; + unsigned mCookie; + + typedef std::map ServiceInfoMap; + ServiceInfoMap mServiceInfoMap; + + std::string mName; + }; +} + +#endif -- cgit v1.2.3