1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <IceUtil/DisableWarnings.h>
6 #include <Communicator.h>
7 #include <BatchRequestInterceptor.h>
8 #include <Dispatcher.h>
9 #include <ImplicitContext.h>
10 #include <Logger.h>
11 #include <ObjectAdapter.h>
12 #include <Operation.h>
13 #include <Properties.h>
14 #include <PropertiesAdmin.h>
15 #include <Proxy.h>
16 #include <Thread.h>
17 #include <Types.h>
18 #include <Util.h>
19 #include <ValueFactoryManager.h>
20 #include <Ice/ValueFactory.h>
21 #include <Ice/Initialize.h>
22 #include <Ice/CommunicatorAsync.h>
23 #include <Ice/LocalException.h>
24 #include <Ice/Locator.h>
25 #include <Ice/ObjectAdapter.h>
26 #include <Ice/Properties.h>
27 #include <Ice/Router.h>
28 
29 #include <pythread.h>
30 
31 using namespace std;
32 using namespace IcePy;
33 
34 #if defined(__GNUC__) && ((__GNUC__ >= 8))
35 #   pragma GCC diagnostic ignored "-Wcast-function-type"
36 #endif
37 
38 #if PY_VERSION_HEX < 0x03070000
39 static long _mainThreadId;
40 #else
41 static unsigned long _mainThreadId;
42 #endif
43 
44 typedef map<Ice::CommunicatorPtr, PyObject*> CommunicatorMap;
45 static CommunicatorMap _communicatorMap;
46 
47 namespace IcePy
48 {
49 
50 struct CommunicatorObject;
51 
52 typedef InvokeThread<Ice::Communicator> WaitForShutdownThread;
53 typedef IceUtil::Handle<WaitForShutdownThread> WaitForShutdownThreadPtr;
54 
55 struct CommunicatorObject
56 {
57     PyObject_HEAD
58     Ice::CommunicatorPtr* communicator;
59     PyObject* wrapper;
60     IceUtil::Monitor<IceUtil::Mutex>* shutdownMonitor;
61     WaitForShutdownThreadPtr* shutdownThread;
62     bool shutdown;
63     DispatcherPtr* dispatcher;
64 };
65 
66 }
67 
68 #ifdef WIN32
69 extern "C"
70 #endif
71 static CommunicatorObject*
communicatorNew(PyTypeObject * type,PyObject *,PyObject *)72 communicatorNew(PyTypeObject* type, PyObject* /*args*/, PyObject* /*kwds*/)
73 {
74     assert(type && type->tp_alloc);
75     CommunicatorObject* self = reinterpret_cast<CommunicatorObject*>(type->tp_alloc(type, 0));
76     if(!self)
77     {
78         return 0;
79     }
80     self->communicator = 0;
81     self->wrapper = 0;
82     self->shutdownMonitor = new IceUtil::Monitor<IceUtil::Mutex>;
83     self->shutdownThread = 0;
84     self->shutdown = false;
85     self->dispatcher = 0;
86     return self;
87 }
88 
89 #ifdef WIN32
90 extern "C"
91 #endif
92 static int
communicatorInit(CommunicatorObject * self,PyObject * args,PyObject *)93 communicatorInit(CommunicatorObject* self, PyObject* args, PyObject* /*kwds*/)
94 {
95     //
96     // The argument options are:
97     //
98     // Ice.initialize()
99     // Ice.initialize(args)
100     // Ice.initialize(initData)
101     // Ice.initialize(configFile)
102     // Ice.initialize(args, initData)
103     // Ice.initialize(args, configFile)
104     //
105 
106     PyObject* arg1 = 0;
107     PyObject* arg2 = 0;
108     if(!PyArg_ParseTuple(args, STRCAST("|OO"), &arg1, &arg2))
109     {
110         return -1;
111     }
112 
113     PyObject* argList = 0;
114     PyObject* initData = 0;
115     PyObject* configFile = 0;
116 
117     if(arg1 == Py_None)
118     {
119         arg1 = 0;
120     }
121 
122     if(arg2 == Py_None)
123     {
124         arg2 = 0;
125     }
126 
127     PyObject* initDataType = lookupType("Ice.InitializationData");
128 
129     if(arg1)
130     {
131         if(PyList_Check(arg1))
132         {
133             argList = arg1;
134         }
135         else if(PyObject_IsInstance(arg1, initDataType))
136         {
137             initData = arg1;
138         }
139         else if(checkString(arg1))
140         {
141             configFile = arg1;
142         }
143         else
144         {
145             PyErr_Format(PyExc_ValueError,
146                 STRCAST("initialize expects an argument list, Ice.InitializationData or a configuration filename"));
147             return -1;
148         }
149     }
150 
151     if(arg2)
152     {
153         if(PyList_Check(arg2))
154         {
155             if(argList)
156             {
157                 PyErr_Format(PyExc_ValueError, STRCAST("unexpected list argument to initialize"));
158                 return -1;
159             }
160             argList = arg2;
161         }
162         else if(PyObject_IsInstance(arg2, initDataType))
163         {
164             if(initData)
165             {
166                 PyErr_Format(PyExc_ValueError, STRCAST("unexpected Ice.InitializationData argument to initialize"));
167                 return -1;
168             }
169             initData = arg2;
170         }
171         else if(checkString(arg2))
172         {
173             if(configFile)
174             {
175                 PyErr_Format(PyExc_ValueError, STRCAST("unexpected string argument to initialize"));
176                 return -1;
177             }
178             configFile = arg2;
179         }
180         else
181         {
182             PyErr_Format(PyExc_ValueError,
183                 STRCAST("initialize expects an argument list, Ice.InitializationData or a configuration filename"));
184             return -1;
185         }
186     }
187 
188     if(initData && configFile)
189     {
190         PyErr_Format(PyExc_ValueError,
191             STRCAST("initialize accepts either Ice.InitializationData or a configuration filename"));
192         return -1;
193     }
194 
195     Ice::StringSeq seq;
196     if(argList && !listToStringSeq(argList, seq))
197     {
198         return -1;
199     }
200 
201     Ice::InitializationData data;
202     DispatcherPtr dispatcherWrapper;
203 
204     try
205     {
206         if(initData)
207         {
208             PyObjectHandle properties = getAttr(initData, "properties", false);
209             PyObjectHandle logger = getAttr(initData, "logger", false);
210             PyObjectHandle threadHook = getAttr(initData, "threadHook", false);
211             PyObjectHandle threadStart = getAttr(initData, "threadStart", false);
212             PyObjectHandle threadStop = getAttr(initData, "threadStop", false);
213             PyObjectHandle batchRequestInterceptor = getAttr(initData, "batchRequestInterceptor", false);
214             PyObjectHandle dispatcher = getAttr(initData, "dispatcher", false);
215 
216             if(properties.get())
217             {
218                 //
219                 // Get the properties implementation.
220                 //
221                 PyObjectHandle impl = getAttr(properties.get(), "_impl", false);
222                 assert(impl.get());
223                 data.properties = getProperties(impl.get());
224             }
225 
226             if(logger.get())
227             {
228                 data.logger = new LoggerWrapper(logger.get());
229             }
230 
231             if(threadHook.get() || threadStart.get() || threadStop.get())
232             {
233                 data.threadHook = new ThreadHook(threadHook.get(), threadStart.get(), threadStop.get());
234             }
235 
236             if(dispatcher.get())
237             {
238                 dispatcherWrapper = new Dispatcher(dispatcher.get());
239                 data.dispatcher = dispatcherWrapper;
240             }
241 
242             if(batchRequestInterceptor.get())
243             {
244                 data.batchRequestInterceptor = new BatchRequestInterceptor(batchRequestInterceptor.get());
245             }
246         }
247 
248         //
249         // We always supply our own implementation of ValueFactoryManager.
250         //
251         data.valueFactoryManager = new ValueFactoryManager;
252 
253         if(!data.properties)
254         {
255             data.properties = Ice::createProperties();
256         }
257 
258         if(configFile)
259         {
260             data.properties->load(getString(configFile));
261         }
262 
263         if(argList)
264         {
265             data.properties = Ice::createProperties(seq, data.properties);
266         }
267     }
268     catch(const Ice::Exception& ex)
269     {
270         setPythonException(ex);
271         return -1;
272     }
273 
274     //
275     // Remaining command line options are passed to the communicator
276     // as an argument vector in case they contain plug-in properties.
277     //
278     int argc = static_cast<int>(seq.size());
279     char** argv = new char*[argc + 1];
280     int i = 0;
281     for(Ice::StringSeq::const_iterator s = seq.begin(); s != seq.end(); ++s, ++i)
282     {
283         argv[i] = strdup(s->c_str());
284     }
285     argv[argc] = 0;
286 
287     data.compactIdResolver = new IdResolver;
288 
289     Ice::CommunicatorPtr communicator;
290     try
291     {
292         AllowThreads allowThreads;
293         if(argList)
294         {
295             communicator = Ice::initialize(argc, argv, data);
296         }
297         else
298         {
299             communicator = Ice::initialize(data);
300         }
301     }
302     catch(const Ice::Exception& ex)
303     {
304         for(i = 0; i < argc; ++i)
305         {
306             free(argv[i]);
307         }
308         delete[] argv;
309 
310         setPythonException(ex);
311         return -1;
312     }
313 
314     //
315     // Replace the contents of the given argument list with the filtered arguments.
316     //
317     if(argList)
318     {
319         PyList_SetSlice(argList, 0, PyList_Size(argList), 0); // Clear the list.
320 
321         for(i = 0; i < argc; ++i)
322         {
323             PyObjectHandle str = Py_BuildValue(STRCAST("s"), argv[i]);
324             PyList_Append(argList, str.get());
325         }
326     }
327 
328     for(i = 0; i < argc; ++i)
329     {
330         free(argv[i]);
331     }
332     delete[] argv;
333 
334     self->communicator = new Ice::CommunicatorPtr(communicator);
335 
336     CommunicatorMap::iterator p = _communicatorMap.find(communicator);
337     if(p != _communicatorMap.end())
338     {
339         _communicatorMap.erase(p);
340     }
341     _communicatorMap.insert(CommunicatorMap::value_type(communicator, reinterpret_cast<PyObject*>(self)));
342 
343     if(dispatcherWrapper)
344     {
345         self->dispatcher = new DispatcherPtr(dispatcherWrapper);
346         dispatcherWrapper->setCommunicator(communicator);
347     }
348 
349     return 0;
350 }
351 
352 #ifdef WIN32
353 extern "C"
354 #endif
355 static void
communicatorDealloc(CommunicatorObject * self)356 communicatorDealloc(CommunicatorObject* self)
357 {
358     if(self->communicator)
359     {
360         CommunicatorMap::iterator p = _communicatorMap.find(*self->communicator);
361         //
362         // find() can fail if an error occurred during communicator initialization.
363         //
364         if(p != _communicatorMap.end())
365         {
366             _communicatorMap.erase(p);
367         }
368     }
369 
370     if(self->shutdownThread)
371     {
372         (*self->shutdownThread)->getThreadControl().join();
373     }
374     delete self->communicator;
375     delete self->shutdownMonitor;
376     delete self->shutdownThread;
377     Py_TYPE(self)->tp_free(reinterpret_cast<PyObject*>(self));
378 }
379 
380 #ifdef WIN32
381 extern "C"
382 #endif
383 static PyObject*
communicatorDestroy(CommunicatorObject * self,PyObject *)384 communicatorDestroy(CommunicatorObject* self, PyObject* /*args*/)
385 {
386     assert(self->communicator);
387 
388     ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast((*self->communicator)->getValueFactoryManager());
389     assert(vfm);
390 
391     try
392     {
393         AllowThreads allowThreads; // Release Python's global interpreter lock to avoid a potential deadlock.
394         (*self->communicator)->destroy();
395     }
396     catch(const Ice::Exception& ex)
397     {
398         setPythonException(ex);
399     }
400 
401     vfm->destroy();
402 
403     if(self->dispatcher)
404     {
405         (*self->dispatcher)->setCommunicator(0); // Break cyclic reference.
406     }
407 
408     //
409     // Break cyclic reference between this object and its Python wrapper.
410     //
411     Py_XDECREF(self->wrapper);
412     self->wrapper = 0;
413 
414     if(PyErr_Occurred())
415     {
416         return 0;
417     }
418     else
419     {
420         Py_INCREF(Py_None);
421         return Py_None;
422     }
423 }
424 
425 #ifdef WIN32
426 extern "C"
427 #endif
428 static PyObject*
communicatorShutdown(CommunicatorObject * self,PyObject *)429 communicatorShutdown(CommunicatorObject* self, PyObject* /*args*/)
430 {
431     assert(self->communicator);
432     try
433     {
434         AllowThreads allowThreads; // Release Python's global interpreter lock to avoid a potential deadlock.
435         (*self->communicator)->shutdown();
436     }
437     catch(const Ice::Exception& ex)
438     {
439         setPythonException(ex);
440         return 0;
441     }
442 
443     Py_INCREF(Py_None);
444     return Py_None;
445 }
446 
447 #ifdef WIN32
448 extern "C"
449 #endif
450 static PyObject*
communicatorWaitForShutdown(CommunicatorObject * self,PyObject * args)451 communicatorWaitForShutdown(CommunicatorObject* self, PyObject* args)
452 {
453     //
454     // This method differs somewhat from the standard Ice API because of
455     // signal issues. This method expects an integer timeout value, and
456     // returns a boolean to indicate whether it was successful. When
457     // called from the main thread, the timeout is used to allow control
458     // to return to the caller (the Python interpreter) periodically.
459     // When called from any other thread, we call waitForShutdown directly
460     // and ignore the timeout.
461     //
462     int timeout = 0;
463     if(!PyArg_ParseTuple(args, STRCAST("i"), &timeout))
464     {
465         return 0;
466     }
467 
468     assert(timeout > 0);
469     assert(self->communicator);
470 
471     //
472     // Do not call waitForShutdown from the main thread, because it prevents
473     // signals (such as keyboard interrupts) from being delivered to Python.
474     //
475     if(PyThread_get_thread_ident() == _mainThreadId)
476     {
477         IceUtil::Monitor<IceUtil::Mutex>::Lock sync(*self->shutdownMonitor);
478 
479         if(!self->shutdown)
480         {
481             if(self->shutdownThread == 0)
482             {
483                 WaitForShutdownThreadPtr t = new WaitForShutdownThread(*self->communicator,
484                                                                        &Ice::Communicator::waitForShutdown,
485                                                                        *self->shutdownMonitor, self->shutdown);
486                 self->shutdownThread = new WaitForShutdownThreadPtr(t);
487                 t->start();
488             }
489 
490             while(!self->shutdown)
491             {
492                 bool done;
493                 {
494                     AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls.
495                     done = (*self->shutdownMonitor).timedWait(IceUtil::Time::milliSeconds(timeout));
496                 }
497 
498                 if(!done)
499                 {
500                     PyRETURN_FALSE;
501                 }
502             }
503         }
504 
505         assert(self->shutdown);
506 
507         Ice::Exception* ex = (*self->shutdownThread)->getException();
508         if(ex)
509         {
510             setPythonException(*ex);
511             return 0;
512         }
513     }
514     else
515     {
516         try
517         {
518             AllowThreads allowThreads; // Release Python's global interpreter lock during blocking calls.
519             (*self->communicator)->waitForShutdown();
520         }
521         catch(const Ice::Exception& ex)
522         {
523             setPythonException(ex);
524             return 0;
525         }
526     }
527 
528     PyRETURN_TRUE;
529 }
530 
531 #ifdef WIN32
532 extern "C"
533 #endif
534 static PyObject*
communicatorIsShutdown(CommunicatorObject * self,PyObject *)535 communicatorIsShutdown(CommunicatorObject* self, PyObject* /*args*/)
536 {
537     assert(self->communicator);
538     bool isShutdown;
539     try
540     {
541         isShutdown = (*self->communicator)->isShutdown();
542     }
543     catch(const Ice::Exception& ex)
544     {
545         setPythonException(ex);
546         return 0;
547     }
548 
549     PyRETURN_BOOL(isShutdown);
550 }
551 
552 #ifdef WIN32
553 extern "C"
554 #endif
555 static PyObject*
communicatorStringToProxy(CommunicatorObject * self,PyObject * args)556 communicatorStringToProxy(CommunicatorObject* self, PyObject* args)
557 {
558     PyObject* strObj;
559     if(!PyArg_ParseTuple(args, STRCAST("O"), &strObj))
560     {
561         return 0;
562     }
563 
564     string str;
565     if(!getStringArg(strObj, "str", str))
566     {
567         return 0;
568     }
569 
570     assert(self->communicator);
571     Ice::ObjectPrx proxy;
572     try
573     {
574         proxy = (*self->communicator)->stringToProxy(str);
575         if(proxy)
576         {
577             return createProxy(proxy, *self->communicator);
578         }
579     }
580     catch(const Ice::Exception& ex)
581     {
582         setPythonException(ex);
583         return 0;
584     }
585 
586     Py_INCREF(Py_None);
587     return Py_None;
588 }
589 
590 #ifdef WIN32
591 extern "C"
592 #endif
593 static PyObject*
communicatorProxyToString(CommunicatorObject * self,PyObject * args)594 communicatorProxyToString(CommunicatorObject* self, PyObject* args)
595 {
596     PyObject* obj;
597     if(!PyArg_ParseTuple(args, STRCAST("O"), &obj))
598     {
599         return 0;
600     }
601 
602     Ice::ObjectPrx proxy;
603     if(!getProxyArg(obj, "proxyToString", "obj", proxy))
604     {
605         return 0;
606     }
607 
608     string str;
609 
610     assert(self->communicator);
611     try
612     {
613         str = (*self->communicator)->proxyToString(proxy);
614     }
615     catch(const Ice::Exception& ex)
616     {
617         setPythonException(ex);
618         return 0;
619     }
620 
621     return createString(str);
622 }
623 
624 #ifdef WIN32
625 extern "C"
626 #endif
627 static PyObject*
communicatorPropertyToProxy(CommunicatorObject * self,PyObject * args)628 communicatorPropertyToProxy(CommunicatorObject* self, PyObject* args)
629 {
630     PyObject* strObj;
631     if(!PyArg_ParseTuple(args, STRCAST("O"), &strObj))
632     {
633         return 0;
634     }
635 
636     string str;
637     if(!getStringArg(strObj, "property", str))
638     {
639         return 0;
640     }
641 
642     assert(self->communicator);
643     Ice::ObjectPrx proxy;
644     try
645     {
646         proxy = (*self->communicator)->propertyToProxy(str);
647         if(proxy)
648         {
649             return createProxy(proxy, *self->communicator);
650         }
651     }
652     catch(const Ice::Exception& ex)
653     {
654         setPythonException(ex);
655         return 0;
656     }
657 
658     Py_INCREF(Py_None);
659     return Py_None;
660 }
661 
662 #ifdef WIN32
663 extern "C"
664 #endif
665 static PyObject*
communicatorProxyToProperty(CommunicatorObject * self,PyObject * args)666 communicatorProxyToProperty(CommunicatorObject* self, PyObject* args)
667 {
668     //
669     // We don't want to accept None here, so we can specify ProxyType and force
670     // the caller to supply a proxy object.
671     //
672     PyObject* proxyObj;
673     PyObject* strObj;
674     if(!PyArg_ParseTuple(args, STRCAST("O!O"), &ProxyType, &proxyObj, &strObj))
675     {
676         return 0;
677     }
678 
679     Ice::ObjectPrx proxy = getProxy(proxyObj);
680     string str;
681     if(!getStringArg(strObj, "property", str))
682     {
683         return 0;
684     }
685 
686     assert(self->communicator);
687     Ice::PropertyDict dict;
688     try
689     {
690         dict = (*self->communicator)->proxyToProperty(proxy, str);
691     }
692     catch(const Ice::Exception& ex)
693     {
694         setPythonException(ex);
695         return 0;
696     }
697 
698     PyObjectHandle result = PyDict_New();
699     if(result.get())
700     {
701         for(Ice::PropertyDict::iterator p = dict.begin(); p != dict.end(); ++p)
702         {
703             PyObjectHandle key = createString(p->first);
704             PyObjectHandle val = createString(p->second);
705             if(!val.get() || PyDict_SetItem(result.get(), key.get(), val.get()) < 0)
706             {
707                 return 0;
708             }
709         }
710     }
711 
712     return result.release();
713 }
714 
715 #ifdef WIN32
716 extern "C"
717 #endif
718 static PyObject*
communicatorStringToIdentity(CommunicatorObject * self,PyObject * args)719 communicatorStringToIdentity(CommunicatorObject* self, PyObject* args)
720 {
721     PyObject* strObj;
722     if(!PyArg_ParseTuple(args, STRCAST("O"), &strObj))
723     {
724         return 0;
725     }
726 
727     string str;
728     if(!getStringArg(strObj, "str", str))
729     {
730         return 0;
731     }
732 
733     assert(self->communicator);
734     Ice::Identity id;
735     try
736     {
737         id = (*self->communicator)->stringToIdentity(str);
738     }
739     catch(const Ice::Exception& ex)
740     {
741         setPythonException(ex);
742         return 0;
743     }
744 
745     return createIdentity(id);
746 }
747 
748 #ifdef WIN32
749 extern "C"
750 #endif
751 static PyObject*
communicatorIdentityToString(CommunicatorObject * self,PyObject * args)752 communicatorIdentityToString(CommunicatorObject* self, PyObject* args)
753 {
754     PyObject* identityType = lookupType("Ice.Identity");
755     PyObject* obj;
756     if(!PyArg_ParseTuple(args, STRCAST("O!"), identityType, &obj))
757     {
758         return 0;
759     }
760 
761     Ice::Identity id;
762     if(!getIdentity(obj, id))
763     {
764         return 0;
765     }
766     string str;
767 
768     assert(self->communicator);
769     try
770     {
771         str = (*self->communicator)->identityToString(id);
772     }
773     catch(const Ice::Exception& ex)
774     {
775         setPythonException(ex);
776         return 0;
777     }
778 
779     return createString(str);
780 }
781 
782 #ifdef WIN32
783 extern "C"
784 #endif
785 static PyObject*
communicatorFlushBatchRequests(CommunicatorObject * self,PyObject * args)786 communicatorFlushBatchRequests(CommunicatorObject* self, PyObject* args)
787 {
788     PyObject* compressBatchType = lookupType("Ice.CompressBatch");
789     PyObject* compressBatch;
790     if(!PyArg_ParseTuple(args, STRCAST("O!"), compressBatchType, &compressBatch))
791     {
792         return 0;
793     }
794 
795     PyObjectHandle v = getAttr(compressBatch, "_value", false);
796     assert(v.get());
797     Ice::CompressBatch cb = static_cast<Ice::CompressBatch>(PyLong_AsLong(v.get()));
798 
799     assert(self->communicator);
800     try
801     {
802         AllowThreads allowThreads; // Release Python's global interpreter lock to avoid a potential deadlock.
803         (*self->communicator)->flushBatchRequests(cb);
804     }
805     catch(const Ice::Exception& ex)
806     {
807         setPythonException(ex);
808         return 0;
809     }
810 
811     Py_INCREF(Py_None);
812     return Py_None;
813 }
814 
815 #ifdef WIN32
816 extern "C"
817 #endif
818 static PyObject*
communicatorFlushBatchRequestsAsync(CommunicatorObject * self,PyObject * args,PyObject *)819 communicatorFlushBatchRequestsAsync(CommunicatorObject* self, PyObject* args, PyObject* /*kwds*/)
820 {
821     PyObject* compressBatchType = lookupType("Ice.CompressBatch");
822     PyObject* compressBatch;
823     if(!PyArg_ParseTuple(args, STRCAST("O!"), compressBatchType, &compressBatch))
824     {
825         return 0;
826     }
827 
828     PyObjectHandle v = getAttr(compressBatch, "_value", false);
829     assert(v.get());
830     Ice::CompressBatch cb = static_cast<Ice::CompressBatch>(PyLong_AsLong(v.get()));
831 
832     assert(self->communicator);
833     const string op = "flushBatchRequests";
834 
835     FlushAsyncCallbackPtr d = new FlushAsyncCallback(op);
836     Ice::Callback_Communicator_flushBatchRequestsPtr callback =
837         Ice::newCallback_Communicator_flushBatchRequests(d, &FlushAsyncCallback::exception, &FlushAsyncCallback::sent);
838 
839     Ice::AsyncResultPtr result;
840 
841     try
842     {
843         result = (*self->communicator)->begin_flushBatchRequests(cb, callback);
844     }
845     catch(const Ice::Exception& ex)
846     {
847         setPythonException(ex);
848         return 0;
849     }
850 
851     PyObjectHandle asyncResultObj = createAsyncResult(result, 0, 0, self->wrapper);
852     if(!asyncResultObj.get())
853     {
854         return 0;
855     }
856 
857     PyObjectHandle future = createFuture(op, asyncResultObj.get());
858     if(!future.get())
859     {
860         return 0;
861     }
862     d->setFuture(future.get());
863     return future.release();
864 }
865 
866 #ifdef WIN32
867 extern "C"
868 #endif
869 static PyObject*
communicatorBeginFlushBatchRequests(CommunicatorObject * self,PyObject * args,PyObject * kwds)870 communicatorBeginFlushBatchRequests(CommunicatorObject* self, PyObject* args, PyObject* kwds)
871 {
872     assert(self->communicator);
873 
874     static char* argNames[] =
875     {
876         const_cast<char*>("compress"),
877         const_cast<char*>("_ex"),
878         const_cast<char*>("_sent"),
879         0
880     };
881     PyObject* compressBatch;
882     PyObject* ex = Py_None;
883     PyObject* sent = Py_None;
884     if(!PyArg_ParseTupleAndKeywords(args, kwds, STRCAST("O|OO"), argNames, &compressBatch, &ex, &sent))
885     {
886         return 0;
887     }
888 
889     PyObject* compressBatchType = lookupType("Ice.CompressBatch");
890     if(!PyObject_IsInstance(compressBatch, reinterpret_cast<PyObject*>(compressBatchType)))
891     {
892         PyErr_Format(PyExc_ValueError, STRCAST("expected an Ice.CompressBatch enumerator"));
893         return 0;
894     }
895 
896     PyObjectHandle v = getAttr(compressBatch, "_value", false);
897     assert(v.get());
898     Ice::CompressBatch cb = static_cast<Ice::CompressBatch>(PyLong_AsLong(v.get()));
899 
900     if(ex == Py_None)
901     {
902         ex = 0;
903     }
904     if(sent == Py_None)
905     {
906         sent = 0;
907     }
908 
909     if(!ex && sent)
910     {
911         PyErr_Format(PyExc_RuntimeError,
912             STRCAST("exception callback must also be provided when sent callback is used"));
913         return 0;
914     }
915 
916     Ice::Callback_Communicator_flushBatchRequestsPtr callback;
917     if(ex || sent)
918     {
919         FlushCallbackPtr d = new FlushCallback(ex, sent, "flushBatchRequests");
920         callback = Ice::newCallback_Communicator_flushBatchRequests(d, &FlushCallback::exception, &FlushCallback::sent);
921     }
922 
923     Ice::AsyncResultPtr result;
924     try
925     {
926         if(callback)
927         {
928             result = (*self->communicator)->begin_flushBatchRequests(cb, callback);
929         }
930         else
931         {
932             result = (*self->communicator)->begin_flushBatchRequests(cb);
933         }
934     }
935     catch(const Ice::Exception& e)
936     {
937         setPythonException(e);
938         return 0;
939     }
940 
941     return createAsyncResult(result, 0, 0, self->wrapper);
942 }
943 
944 #ifdef WIN32
945 extern "C"
946 #endif
947 static PyObject*
communicatorEndFlushBatchRequests(CommunicatorObject * self,PyObject * args)948 communicatorEndFlushBatchRequests(CommunicatorObject* self, PyObject* args)
949 {
950     assert(self->communicator);
951 
952     PyObject* result;
953     if(!PyArg_ParseTuple(args, STRCAST("O!"), &AsyncResultType, &result))
954     {
955         return 0;
956     }
957 
958     Ice::AsyncResultPtr r = getAsyncResult(result);
959     try
960     {
961         AllowThreads allowThreads; // Release Python's global interpreter lock during blocking invocations.
962         (*self->communicator)->end_flushBatchRequests(r);
963     }
964     catch(const Ice::Exception& ex)
965     {
966         setPythonException(ex);
967         return 0;
968     }
969 
970     Py_INCREF(Py_None);
971     return Py_None;
972 }
973 
974 #ifdef WIN32
975 extern "C"
976 #endif
977 static PyObject*
communicatorCreateAdmin(CommunicatorObject * self,PyObject * args)978 communicatorCreateAdmin(CommunicatorObject* self, PyObject* args)
979 {
980     PyObject* adapter;
981     PyObject* identityType = lookupType("Ice.Identity");
982     PyObject* id;
983     if(!PyArg_ParseTuple(args, STRCAST("OO!"), &adapter, identityType, &id))
984     {
985         return 0;
986     }
987 
988     Ice::ObjectAdapterPtr oa;
989 
990     PyObject* adapterType = lookupType("Ice.ObjectAdapter");
991     if(adapter != Py_None && !PyObject_IsInstance(adapter, adapterType))
992     {
993         PyErr_Format(PyExc_ValueError, STRCAST("expected ObjectAdapter or None"));
994         return 0;
995     }
996 
997     if(adapter != Py_None)
998     {
999         oa = unwrapObjectAdapter(adapter);
1000     }
1001 
1002     Ice::Identity identity;
1003     if(!getIdentity(id, identity))
1004     {
1005         return 0;
1006     }
1007 
1008     assert(self->communicator);
1009     Ice::ObjectPrx proxy;
1010     try
1011     {
1012         proxy = (*self->communicator)->createAdmin(oa, identity);
1013         assert(proxy);
1014 
1015         return createProxy(proxy, *self->communicator);
1016     }
1017     catch(const Ice::Exception& ex)
1018     {
1019         setPythonException(ex);
1020         return 0;
1021     }
1022 }
1023 
1024 #ifdef WIN32
1025 extern "C"
1026 #endif
1027 static PyObject*
communicatorGetAdmin(CommunicatorObject * self,PyObject *)1028 communicatorGetAdmin(CommunicatorObject* self, PyObject* /*args*/)
1029 {
1030     assert(self->communicator);
1031     Ice::ObjectPrx proxy;
1032     try
1033     {
1034         proxy = (*self->communicator)->getAdmin();
1035         if(proxy)
1036         {
1037             return createProxy(proxy, *self->communicator);
1038         }
1039     }
1040     catch(const Ice::Exception& ex)
1041     {
1042         setPythonException(ex);
1043         return 0;
1044     }
1045 
1046     Py_INCREF(Py_None);
1047     return Py_None;
1048 }
1049 
1050 #ifdef WIN32
1051 extern "C"
1052 #endif
1053 static PyObject*
communicatorAddAdminFacet(CommunicatorObject * self,PyObject * args)1054 communicatorAddAdminFacet(CommunicatorObject* self, PyObject* args)
1055 {
1056     PyObject* objectType = lookupType("Ice.Object");
1057     PyObject* servant;
1058     PyObject* facetObj;
1059     if(!PyArg_ParseTuple(args, STRCAST("O!O"), objectType, &servant, &facetObj))
1060     {
1061         return 0;
1062     }
1063 
1064     string facet;
1065     if(!getStringArg(facetObj, "facet", facet))
1066     {
1067         return 0;
1068     }
1069 
1070     ServantWrapperPtr wrapper = createServantWrapper(servant);
1071     if(PyErr_Occurred())
1072     {
1073         return 0;
1074     }
1075 
1076     assert(self->communicator);
1077     try
1078     {
1079         (*self->communicator)->addAdminFacet(wrapper, facet);
1080     }
1081     catch(const Ice::Exception& ex)
1082     {
1083         setPythonException(ex);
1084         return 0;
1085     }
1086 
1087     Py_INCREF(Py_None);
1088     return Py_None;
1089 }
1090 
1091 #ifdef WIN32
1092 extern "C"
1093 #endif
1094 static PyObject*
communicatorFindAdminFacet(CommunicatorObject * self,PyObject * args)1095 communicatorFindAdminFacet(CommunicatorObject* self, PyObject* args)
1096 {
1097     PyObject* facetObj;
1098     if(!PyArg_ParseTuple(args, STRCAST("O"), &facetObj))
1099     {
1100         return 0;
1101     }
1102 
1103     string facet;
1104     if(!getStringArg(facetObj, "facet", facet))
1105     {
1106         return 0;
1107     }
1108 
1109     assert(self->communicator);
1110     try
1111     {
1112         //
1113         // The facet being found may not be implemented by a Python servant
1114         // (e.g., it could be the Process or Properties facet), in which case
1115         // we return None.
1116         //
1117         Ice::ObjectPtr obj = (*self->communicator)->findAdminFacet(facet);
1118         if(obj)
1119         {
1120             ServantWrapperPtr wrapper = ServantWrapperPtr::dynamicCast(obj);
1121             if(wrapper)
1122             {
1123                 return wrapper->getObject();
1124             }
1125 
1126             Ice::NativePropertiesAdminPtr props = Ice::NativePropertiesAdminPtr::dynamicCast(obj);
1127             if(props)
1128             {
1129                 return createNativePropertiesAdmin(props);
1130             }
1131 
1132             // If the facet isn't supported in Python, just return an Ice.Object.
1133             PyTypeObject* objectType = reinterpret_cast<PyTypeObject*>(lookupType("Ice.Object"));
1134             return objectType->tp_alloc(objectType, 0);
1135         }
1136     }
1137     catch(const Ice::Exception& ex)
1138     {
1139         setPythonException(ex);
1140         return 0;
1141     }
1142 
1143     Py_INCREF(Py_None);
1144     return Py_None;
1145 }
1146 
1147 #ifdef WIN32
1148 extern "C"
1149 #endif
1150 static PyObject*
communicatorFindAllAdminFacets(CommunicatorObject * self,PyObject *)1151 communicatorFindAllAdminFacets(CommunicatorObject* self, PyObject* /*args*/)
1152 {
1153     assert(self->communicator);
1154     Ice::FacetMap facetMap;
1155     try
1156     {
1157         facetMap = (*self->communicator)->findAllAdminFacets();
1158     }
1159     catch(const Ice::Exception& ex)
1160     {
1161         setPythonException(ex);
1162         return 0;
1163     }
1164 
1165     PyObjectHandle result = PyDict_New();
1166     if(!result.get())
1167     {
1168         return 0;
1169     }
1170 
1171     PyTypeObject* objectType = reinterpret_cast<PyTypeObject*>(lookupType("Ice.Object"));
1172     PyObjectHandle plainObject = objectType->tp_alloc(objectType, 0);
1173 
1174     for(Ice::FacetMap::const_iterator p = facetMap.begin(); p != facetMap.end(); ++p)
1175     {
1176 
1177         PyObjectHandle obj = plainObject;
1178 
1179         ServantWrapperPtr wrapper = ServantWrapperPtr::dynamicCast(p->second);
1180         if(wrapper)
1181         {
1182             obj = wrapper->getObject();
1183         }
1184         else
1185         {
1186             Ice::NativePropertiesAdminPtr props = Ice::NativePropertiesAdminPtr::dynamicCast(p->second);
1187             if(props)
1188             {
1189                 obj = createNativePropertiesAdmin(props);
1190             }
1191         }
1192 
1193         if(PyDict_SetItemString(result.get(), const_cast<char*>(p->first.c_str()), obj.get()) < 0)
1194         {
1195             return 0;
1196         }
1197     }
1198 
1199     return result.release();
1200 }
1201 
1202 #ifdef WIN32
1203 extern "C"
1204 #endif
1205 static PyObject*
communicatorRemoveAdminFacet(CommunicatorObject * self,PyObject * args)1206 communicatorRemoveAdminFacet(CommunicatorObject* self, PyObject* args)
1207 {
1208     PyObject* facetObj;
1209     if(!PyArg_ParseTuple(args, STRCAST("O"), &facetObj))
1210     {
1211         return 0;
1212     }
1213 
1214     string facet;
1215     if(!getStringArg(facetObj, "facet", facet))
1216     {
1217         return 0;
1218     }
1219 
1220     assert(self->communicator);
1221     try
1222     {
1223         //
1224         // The facet being removed may not be implemented by a Python servant
1225         // (e.g., it could be the Process or Properties facet), in which case
1226         // we return None.
1227         //
1228         Ice::ObjectPtr obj = (*self->communicator)->removeAdminFacet(facet);
1229         assert(obj);
1230         ServantWrapperPtr wrapper = ServantWrapperPtr::dynamicCast(obj);
1231         if(wrapper)
1232         {
1233             return wrapper->getObject();
1234         }
1235     }
1236     catch(const Ice::Exception& ex)
1237     {
1238         setPythonException(ex);
1239         return 0;
1240     }
1241 
1242     Py_INCREF(Py_None);
1243     return Py_None;
1244 }
1245 
1246 #ifdef WIN32
1247 extern "C"
1248 #endif
1249 static PyObject*
communicatorSetWrapper(CommunicatorObject * self,PyObject * args)1250 communicatorSetWrapper(CommunicatorObject* self, PyObject* args)
1251 {
1252     PyObject* wrapper;
1253     if(!PyArg_ParseTuple(args, STRCAST("O"), &wrapper))
1254     {
1255         return 0;
1256     }
1257 
1258     assert(!self->wrapper);
1259     self->wrapper = wrapper;
1260     Py_INCREF(self->wrapper);
1261 
1262     Py_INCREF(Py_None);
1263     return Py_None;
1264 }
1265 
1266 #ifdef WIN32
1267 extern "C"
1268 #endif
1269 static PyObject*
communicatorGetWrapper(CommunicatorObject * self,PyObject *)1270 communicatorGetWrapper(CommunicatorObject* self, PyObject* /*args*/)
1271 {
1272     assert(self->wrapper);
1273     Py_INCREF(self->wrapper);
1274     return self->wrapper;
1275 }
1276 
1277 #ifdef WIN32
1278 extern "C"
1279 #endif
1280 static PyObject*
communicatorGetProperties(CommunicatorObject * self,PyObject *)1281 communicatorGetProperties(CommunicatorObject* self, PyObject* /*args*/)
1282 {
1283     assert(self->communicator);
1284     Ice::PropertiesPtr properties;
1285     try
1286     {
1287         properties = (*self->communicator)->getProperties();
1288     }
1289     catch(const Ice::Exception& ex)
1290     {
1291         setPythonException(ex);
1292         return 0;
1293     }
1294 
1295     return createProperties(properties);
1296 }
1297 
1298 #ifdef WIN32
1299 extern "C"
1300 #endif
1301 static PyObject*
communicatorGetLogger(CommunicatorObject * self,PyObject *)1302 communicatorGetLogger(CommunicatorObject* self, PyObject* /*args*/)
1303 {
1304     assert(self->communicator);
1305     Ice::LoggerPtr logger;
1306     try
1307     {
1308         logger = (*self->communicator)->getLogger();
1309     }
1310     catch(const Ice::Exception& ex)
1311     {
1312         setPythonException(ex);
1313         return 0;
1314     }
1315 
1316     //
1317     // The communicator's logger can either be a C++ object (such as
1318     // the default logger supplied by the Ice run time), or a C++
1319     // wrapper around a Python implementation. If the latter, we
1320     // return it directly. Otherwise, we create a Python object
1321     // that delegates to the C++ object.
1322     //
1323     LoggerWrapperPtr wrapper = LoggerWrapperPtr::dynamicCast(logger);
1324     if(wrapper)
1325     {
1326         PyObject* obj = wrapper->getObject();
1327         Py_INCREF(obj);
1328         return obj;
1329     }
1330 
1331     return createLogger(logger);
1332 }
1333 
1334 #ifdef WIN32
1335 extern "C"
1336 #endif
1337 static PyObject*
communicatorAddObjectFactory(CommunicatorObject * self,PyObject * args)1338 communicatorAddObjectFactory(CommunicatorObject* self, PyObject* args)
1339 {
1340     PyObject* objectFactoryType = lookupType("Ice.ObjectFactory");
1341     assert(objectFactoryType);
1342     PyObject* valueFactoryType = lookupType("types.FunctionType");
1343     assert(valueFactoryType);
1344 
1345     PyObject* objectFactory;
1346     PyObject* strObj;
1347     PyObject* valueFactory;
1348     if(!PyArg_ParseTuple(args, STRCAST("O!OO!"), objectFactoryType, &objectFactory, &strObj, valueFactoryType,
1349                          &valueFactory))
1350     {
1351         return 0;
1352     }
1353 
1354     string id;
1355     if(!getStringArg(strObj, "id", id))
1356     {
1357         return 0;
1358     }
1359 
1360     ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast((*self->communicator)->getValueFactoryManager());
1361     assert(vfm);
1362 
1363     try
1364     {
1365         vfm->add(valueFactory, objectFactory, id);
1366     }
1367     catch(const Ice::Exception& ex)
1368     {
1369         setPythonException(ex);
1370         return 0;
1371 
1372     }
1373 
1374     Py_INCREF(Py_None);
1375     return Py_None;
1376 }
1377 
1378 #ifdef WIN32
1379 extern "C"
1380 #endif
1381 static PyObject*
communicatorFindObjectFactory(CommunicatorObject * self,PyObject * args)1382 communicatorFindObjectFactory(CommunicatorObject* self, PyObject* args)
1383 {
1384     PyObject* strObj;
1385     if(!PyArg_ParseTuple(args, STRCAST("O"), &strObj))
1386     {
1387         return 0;
1388     }
1389 
1390     string id;
1391     if(!getStringArg(strObj, "id", id))
1392     {
1393         return 0;
1394     }
1395 
1396     ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast((*self->communicator)->getValueFactoryManager());
1397     assert(vfm);
1398 
1399     return vfm->findObjectFactory(id);
1400 }
1401 
1402 #ifdef WIN32
1403 extern "C"
1404 #endif
1405 static PyObject*
communicatorGetValueFactoryManager(CommunicatorObject * self,PyObject *)1406 communicatorGetValueFactoryManager(CommunicatorObject* self, PyObject* /*args*/)
1407 {
1408     ValueFactoryManagerPtr vfm = ValueFactoryManagerPtr::dynamicCast((*self->communicator)->getValueFactoryManager());
1409 
1410     return vfm->getObject();
1411 }
1412 
1413 #ifdef WIN32
1414 extern "C"
1415 #endif
1416 static PyObject*
communicatorGetImplicitContext(CommunicatorObject * self,PyObject *)1417 communicatorGetImplicitContext(CommunicatorObject* self, PyObject* /*args*/)
1418 {
1419     Ice::ImplicitContextPtr implicitContext = (*self->communicator)->getImplicitContext();
1420 
1421     if(implicitContext == 0)
1422     {
1423         Py_INCREF(Py_None);
1424         return Py_None;
1425     }
1426 
1427     return createImplicitContext(implicitContext);
1428 }
1429 
1430 #ifdef WIN32
1431 extern "C"
1432 #endif
1433 static PyObject*
communicatorCreateObjectAdapter(CommunicatorObject * self,PyObject * args)1434 communicatorCreateObjectAdapter(CommunicatorObject* self, PyObject* args)
1435 {
1436     PyObject* strObj;
1437     if(!PyArg_ParseTuple(args, STRCAST("O"), &strObj))
1438     {
1439         return 0;
1440     }
1441 
1442     string name;
1443     if(!getStringArg(strObj, "name", name))
1444     {
1445         return 0;
1446     }
1447 
1448     assert(self->communicator);
1449     Ice::ObjectAdapterPtr adapter;
1450     try
1451     {
1452         adapter = (*self->communicator)->createObjectAdapter(name);
1453     }
1454     catch(const Ice::Exception& ex)
1455     {
1456         setPythonException(ex);
1457         return 0;
1458     }
1459 
1460     PyObject* obj = createObjectAdapter(adapter);
1461     if(!obj)
1462     {
1463         try
1464         {
1465             adapter->deactivate();
1466         }
1467         catch(const Ice::Exception&)
1468         {
1469         }
1470     }
1471 
1472     return obj;
1473 }
1474 
1475 #ifdef WIN32
1476 extern "C"
1477 #endif
1478 static PyObject*
communicatorCreateObjectAdapterWithEndpoints(CommunicatorObject * self,PyObject * args)1479 communicatorCreateObjectAdapterWithEndpoints(CommunicatorObject* self, PyObject* args)
1480 {
1481     PyObject* nameObj;
1482     PyObject* endpointsObj;
1483     if(!PyArg_ParseTuple(args, STRCAST("OO"), &nameObj, &endpointsObj))
1484     {
1485         return 0;
1486     }
1487 
1488     string name;
1489     string endpoints;
1490     if(!getStringArg(nameObj, "name", name))
1491     {
1492         return 0;
1493     }
1494     if(!getStringArg(endpointsObj, "endpoints", endpoints))
1495     {
1496         return 0;
1497     }
1498 
1499     assert(self->communicator);
1500     Ice::ObjectAdapterPtr adapter;
1501     try
1502     {
1503         adapter = (*self->communicator)->createObjectAdapterWithEndpoints(name, endpoints);
1504     }
1505     catch(const Ice::Exception& ex)
1506     {
1507         setPythonException(ex);
1508         return 0;
1509     }
1510 
1511     PyObject* obj = createObjectAdapter(adapter);
1512     if(!obj)
1513     {
1514         try
1515         {
1516             adapter->deactivate();
1517         }
1518         catch(const Ice::Exception&)
1519         {
1520         }
1521     }
1522 
1523     return obj;
1524 }
1525 
1526 #ifdef WIN32
1527 extern "C"
1528 #endif
1529 static PyObject*
communicatorCreateObjectAdapterWithRouter(CommunicatorObject * self,PyObject * args)1530 communicatorCreateObjectAdapterWithRouter(CommunicatorObject* self, PyObject* args)
1531 {
1532     PyObject* nameObj;
1533     PyObject* p;
1534     if(!PyArg_ParseTuple(args, STRCAST("OO"), &nameObj, &p))
1535     {
1536         return 0;
1537     }
1538 
1539     string name;
1540     if(!getStringArg(nameObj, "name", name))
1541     {
1542         return 0;
1543     }
1544 
1545     Ice::ObjectPrx proxy;
1546     if(!getProxyArg(p, "createObjectAdapterWithRouter", "rtr", proxy, "Ice.RouterPrx"))
1547     {
1548         return 0;
1549     }
1550 
1551     Ice::RouterPrx router = Ice::RouterPrx::uncheckedCast(proxy);
1552 
1553     assert(self->communicator);
1554     Ice::ObjectAdapterPtr adapter;
1555     try
1556     {
1557         AllowThreads allowThreads; // Release Python's global interpreter lock to avoid a potential deadlock.
1558         adapter = (*self->communicator)->createObjectAdapterWithRouter(name, router);
1559     }
1560     catch(const Ice::Exception& ex)
1561     {
1562         setPythonException(ex);
1563         return 0;
1564     }
1565 
1566     PyObject* obj = createObjectAdapter(adapter);
1567     if(!obj)
1568     {
1569         try
1570         {
1571             adapter->deactivate();
1572         }
1573         catch(const Ice::Exception&)
1574         {
1575         }
1576     }
1577 
1578     return obj;
1579 }
1580 
1581 #ifdef WIN32
1582 extern "C"
1583 #endif
1584 static PyObject*
communicatorGetDefaultRouter(CommunicatorObject * self,PyObject *)1585 communicatorGetDefaultRouter(CommunicatorObject* self, PyObject* /*args*/)
1586 {
1587     assert(self->communicator);
1588     Ice::RouterPrx router;
1589     try
1590     {
1591         router = (*self->communicator)->getDefaultRouter();
1592     }
1593     catch(const Ice::Exception& ex)
1594     {
1595         setPythonException(ex);
1596         return 0;
1597     }
1598 
1599     if(!router)
1600     {
1601         Py_INCREF(Py_None);
1602         return Py_None;
1603     }
1604 
1605     PyObject* routerProxyType = lookupType("Ice.RouterPrx");
1606     assert(routerProxyType);
1607     return createProxy(router, *self->communicator, routerProxyType);
1608 }
1609 
1610 #ifdef WIN32
1611 extern "C"
1612 #endif
1613 static PyObject*
communicatorSetDefaultRouter(CommunicatorObject * self,PyObject * args)1614 communicatorSetDefaultRouter(CommunicatorObject* self, PyObject* args)
1615 {
1616     PyObject* p;
1617     if(!PyArg_ParseTuple(args, STRCAST("O"), &p))
1618     {
1619         return 0;
1620     }
1621 
1622     Ice::ObjectPrx proxy;
1623     if(!getProxyArg(p, "setDefaultRouter", "rtr", proxy, "Ice.RouterPrx"))
1624     {
1625         return 0;
1626     }
1627 
1628     Ice::RouterPrx router = Ice::RouterPrx::uncheckedCast(proxy);
1629 
1630     assert(self->communicator);
1631     try
1632     {
1633         (*self->communicator)->setDefaultRouter(router);
1634     }
1635     catch(const Ice::Exception& ex)
1636     {
1637         setPythonException(ex);
1638         return 0;
1639     }
1640 
1641     Py_INCREF(Py_None);
1642     return Py_None;
1643 }
1644 
1645 #ifdef WIN32
1646 extern "C"
1647 #endif
1648 static PyObject*
communicatorGetDefaultLocator(CommunicatorObject * self,PyObject *)1649 communicatorGetDefaultLocator(CommunicatorObject* self, PyObject* /*args*/)
1650 {
1651     assert(self->communicator);
1652     Ice::LocatorPrx locator;
1653     try
1654     {
1655         locator = (*self->communicator)->getDefaultLocator();
1656     }
1657     catch(const Ice::Exception& ex)
1658     {
1659         setPythonException(ex);
1660         return 0;
1661     }
1662 
1663     if(!locator)
1664     {
1665         Py_INCREF(Py_None);
1666         return Py_None;
1667     }
1668 
1669     PyObject* locatorProxyType = lookupType("Ice.LocatorPrx");
1670     assert(locatorProxyType);
1671     return createProxy(locator, *self->communicator, locatorProxyType);
1672 }
1673 
1674 #ifdef WIN32
1675 extern "C"
1676 #endif
1677 static PyObject*
communicatorSetDefaultLocator(CommunicatorObject * self,PyObject * args)1678 communicatorSetDefaultLocator(CommunicatorObject* self, PyObject* args)
1679 {
1680     PyObject* p;
1681     if(!PyArg_ParseTuple(args, STRCAST("O"), &p))
1682     {
1683         return 0;
1684     }
1685 
1686     Ice::ObjectPrx proxy;
1687     if(!getProxyArg(p, "setDefaultLocator", "loc", proxy, "Ice.LocatorPrx"))
1688     {
1689         return 0;
1690     }
1691 
1692     Ice::LocatorPrx locator = Ice::LocatorPrx::uncheckedCast(proxy);
1693 
1694     assert(self->communicator);
1695     try
1696     {
1697         (*self->communicator)->setDefaultLocator(locator);
1698     }
1699     catch(const Ice::Exception& ex)
1700     {
1701         setPythonException(ex);
1702         return 0;
1703     }
1704 
1705     Py_INCREF(Py_None);
1706     return Py_None;
1707 }
1708 
1709 static PyMethodDef CommunicatorMethods[] =
1710 {
1711     { STRCAST("destroy"), reinterpret_cast<PyCFunction>(communicatorDestroy), METH_NOARGS,
1712         PyDoc_STR(STRCAST("destroy() -> None")) },
1713     { STRCAST("shutdown"), reinterpret_cast<PyCFunction>(communicatorShutdown), METH_NOARGS,
1714         PyDoc_STR(STRCAST("shutdown() -> None")) },
1715     { STRCAST("waitForShutdown"), reinterpret_cast<PyCFunction>(communicatorWaitForShutdown), METH_VARARGS,
1716         PyDoc_STR(STRCAST("waitForShutdown() -> None")) },
1717     { STRCAST("isShutdown"), reinterpret_cast<PyCFunction>(communicatorIsShutdown), METH_NOARGS,
1718         PyDoc_STR(STRCAST("isShutdown() -> bool")) },
1719     { STRCAST("stringToProxy"), reinterpret_cast<PyCFunction>(communicatorStringToProxy), METH_VARARGS,
1720         PyDoc_STR(STRCAST("stringToProxy(str) -> Ice.ObjectPrx")) },
1721     { STRCAST("proxyToString"), reinterpret_cast<PyCFunction>(communicatorProxyToString), METH_VARARGS,
1722         PyDoc_STR(STRCAST("proxyToString(Ice.ObjectPrx) -> string")) },
1723     { STRCAST("propertyToProxy"), reinterpret_cast<PyCFunction>(communicatorPropertyToProxy), METH_VARARGS,
1724         PyDoc_STR(STRCAST("propertyToProxy(str) -> Ice.ObjectPrx")) },
1725     { STRCAST("proxyToProperty"), reinterpret_cast<PyCFunction>(communicatorProxyToProperty), METH_VARARGS,
1726         PyDoc_STR(STRCAST("proxyToProperty(Ice.ObjectPrx, str) -> dict")) },
1727     { STRCAST("stringToIdentity"), reinterpret_cast<PyCFunction>(communicatorStringToIdentity), METH_VARARGS,
1728         PyDoc_STR(STRCAST("stringToIdentity(str) -> Ice.Identity")) },
1729     { STRCAST("identityToString"), reinterpret_cast<PyCFunction>(communicatorIdentityToString), METH_VARARGS,
1730         PyDoc_STR(STRCAST("identityToString(Ice.Identity) -> string")) },
1731     { STRCAST("createObjectAdapter"), reinterpret_cast<PyCFunction>(communicatorCreateObjectAdapter), METH_VARARGS,
1732         PyDoc_STR(STRCAST("createObjectAdapter(name) -> Ice.ObjectAdapter")) },
1733     { STRCAST("createObjectAdapterWithEndpoints"),
1734         reinterpret_cast<PyCFunction>(communicatorCreateObjectAdapterWithEndpoints), METH_VARARGS,
1735         PyDoc_STR(STRCAST("createObjectAdapterWithEndpoints(name, endpoints) -> Ice.ObjectAdapter")) },
1736     { STRCAST("createObjectAdapterWithRouter"),
1737         reinterpret_cast<PyCFunction>(communicatorCreateObjectAdapterWithRouter), METH_VARARGS,
1738         PyDoc_STR(STRCAST("createObjectAdapterWithRouter(name, router) -> Ice.ObjectAdapter")) },
1739     { STRCAST("addObjectFactory"), reinterpret_cast<PyCFunction>(communicatorAddObjectFactory), METH_VARARGS,
1740         PyDoc_STR(STRCAST("addObjectFactory(factory, id) -> None")) },
1741     { STRCAST("findObjectFactory"), reinterpret_cast<PyCFunction>(communicatorFindObjectFactory), METH_VARARGS,
1742         PyDoc_STR(STRCAST("findObjectFactory(id) -> Ice.ObjectFactory")) },
1743     { STRCAST("getValueFactoryManager"), reinterpret_cast<PyCFunction>(communicatorGetValueFactoryManager), METH_NOARGS,
1744         PyDoc_STR(STRCAST("getValueFactoryManager() -> Ice.ValueFactoryManager")) },
1745     { STRCAST("getImplicitContext"), reinterpret_cast<PyCFunction>(communicatorGetImplicitContext), METH_NOARGS,
1746       PyDoc_STR(STRCAST("getImplicitContext() -> Ice.ImplicitContext")) },
1747     { STRCAST("getProperties"), reinterpret_cast<PyCFunction>(communicatorGetProperties), METH_NOARGS,
1748         PyDoc_STR(STRCAST("getProperties() -> Ice.Properties")) },
1749     { STRCAST("getLogger"), reinterpret_cast<PyCFunction>(communicatorGetLogger), METH_NOARGS,
1750         PyDoc_STR(STRCAST("getLogger() -> Ice.Logger")) },
1751     { STRCAST("getDefaultRouter"), reinterpret_cast<PyCFunction>(communicatorGetDefaultRouter), METH_NOARGS,
1752         PyDoc_STR(STRCAST("getDefaultRouter() -> proxy")) },
1753     { STRCAST("setDefaultRouter"), reinterpret_cast<PyCFunction>(communicatorSetDefaultRouter), METH_VARARGS,
1754         PyDoc_STR(STRCAST("setDefaultRouter(proxy) -> None")) },
1755     { STRCAST("getDefaultLocator"), reinterpret_cast<PyCFunction>(communicatorGetDefaultLocator), METH_NOARGS,
1756         PyDoc_STR(STRCAST("getDefaultLocator() -> proxy")) },
1757     { STRCAST("setDefaultLocator"), reinterpret_cast<PyCFunction>(communicatorSetDefaultLocator), METH_VARARGS,
1758         PyDoc_STR(STRCAST("setDefaultLocator(proxy) -> None")) },
1759     { STRCAST("flushBatchRequests"), reinterpret_cast<PyCFunction>(communicatorFlushBatchRequests), METH_VARARGS,
1760         PyDoc_STR(STRCAST("flushBatchRequests(compress) -> None")) },
1761     { STRCAST("flushBatchRequestsAsync"), reinterpret_cast<PyCFunction>(communicatorFlushBatchRequestsAsync),
1762         METH_VARARGS, PyDoc_STR(STRCAST("flushBatchRequestsAsync(compress) -> Ice.Future")) },
1763     { STRCAST("begin_flushBatchRequests"), reinterpret_cast<PyCFunction>(communicatorBeginFlushBatchRequests),
1764         METH_VARARGS | METH_KEYWORDS,
1765         PyDoc_STR(STRCAST("begin_flushBatchRequests(compress[, _ex][, _sent]) -> Ice.AsyncResult")) },
1766     { STRCAST("end_flushBatchRequests"), reinterpret_cast<PyCFunction>(communicatorEndFlushBatchRequests),
1767         METH_VARARGS, PyDoc_STR(STRCAST("end_flushBatchRequests(Ice.AsyncResult) -> None")) },
1768     { STRCAST("createAdmin"), reinterpret_cast<PyCFunction>(communicatorCreateAdmin), METH_VARARGS,
1769         PyDoc_STR(STRCAST("createAdmin(adminAdapter, adminIdentity) -> Ice.ObjectPrx")) },
1770     { STRCAST("getAdmin"), reinterpret_cast<PyCFunction>(communicatorGetAdmin), METH_NOARGS,
1771         PyDoc_STR(STRCAST("getAdmin() -> Ice.ObjectPrx")) },
1772     { STRCAST("addAdminFacet"), reinterpret_cast<PyCFunction>(communicatorAddAdminFacet), METH_VARARGS,
1773         PyDoc_STR(STRCAST("addAdminFacet(servant, facet) -> None")) },
1774     { STRCAST("findAdminFacet"), reinterpret_cast<PyCFunction>(communicatorFindAdminFacet), METH_VARARGS,
1775         PyDoc_STR(STRCAST("findAdminFacet(facet) -> Ice.Object")) },
1776     { STRCAST("findAllAdminFacets"), reinterpret_cast<PyCFunction>(communicatorFindAllAdminFacets), METH_NOARGS,
1777       PyDoc_STR(STRCAST("findAllAdminFacets() -> dictionary")) },
1778     { STRCAST("removeAdminFacet"), reinterpret_cast<PyCFunction>(communicatorRemoveAdminFacet), METH_VARARGS,
1779         PyDoc_STR(STRCAST("removeAdminFacet(facet) -> Ice.Object")) },
1780     { STRCAST("_setWrapper"), reinterpret_cast<PyCFunction>(communicatorSetWrapper), METH_VARARGS,
1781         PyDoc_STR(STRCAST("internal function")) },
1782     { STRCAST("_getWrapper"), reinterpret_cast<PyCFunction>(communicatorGetWrapper), METH_NOARGS,
1783         PyDoc_STR(STRCAST("internal function")) },
1784     { 0, 0 } /* sentinel */
1785 };
1786 
1787 namespace IcePy
1788 {
1789 
1790 PyTypeObject CommunicatorType =
1791 {
1792     /* The ob_type field must be initialized in the module init function
1793      * to be portable to Windows without using C++. */
1794     PyVarObject_HEAD_INIT(0, 0)
1795     STRCAST("IcePy.Communicator"),   /* tp_name */
1796     sizeof(CommunicatorObject),      /* tp_basicsize */
1797     0,                               /* tp_itemsize */
1798     /* methods */
1799     reinterpret_cast<destructor>(communicatorDealloc), /* tp_dealloc */
1800     0,                               /* tp_print */
1801     0,                               /* tp_getattr */
1802     0,                               /* tp_setattr */
1803     0,                               /* tp_reserved */
1804     0,                               /* tp_repr */
1805     0,                               /* tp_as_number */
1806     0,                               /* tp_as_sequence */
1807     0,                               /* tp_as_mapping */
1808     0,                               /* tp_hash */
1809     0,                               /* tp_call */
1810     0,                               /* tp_str */
1811     0,                               /* tp_getattro */
1812     0,                               /* tp_setattro */
1813     0,                               /* tp_as_buffer */
1814     Py_TPFLAGS_DEFAULT,              /* tp_flags */
1815     0,                               /* tp_doc */
1816     0,                               /* tp_traverse */
1817     0,                               /* tp_clear */
1818     0,                               /* tp_richcompare */
1819     0,                               /* tp_weaklistoffset */
1820     0,                               /* tp_iter */
1821     0,                               /* tp_iternext */
1822     CommunicatorMethods,             /* tp_methods */
1823     0,                               /* tp_members */
1824     0,                               /* tp_getset */
1825     0,                               /* tp_base */
1826     0,                               /* tp_dict */
1827     0,                               /* tp_descr_get */
1828     0,                               /* tp_descr_set */
1829     0,                               /* tp_dictoffset */
1830     reinterpret_cast<initproc>(communicatorInit), /* tp_init */
1831     0,                               /* tp_alloc */
1832     reinterpret_cast<newfunc>(communicatorNew), /* tp_new */
1833     0,                               /* tp_free */
1834     0,                               /* tp_is_gc */
1835 };
1836 
1837 }
1838 
1839 bool
initCommunicator(PyObject * module)1840 IcePy::initCommunicator(PyObject* module)
1841 {
1842     _mainThreadId = PyThread_get_thread_ident();
1843 
1844     if(PyType_Ready(&CommunicatorType) < 0)
1845     {
1846         return false;
1847     }
1848     PyTypeObject* type = &CommunicatorType; // Necessary to prevent GCC's strict-alias warnings.
1849     if(PyModule_AddObject(module, STRCAST("Communicator"), reinterpret_cast<PyObject*>(type)) < 0)
1850     {
1851         return false;
1852     }
1853 
1854     return true;
1855 }
1856 
1857 Ice::CommunicatorPtr
getCommunicator(PyObject * obj)1858 IcePy::getCommunicator(PyObject* obj)
1859 {
1860     assert(PyObject_IsInstance(obj, reinterpret_cast<PyObject*>(&CommunicatorType)));
1861     CommunicatorObject* cobj = reinterpret_cast<CommunicatorObject*>(obj);
1862     return *cobj->communicator;
1863 }
1864 
1865 PyObject*
createCommunicator(const Ice::CommunicatorPtr & communicator)1866 IcePy::createCommunicator(const Ice::CommunicatorPtr& communicator)
1867 {
1868     CommunicatorMap::iterator p = _communicatorMap.find(communicator);
1869     if(p != _communicatorMap.end())
1870     {
1871         Py_INCREF(p->second);
1872         return p->second;
1873     }
1874 
1875     CommunicatorObject* obj = communicatorNew(&CommunicatorType, 0, 0);
1876     if(obj)
1877     {
1878         obj->communicator = new Ice::CommunicatorPtr(communicator);
1879     }
1880     return (PyObject*)obj;
1881 }
1882 
1883 PyObject*
getCommunicatorWrapper(const Ice::CommunicatorPtr & communicator)1884 IcePy::getCommunicatorWrapper(const Ice::CommunicatorPtr& communicator)
1885 {
1886     CommunicatorMap::iterator p = _communicatorMap.find(communicator);
1887     assert(p != _communicatorMap.end());
1888     CommunicatorObject* obj = reinterpret_cast<CommunicatorObject*>(p->second);
1889     if(obj->wrapper)
1890     {
1891         Py_INCREF(obj->wrapper);
1892         return obj->wrapper;
1893     }
1894     else
1895     {
1896         //
1897         // Communicator must have been destroyed already.
1898         //
1899         Py_INCREF(Py_None);
1900         return Py_None;
1901     }
1902 }
1903 
1904 extern "C"
1905 PyObject*
IcePy_identityToString(PyObject *,PyObject * args)1906 IcePy_identityToString(PyObject* /*self*/, PyObject* args)
1907 {
1908     PyObject* identityType = lookupType("Ice.Identity");
1909     PyObject* obj;
1910     PyObject* mode = 0;
1911     if(!PyArg_ParseTuple(args, STRCAST("O!O"), identityType, &obj, &mode))
1912     {
1913         return 0;
1914     }
1915 
1916     Ice::Identity id;
1917     if(!getIdentity(obj, id))
1918     {
1919         return 0;
1920     }
1921 
1922     Ice::ToStringMode toStringMode = Ice::Unicode;
1923     if(mode != Py_None && PyObject_HasAttrString(mode, STRCAST("value")))
1924     {
1925         PyObjectHandle modeValue = getAttr(mode, "value", true);
1926         toStringMode = static_cast<Ice::ToStringMode>(PyLong_AsLong(modeValue.get()));
1927     }
1928 
1929     string str;
1930 
1931     try
1932     {
1933         str = identityToString(id, toStringMode);
1934     }
1935     catch(const Ice::Exception& ex)
1936     {
1937         setPythonException(ex);
1938         return 0;
1939     }
1940 
1941     return createString(str);
1942 }
1943 
1944 extern "C"
1945 PyObject*
IcePy_stringToIdentity(PyObject *,PyObject * obj)1946 IcePy_stringToIdentity(PyObject* /*self*/, PyObject* obj)
1947 {
1948     string str;
1949     if(!getStringArg(obj, "str", str))
1950     {
1951         return 0;
1952     }
1953 
1954     Ice::Identity id;
1955     try
1956     {
1957         id = Ice::stringToIdentity(str);
1958     }
1959     catch(const Ice::Exception& ex)
1960     {
1961         setPythonException(ex);
1962         return 0;
1963     }
1964 
1965     return createIdentity(id);
1966 }
1967