summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuo Jinghua <sunmoon1997@gmail.com>2011-11-26 18:37:27 +0800
committerLuo Jinghua <sunmoon1997@gmail.com>2011-11-26 18:38:49 +0800
commit837cb69583d8be07d5d9bed3739ef75bcfa15da3 (patch)
tree333e009ac7113843256208e64d48fe81689603b6
parente340dacb3015693cdb30abfe9f4674c1d4f43441 (diff)
SexyAppFramework: Added a very simple service resolver
-rw-r--r--osframework/source/SexyAppFramework/SConscript4
-rw-r--r--osframework/source/SexyAppFramework/SexyServiceManager.cpp362
-rw-r--r--osframework/source/SexyAppFramework/SexyServiceManager.h77
3 files changed, 441 insertions, 2 deletions
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 <winsock.h>
+#else
+#include <sys/select.h>
+#include <sys/time.h>
+#include <sys/types.h>
+#include <unistd.h>
+#endif
+
+#include <errno.h>
+#include <assert.h>
+
+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 <map>
+#include <string>
+
+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<std::string, ServiceInfo> ServiceInfoMap;
+ ServiceInfoMap mServiceInfoMap;
+
+ std::string mName;
+ };
+}
+
+#endif