GTK+ IOStream  Beta
<< GTK+ >> add C++ IOStream operators to GTK+. Now with extra abilities ... like network serialisation
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
ORB.H
Go to the documentation of this file.
1 /* Copyright 2000-2013 Matt Flax <flatmax@flatmax.org>
2  This file is part of GTK+ IOStream class set
3 
4  GTK+ IOStream is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; either version 2 of the License, or
7  (at your option) any later version.
8 
9  GTK+ IOStream is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  GNU General Public License for more details.
13 
14  You have received a copy of the GNU General Public License
15  along with GTK+ IOStream
16  */
17 #ifndef ORB_H_
18 #define ORB_H_
19 
20 #ifndef ZEROC_ICE_EMBEDDED
21 #include <Ice/Ice.h>
22 #include <IceUtil/Mutex.h>
23 #else
24 #include <IceE/IceE.h>
25 #include <IceE/Mutex.h>
26 #endif
27 
28 #include <list>
29 #include <iostream>
30 #include <sstream>
31 #include <vector>
32 using namespace std;
33 
34 #include "ORBICE.H"
35 
36 namespace ORB {
37 
38 #define ORB_DEFAULT_BASEPORT 10000
39 
40 
73 template <class ZEROCICETYPE>
74 class ORBObject : public ZEROCICETYPE {
75 public:
76  const static string name;
77 };
78 
86 class ORBBase {
87  int basePort;
88  IceUtil::Mutex countMutex;
89  list<int> offsetList;
90 
93  void init(int basePortDifferent) {
94  basePort=basePortDifferent;
95  }
96 public:
98  ORBBase(void) {
100  }
101  ORBBase(int basePortDifferent) {
102  init(basePortDifferent);
103  }
107  int getPortOffset(void) {
108  countMutex.lock();
109 
110  int i=-1;
111  if (offsetList.size()>0) {
112  // insert the first missing number
113  offsetList.sort();
114  std::list<int>::iterator offset=offsetList.begin();
115  while (*(offset++)==++i) ; // find the first missing number
116  } else // the list is empty
117  i=0;
118  offsetList.push_back(i); // add the missing number to the list
119 
120  countMutex.unlock();
121  return i;
122  }
123 
127  void removePortOffset(int whichOffset) {
128  countMutex.lock();
129  offsetList.remove(whichOffset);
130  countMutex.unlock();
131  }
132 
137  int getTCPUDPPort(int portOffset) {
138  return basePort+2*portOffset;
139  }
140 
146  int getSSLPort(int portOffset) {
147  return getTCPUDPPort(portOffset)+1;
148  }
149 
154  int getBasePort(void) {
155  return basePort;
156  }
157 
164  string generateEndPoint(const string& transportName, std::string& ipAddress, int& portOffset) {
165  string tn=transportName, ia=ipAddress;
166  int po=portOffset;
167  return generateEndPoint(tn, ia, po);
168  }
169 
176  string generateEndPoint(string &transportName, string ipAddress, int portOffset) {
177  stringstream endPoint;
178  if (ipAddress.size()>0) { // if we are setting up a proxy string
179  ipAddress=string(" -h ")+ipAddress+' ';
180  endPoint<<transportName<<":";
181  }
182  endPoint<<"tcp " <<ipAddress<< "-p "<<getTCPUDPPort(portOffset);
183 #ifndef ZEROC_ICE_EMBEDDED
184  endPoint<<" : udp "<<ipAddress<<"-p "<<getTCPUDPPort(portOffset);
185 #endif
186  cout<<"endpoint :"<<endl;
187  cout<<endPoint.str()<<endl;
188  // currently ssl is not activated ... this can be activated but would require certs
189  //endPoint<<"tcp " <<ipAddress<< "-p "<<getTCPUDPPort(portOffset)<<":udp "<<ipAddress<<"-p "<<getTCPUDPPort(portOffset)<<":ssl "<<ipAddress<<"-p "<<getSSLPort(portOffset); // get the TCP, USP and SSL ports
190  return endPoint.str();
191  }
192 };
193 
207 class ORBOriginator : public ORB::ORBICE, virtual public ORBBase {
208 protected:
210  string hostAddress;
211 
212  string transportName;
213  Ice::CommunicatorPtr communicator;
214  Ice::ObjectAdapterPtr adapterPtr;
215 
222  ORBOriginator(int argc, char *argv[], string transportNameIn, string ipAddress) {
223  initialise(argc, argv, transportNameIn, ipAddress, vector<pair<string,string> >()); // initialise the communicator and adapter
224  }
225 
233  ORBOriginator(int argc, char *argv[], string transportNameIn, string ipAddress, const vector<pair<string,string> > extraProperties) {
234  initialise(argc, argv, transportNameIn, ipAddress, extraProperties); // initialise the communicator and adapter
235  }
236 
244  ORBOriginator(int argc, char *argv[], string transportNameIn, string ipAddress, int basePortDifferent): ORBBase(basePortDifferent) {
245  initialise(argc, argv, transportNameIn, ipAddress, vector<pair<string,string> >()); // initialise the communicator and adapter
246  }
247 
256  ORBOriginator(int argc, char *argv[], string transportNameIn, string ipAddress, const vector<pair<string,string> > extraProperties, int basePortDifferent): ORBBase(basePortDifferent) {
257  initialise(argc, argv, transportNameIn, ipAddress, extraProperties); // initialise the communicator and adapter
258  }
259 
268  void initialise(int argc, char *argv[], string transportNameIn, string ipAddress, const vector<pair<string,string> > extraProperties) {
269  communicator=NULL;
270  hostAddress=ipAddress;
271  portOffset=getPortOffset(); // get a unique port offset
272  transportName=transportNameIn; // set the ZeroC ICE application layer name
273  Ice::InitializationData initData; // generate required initialisation data
274  initData.properties = Ice::createProperties();
275  initData.properties->setProperty("Ice.Warn.Connections", "2");
276  initData.properties->setProperty("Ice.Warn.UnusedProperties", "1");
277  // parse the extra properties
278  for (vector<pair<string,string> >::const_iterator pss=extraProperties.begin(); pss!=extraProperties.end(); ++pss)
279  initData.properties->setProperty(pss->first, pss->second);
280 
281  communicator = Ice::initialize(argc, argv, initData); // create the communicator
282  }
283 
286  void initialiseAdapter(void) {
287  //cout<<"enpoint string "<<generateEndPoint(transportName, string(), portOffset).c_str()<<endl;
288  adapterPtr=communicator->createObjectAdapterWithEndpoints(transportName+".Control",generateEndPoint(transportName, hostAddress, portOffset).c_str());
289  adapterPtr->add((ORB::ORBICE*)this, communicator->stringToIdentity(transportName)); // add this class to the adapter
290  adapterPtr->activate();
291  }
292 
296  void getObjectPointer(const string &name, Ice::ObjectPtr &objectPointer, const Ice::Current& cur) {
297  Ice::Identity identity;
298  identity.name=name;
299  objectPointer=adapterPtr->find(identity);
300  //cout<<"objectPointer = "<<objectPointer<<endl;
301  }
302 
303 public:
311  ORBOriginator(int argc, char *argv[], string transportNameIn) {
312  initialise(argc, argv, transportNameIn, string(), vector<pair<string,string> >()); // initialise the communicator and adapter
313  initialiseAdapter();
314  }
315 
324  ORBOriginator(int argc, char *argv[], string transportNameIn, int basePortDifferent): ORBBase(basePortDifferent) {
325  initialise(argc, argv, transportNameIn, string(), vector<pair<string,string> >()); // initialise the communicator and adapter
326  initialiseAdapter();
327  }
328 
337  ORBOriginator(int argc, char *argv[], string transportNameIn, const vector<pair<string,string> > extraProperties) {
338  initialise(argc, argv, transportNameIn, string(), extraProperties); // initialise the communicator and adapter
339  initialiseAdapter();
340  }
341 
351  ORBOriginator(int argc, char *argv[], string transportNameIn, const vector<pair<string,string> > extraProperties, int basePortDifferent): ORBBase(basePortDifferent) {
352  initialise(argc, argv, transportNameIn, string(), extraProperties); // initialise the communicator and adapter
353  initialiseAdapter();
354  }
355 
357  virtual ~ORBOriginator(void) {
358  removePortOffset(portOffset);
359  if (communicator)
360  communicator->shutdown();
361  }
362 
366  void shutdown(const Ice::Current& cur) {
367  cur.adapter->getCommunicator()->shutdown();
368  }
369 
374  void addClass(Ice::ObjectPtr objectToORB, const string &name) {
375  Ice::Identity identity;
376  identity.name=name;
377  if (adapterPtr->find(identity)) // check whether it already exists
378  cerr<<"ORBOriginator::addClass : WARNING : that class is already serlialised on the adapter"<<endl;
379  adapterPtr->add(objectToORB, identity);
380  }
381 
384  void waitForShutdown(void) {
385  communicator->waitForShutdown();
386  }
387 };
388 
397 class ORBReplicator : public Ice::ObjectFactory, public ORBOriginator {
398  ORB::ORBICEPrx oRBOriginatorPrx;
399 
402  void destroy() {
403  }
404 
408  void initialise(void) {
409  oRBOriginatorPrx = ORB::ORBICEPrx::checkedCast(communicator->stringToProxy(generateEndPoint(transportName, hostAddress, portOffset).c_str())->ice_twoway()->ice_timeout(-1)->ice_secure(false));
410  if (!oRBOriginatorPrx) {
411  cerr<<"ORBReplicator::initialise : couldn't get the ORBOriginator proxy, can't continue \n\n\tPlease check that the intended application on the other side of the netowrk is up and running!"<<endl;
412  assert(false);
413  }
414  }
415 
416 public:
425  ORBReplicator(int argc, char *argv[], string transportNameIn, string ipAddress) : ORBOriginator(argc, argv, transportNameIn, ipAddress) {
426  initialise();
427  }
428 
438  ORBReplicator(int argc, char *argv[], string transportNameIn, string ipAddress, int basePortDifferent) : ORBOriginator(argc, argv, transportNameIn, ipAddress, basePortDifferent) {
439  initialise();
440  }
441 
451  ORBReplicator(int argc, char *argv[], string transportNameIn, string ipAddress, const vector<pair<string,string> > extraProperties) : ORBOriginator(argc, argv, transportNameIn, ipAddress, extraProperties) {
452  initialise();
453  }
454 
465  ORBReplicator(int argc, char *argv[], string transportNameIn, string ipAddress, const vector<pair<string,string> > extraProperties, int basePortDifferent) : ORBOriginator(argc, argv, transportNameIn, ipAddress, extraProperties, basePortDifferent) {
466  initialise();
467  }
468 
472  virtual Ice::ObjectPtr create(const std::string&)=0;
473 
474 // /** Register a class with the object factory.
475 // When required ORBOriginator::create will make the required class.
476 // \param The unique id which identifies the class to create
477 // \tparam ICEIDTYPE The class to get the static id from
478 // */
479 // template<typename ICEIDTYPE>
480 // void addObjectFactory(void) {
481 // communicator->addObjectFactory(static_cast<Ice::ObjectFactory*>(this), ICEIDTYPE::ice_staticId()); // register that the factory can now generate the specified class
482 // }
483 
486  void addClass(Ice::ObjectPtr objectToORB, const string &name) {
487  cerr<<"ORBReplicator::addClass : Only ORBOriginators can add classes to the ORB application layer\n\t You need an originator on this side to add your classes to the ORB application layer"<<endl;
488  }
489 
492  void shutdown(void) {
493  oRBOriginatorPrx->shutdown(); // call the Originator's shutdown method
494  }
495 
502  template<typename PRXTYPE>
503  PRXTYPE getObjectProxy(const string &nameIn) {
504  return PRXTYPE::checkedCast(communicator->stringToProxy(generateEndPoint(nameIn, hostAddress, portOffset).c_str()));
505  }
506 
517  template<typename CLASSTYPE>
518  CLASSTYPE *getObjectPointer(const string &nameIn) {
519  if (!communicator->findObjectFactory(CLASSTYPE::ice_staticId())) // add the object to the factory if it is missing
520  communicator->addObjectFactory(static_cast<Ice::ObjectFactory*>(this), CLASSTYPE::ice_staticId()); // register that the factory can now generate the specified class
521 
522  // request the object from the ORBOriginator, and create it using the factory.
523  Ice::ObjectPtr objectPtr;
524  oRBOriginatorPrx->getObjectPointer(nameIn, objectPtr);
525  objectPtr->__setNoDelete(true); // we have to memory manage ourselves
526  //return PTRTYPE::dynamicCast(objectPtr); // this was used previously to return the pointer
527  return dynamic_cast<CLASSTYPE *>(objectPtr.get());
528  }
529 };
530 
531 };
532 #endif // ORB_H_