Skip to content

Instantly share code, notes, and snippets.

@j0sh
Created January 6, 2012 05:59
Show Gist options
  • Select an option

  • Save j0sh/1569246 to your computer and use it in GitHub Desktop.

Select an option

Save j0sh/1569246 to your computer and use it in GitHub Desktop.
Add to protocol factory at runtime.
From 884e6614fbe3dffec655ca6f24ced224bc25cb43 Mon Sep 17 00:00:00 2001
From: Josh Allmann <joshua.allmann@gmail.com>
Date: Wed, 11 Jan 2012 00:39:48 -0800
Subject: [PATCH 0/2] BaseProtocolFactory simplifications
This patchset removes the need to subclass BaseProtocolFactory.
Protocols can now be added to a factory instance at runtime
before being registered with the factory manager. This greatly
reduces the amount of boilerplate needed to add new protocols.
Josh Allmann (2):
Make BaseProtocolFactory non-abstract and modifiable at runtime.
Convert samplefactory to use simplified protocol factory.
.../samplefactory/include/protocolfactory.h | 44 ---------
.../samplefactory/src/protocolfactory.cpp | 95 --------------------
.../samplefactory/src/samplefactory.cpp | 17 +++-
.../thelib/include/protocols/baseprotocolfactory.h | 27 +++++-
.../thelib/src/protocols/baseprotocolfactory.cpp | 46 ++++++++++
5 files changed, 84 insertions(+), 145 deletions(-)
delete mode 100644 sources/applications/samplefactory/include/protocolfactory.h
delete mode 100644 sources/applications/samplefactory/src/protocolfactory.cpp
--
1.7.5.4
From 6c04576a2685d922778b8dd268cadcc31f236421 Mon Sep 17 00:00:00 2001
From: Josh Allmann <joshua.allmann@gmail.com>
Date: Wed, 11 Jan 2012 00:34:16 -0800
Subject: [PATCH 1/2] Make BaseProtocolFactory non-abstract and modifiable at
runtime.
---
.../thelib/include/protocols/baseprotocolfactory.h | 27 ++++++++++--
.../thelib/src/protocols/baseprotocolfactory.cpp | 46 ++++++++++++++++++++
2 files changed, 69 insertions(+), 4 deletions(-)
diff --git a/sources/thelib/include/protocols/baseprotocolfactory.h b/sources/thelib/include/protocols/baseprotocolfactory.h
index bcb0c0c..2cdf4d9 100644
--- a/sources/thelib/include/protocols/baseprotocolfactory.h
+++ b/sources/thelib/include/protocols/baseprotocolfactory.h
@@ -23,6 +23,11 @@
#include "common.h"
+#define PROTOCOL_CONSTRUCTOR(type) \
+ static BaseProtocol* new_##type() { \
+ return new type(); \
+ }
+
class BaseProtocol;
/*!
@@ -33,6 +38,10 @@ class DLLEXP BaseProtocolFactory {
private:
static uint32_t _idGenerator;
uint32_t _id;
+
+ typedef BaseProtocol*(*ConstructorType)();
+ map<string, vector<uint64_t> > _protocols;
+ map<uint64_t, ConstructorType> _constructors;
public:
/*!
@brief Constructor: Increments the _idGenerator parameter.
@@ -48,22 +57,32 @@ public:
/*!
@brief Function that will contain all the protocols that will be handled by the factory.
*/
- virtual vector<uint64_t> HandledProtocols() = 0;
+ virtual vector<uint64_t> HandledProtocols();
/*!
@brief Function that will contain all the protocol chains that will be handled by the factory.
*/
- virtual vector<string> HandledProtocolChains() = 0;
+ virtual vector<string> HandledProtocolChains();
/*!
@brief This functions is where the protocol chains whose names are all defined, are resolved.
@param name: The name given to the protocol chain.
*/
- virtual vector<uint64_t> ResolveProtocolChain(string name) = 0;
+ virtual vector<uint64_t> ResolveProtocolChain(string name);
/*!
@brief This function is where protocols are spawned.
@param type: The protocol to be spawned.
@param parameters: Each protocol can have parameters. This is optional.
*/
- virtual BaseProtocol *SpawnProtocol(uint64_t type, Variant &parameters) = 0;
+ virtual BaseProtocol *SpawnProtocol(uint64_t type, Variant &parameters);
+
+ /*!
+ @brief Add a new protocol to the factory.
+ @param name: Name of the protocol.
+ @param constructor: Function returning an instance of the protocol.
+ @param chain_length number of levels in the protocol chain.
+ @param varargs The protocol chain proper, uint64_t typesd.
+ */
+ virtual void AddProtocol(const string &name, BaseProtocol*(*constructor)(), int chain_length, ...);
+
};
#endif /* _BASEPROTOCOLFACTORY_H */
diff --git a/sources/thelib/src/protocols/baseprotocolfactory.cpp b/sources/thelib/src/protocols/baseprotocolfactory.cpp
index 180b8dd..dfd6e2f 100644
--- a/sources/thelib/src/protocols/baseprotocolfactory.cpp
+++ b/sources/thelib/src/protocols/baseprotocolfactory.cpp
@@ -18,6 +18,7 @@
*/
#include "protocols/baseprotocolfactory.h"
+#include "protocols/baseprotocol.h"
uint32_t BaseProtocolFactory::_idGenerator = 0;
@@ -32,4 +33,49 @@ uint32_t BaseProtocolFactory::GetId() {
return _id;
}
+vector<uint64_t> BaseProtocolFactory::HandledProtocols() {
+ vector<uint64_t> result;
+ FOR_MAP(_constructors, uint64_t, ConstructorType, i) {
+ ADD_VECTOR_END(result, MAP_KEY(i));
+ }
+ return result;
+}
+
+vector<string> BaseProtocolFactory::HandledProtocolChains() {
+ vector<string> result;
+ FOR_MAP(_protocols, string, vector<uint64_t>, i) {
+ ADD_VECTOR_END(result, MAP_KEY(i));
+ }
+ return result;
+}
+
+vector<uint64_t> BaseProtocolFactory::ResolveProtocolChain(string name) {
+ if (MAP_HAS1(_protocols, name)) {
+ return _protocols[name];
+ }
+ vector<uint64_t> result;
+ return result;
+}
+BaseProtocol* BaseProtocolFactory::SpawnProtocol(uint64_t type, Variant &parameters)
+{
+ if (MAP_HAS1(_constructors, type)) return _constructors[type]();
+ return NULL;
+}
+
+void BaseProtocolFactory::AddProtocol(const string &name,
+ BaseProtocol* (*constructor)(), int chain_length, ...) {
+ if (name.size() == 0 || chain_length <= 0) return;
+
+ va_list args;
+ va_start(args, chain_length);
+ vector<uint64_t> chain;
+ uint64_t type;
+ for (int i = 0; i < chain_length; i++) {
+ type = va_arg(args, uint64_t);
+ ADD_VECTOR_END(chain, type);
+ }
+ va_end(args);
+ _protocols[name] = chain;
+ _constructors[type] = constructor;
+}
--
1.7.5.4
From 987dee886cb39e7050f97b41e549dca77ba2dfff Mon Sep 17 00:00:00 2001
From: Josh Allmann <joshua.allmann@gmail.com>
Date: Wed, 11 Jan 2012 00:37:36 -0800
Subject: [PATCH 2/2] Convert samplefactory to use simplified protocol
factory.
---
.../samplefactory/include/protocolfactory.h | 44 ---------
.../samplefactory/src/protocolfactory.cpp | 95 --------------------
.../samplefactory/src/samplefactory.cpp | 17 +++-
.../samplefactory/src/samplefactoryapplication.cpp | 1 -
4 files changed, 15 insertions(+), 142 deletions(-)
delete mode 100644 sources/applications/samplefactory/include/protocolfactory.h
delete mode 100644 sources/applications/samplefactory/src/protocolfactory.cpp
diff --git a/sources/applications/samplefactory/include/protocolfactory.h b/sources/applications/samplefactory/include/protocolfactory.h
deleted file mode 100644
index 163e0e7..0000000
--- a/sources/applications/samplefactory/include/protocolfactory.h
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Copyright (c) 2010,
- * Gavriloaie Eugen-Andrei (shiretu@gmail.com)
- *
- * This file is part of crtmpserver.
- * crtmpserver 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 3 of the License, or
- * (at your option) any later version.
- *
- * crtmpserver 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 crtmpserver. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#ifndef _PROTOCOLFACTORY_H
-#define _PROTOCOLFACTORY_H
-
-#include "protocols/baseprotocolfactory.h"
-#include "protocols/protocoltypes.h"
-
-namespace app_samplefactory {
-
- class DLLEXP ProtocolFactory
- : public BaseProtocolFactory {
- public:
- ProtocolFactory();
- virtual ~ProtocolFactory();
-
- virtual vector<uint64_t> HandledProtocols();
- virtual vector<string> HandledProtocolChains();
- virtual vector<uint64_t> ResolveProtocolChain(string name);
- virtual BaseProtocol *SpawnProtocol(uint64_t type, Variant &parameters);
- };
-}
-
-#endif /* _PROTOCOLFACTORY_H */
-
-
diff --git a/sources/applications/samplefactory/src/protocolfactory.cpp b/sources/applications/samplefactory/src/protocolfactory.cpp
deleted file mode 100644
index a30a90a..0000000
--- a/sources/applications/samplefactory/src/protocolfactory.cpp
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- * Copyright (c) 2010,
- * Gavriloaie Eugen-Andrei (shiretu@gmail.com)
- *
- * This file is part of crtmpserver.
- * crtmpserver 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 3 of the License, or
- * (at your option) any later version.
- *
- * crtmpserver 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 crtmpserver. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "protocolfactory.h"
-#include "protocols/baseprotocol.h"
-#include "localdefines.h"
-#include "echoprotocol.h"
-#include "httpdownloadprotocol.h"
-using namespace app_samplefactory;
-
-ProtocolFactory::ProtocolFactory() {
-
-}
-
-ProtocolFactory::~ProtocolFactory() {
-}
-
-vector<uint64_t> ProtocolFactory::HandledProtocols() {
- vector<uint64_t> result;
- ADD_VECTOR_END(result, PT_ECHO_PROTOCOL);
- ADD_VECTOR_END(result, PT_HTTP_DOWNLOAD_PROTOCOL);
- return result;
-}
-
-vector<string> ProtocolFactory::HandledProtocolChains() {
- vector<string> result;
- ADD_VECTOR_END(result, "echoProtocol");
- ADD_VECTOR_END(result, "httpEchoProtocol");
- ADD_VECTOR_END(result, "httpDownload");
- return result;
-}
-
-vector<uint64_t> ProtocolFactory::ResolveProtocolChain(string name) {
- vector<uint64_t> result;
- if (name == "echoProtocol") {
- ADD_VECTOR_END(result, PT_TCP);
- ADD_VECTOR_END(result, PT_ECHO_PROTOCOL);
- } else if (name == "httpEchoProtocol") {
- ADD_VECTOR_END(result, PT_TCP);
- ADD_VECTOR_END(result, PT_INBOUND_HTTP);
- ADD_VECTOR_END(result, PT_ECHO_PROTOCOL);
- } else if (name == "httpDownload") {
- ADD_VECTOR_END(result, PT_TCP);
- ADD_VECTOR_END(result, PT_OUTBOUND_HTTP);
- ADD_VECTOR_END(result, PT_HTTP_DOWNLOAD_PROTOCOL);
- } else {
- ASSERT("This protocol stack should not land here");
- }
- return result;
-}
-
-BaseProtocol *ProtocolFactory::SpawnProtocol(uint64_t type, Variant &parameters) {
- BaseProtocol *pResult = NULL;
- switch (type) {
- case PT_ECHO_PROTOCOL:
- pResult = new EchoProtocol();
- break;
- case PT_HTTP_DOWNLOAD_PROTOCOL:
- pResult = new HTTPDownloadProtocol();
- break;
- default:
- FATAL("Spawning protocol %s not yet implemented",
- STR(tagToString(type)));
- break;
- }
-
- if (pResult != NULL) {
- if (!pResult->Initialize(parameters)) {
- FATAL("Unable to initialize protocol %s",
- STR(tagToString(type)));
- delete pResult;
- pResult = NULL;
- }
- }
-
- return pResult;
-}
-
diff --git a/sources/applications/samplefactory/src/samplefactory.cpp b/sources/applications/samplefactory/src/samplefactory.cpp
index a576f2e..6d2ba66 100644
--- a/sources/applications/samplefactory/src/samplefactory.cpp
+++ b/sources/applications/samplefactory/src/samplefactory.cpp
@@ -18,17 +18,30 @@
*/
#include "application/baseclientapplication.h"
+#include "protocols/baseprotocolfactory.h"
#include "samplefactory.h"
#include "samplefactoryapplication.h"
-#include "protocolfactory.h"
+#include "echoprotocol.h"
+#include "httpdownloadprotocol.h"
+#include "localdefines.h"
using namespace app_samplefactory;
+PROTOCOL_CONSTRUCTOR(EchoProtocol)
+PROTOCOL_CONSTRUCTOR(HTTPDownloadProtocol)
+
extern "C" BaseClientApplication *GetApplication_samplefactory(Variant configuration) {
return new SampleFactoryApplication(
configuration);
}
extern "C" DLLEXP BaseProtocolFactory *GetFactory_samplefactory(Variant configuration) {
- return new ProtocolFactory();
+ BaseProtocolFactory *f = new BaseProtocolFactory();
+ f->AddProtocol("echoProtocol", new_EchoProtocol, 2,
+ PT_TCP, PT_ECHO_PROTOCOL);
+ f->AddProtocol("httpEchoProtocol", new_EchoProtocol, 3,
+ PT_TCP, PT_INBOUND_HTTP, PT_ECHO_PROTOCOL);
+ f->AddProtocol("httpDownload", new_HTTPDownloadProtocol, 3,
+ PT_TCP, PT_OUTBOUND_HTTP, PT_HTTP_DOWNLOAD_PROTOCOL);
+ return f;
}
diff --git a/sources/applications/samplefactory/src/samplefactoryapplication.cpp b/sources/applications/samplefactory/src/samplefactoryapplication.cpp
index 074f591..01c9c8a 100644
--- a/sources/applications/samplefactory/src/samplefactoryapplication.cpp
+++ b/sources/applications/samplefactory/src/samplefactoryapplication.cpp
@@ -20,7 +20,6 @@
#include "samplefactoryapplication.h"
#include "protocols/baseprotocol.h"
-#include "protocolfactory.h"
#include "protocols/protocolfactorymanager.h"
#include "localdefines.h"
#include "echoappprotocolhandler.h"
--
1.7.5.4
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment