1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <Proxy.h>
6 #include <Connection.h>
7 #include <Endpoint.h>
8 #include <Util.h>
9 
10 using namespace std;
11 using namespace IcePHP;
12 
13 ZEND_EXTERN_MODULE_GLOBALS(ice)
14 
15 //
16 // Here's a brief description of how proxies are handled by this extension.
17 //
18 // A single PHP class, ObjectPrx, is registered. This is an "internal" class,
19 // i.e., implemented by this extension, and it is used to represent all proxies
20 // regardless of interface type.
21 //
22 // Like in C++, a proxy is only capable of invoking the Ice::ObjectPrx operations
23 // until it is narrowed with a checked or unchecked cast. Unlike C++, no PHP classes
24 // are created for proxies, because all marshaling activity is driven by the type
25 // definitions, not by statically-generated code.
26 //
27 // In order to perform a checked or unchecked cast, the generated code invokes
28 // ice_checkedCast or ice_uncheckedCast on the proxy to be narrowed, supplying a scoped
29 // name for the desired type. Internally, the proxy validates the scoped name and returns
30 // a new proxy containing the class or interface definition. This proxy is considered
31 // to be narrowed to that interface and therefore supports user-defined operations.
32 //
33 // Naturally, there are many predefined proxy methods (e.g., ice_getIdentity, etc.), but
34 // the proxy also needs to support user-defined operations (if it has type information).
35 // We use a Zend API hook that allows us to intercept the invocation of unknown methods
36 // on the proxy object.
37 //
38 
39 //
40 // Class entries represent the PHP class implementations we have registered.
41 //
42 namespace IcePHP
43 {
44 zend_class_entry* proxyClassEntry = 0;
45 }
46 
47 //
48 // Ice::ObjectPrx support.
49 //
50 static zend_object_handlers _handlers;
51 
52 extern "C"
53 {
54 static zend_object* handleAlloc(zend_class_entry*);
55 static void handleFreeStorage(zend_object*);
56 static zend_object* handleClone(zval*);
57 static union _zend_function* handleGetMethod(zend_object**, zend_string*, const zval*);
58 static int handleCompare(zval*, zval*);
59 }
60 
61 namespace IcePHP
62 {
63 
64 //
65 // Encapsulates proxy and type information.
66 //
67 class Proxy : public IceUtil::Shared
68 {
69 public:
70 
71     Proxy(const Ice::ObjectPrx&, const ProxyInfoPtr&, const CommunicatorInfoPtr&);
72     ~Proxy();
73 
74     bool clone(zval*, const Ice::ObjectPrx&);
75     bool cloneUntyped(zval*, const Ice::ObjectPrx&);
76     static bool create(zval*, const Ice::ObjectPrx&, const ProxyInfoPtr&, const CommunicatorInfoPtr&);
77 
78     Ice::ObjectPrx proxy;
79     ProxyInfoPtr info;
80     CommunicatorInfoPtr communicator;
81     zval* connection;
82     zval* cachedConnection;
83 };
84 typedef IceUtil::Handle<Proxy> ProxyPtr;
85 
86 } // End of namespace IcePHP
87 
ZEND_METHOD(Ice_ObjectPrx,__construct)88 ZEND_METHOD(Ice_ObjectPrx, __construct)
89 {
90     runtimeError("proxies cannot be instantiated, use stringToProxy()");
91 }
92 
ZEND_METHOD(Ice_ObjectPrx,__toString)93 ZEND_METHOD(Ice_ObjectPrx, __toString)
94 {
95     if(ZEND_NUM_ARGS() > 0)
96     {
97         WRONG_PARAM_COUNT;
98     }
99 
100     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
101     assert(_this);
102 
103     try
104     {
105         string str = _this->proxy->ice_toString();
106         RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()));
107     }
108     catch(const IceUtil::Exception& ex)
109     {
110         throwException(ex);
111         RETURN_NULL();
112     }
113 }
114 
ZEND_METHOD(Ice_ObjectPrx,ice_getCommunicator)115 ZEND_METHOD(Ice_ObjectPrx, ice_getCommunicator)
116 {
117     if(ZEND_NUM_ARGS() > 0)
118     {
119         WRONG_PARAM_COUNT;
120     }
121 
122     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
123     assert(_this);
124 
125     _this->communicator->getZval(return_value);
126 }
127 
ZEND_METHOD(Ice_ObjectPrx,ice_toString)128 ZEND_METHOD(Ice_ObjectPrx, ice_toString)
129 {
130     ZEND_MN(Ice_ObjectPrx___toString)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
131 }
132 
ZEND_METHOD(Ice_ObjectPrx,ice_getIdentity)133 ZEND_METHOD(Ice_ObjectPrx, ice_getIdentity)
134 {
135     if(ZEND_NUM_ARGS() != 0)
136     {
137         WRONG_PARAM_COUNT;
138     }
139 
140     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
141     assert(_this);
142     assert(_this->proxy);
143 
144     createIdentity(return_value, _this->proxy->ice_getIdentity());
145 }
146 
ZEND_METHOD(Ice_ObjectPrx,ice_identity)147 ZEND_METHOD(Ice_ObjectPrx, ice_identity)
148 {
149     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
150     assert(_this);
151 
152     zend_class_entry* cls = idToClass("::Ice::Identity");
153     assert(cls);
154 
155     zval *zid;
156 
157     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zid, cls) == FAILURE)
158     {
159         RETURN_NULL();
160     }
161 
162     Ice::Identity id;
163     if(extractIdentity(zid, id))
164     {
165         try
166         {
167             if(!_this->cloneUntyped(return_value, _this->proxy->ice_identity(id)))
168             {
169                 RETURN_NULL();
170             }
171         }
172         catch(const IceUtil::Exception& ex)
173         {
174             throwException(ex);
175             RETURN_NULL();
176         }
177     }
178 }
179 
ZEND_METHOD(Ice_ObjectPrx,ice_getContext)180 ZEND_METHOD(Ice_ObjectPrx, ice_getContext)
181 {
182     if(ZEND_NUM_ARGS() != 0)
183     {
184         WRONG_PARAM_COUNT;
185     }
186 
187     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
188     assert(_this);
189 
190     if(!createStringMap(return_value, _this->proxy->ice_getContext()))
191     {
192         RETURN_NULL();
193     }
194 }
195 
ZEND_METHOD(Ice_ObjectPrx,ice_context)196 ZEND_METHOD(Ice_ObjectPrx, ice_context)
197 {
198     zval* arr = 0;
199 
200     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("a"), &arr) == FAILURE)
201     {
202         RETURN_NULL();
203     }
204 
205     //
206     // Populate the context.
207     //
208     Ice::Context ctx;
209     if(arr && !extractStringMap(arr, ctx))
210     {
211         RETURN_NULL();
212     }
213 
214     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
215     assert(_this);
216 
217     try
218     {
219         if(!_this->clone(return_value, _this->proxy->ice_context(ctx)))
220         {
221             RETURN_NULL();
222         }
223     }
224     catch(const IceUtil::Exception& ex)
225     {
226         throwException(ex);
227         RETURN_NULL();
228     }
229 }
230 
ZEND_METHOD(Ice_ObjectPrx,ice_getFacet)231 ZEND_METHOD(Ice_ObjectPrx, ice_getFacet)
232 {
233     if(ZEND_NUM_ARGS() != 0)
234     {
235         WRONG_PARAM_COUNT;
236     }
237 
238     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
239     assert(_this);
240 
241     try
242     {
243         string facet = _this->proxy->ice_getFacet();
244         ZVAL_STRINGL(return_value, STRCAST(facet.c_str()), static_cast<int>(facet.length()));
245     }
246     catch(const IceUtil::Exception& ex)
247     {
248         throwException(ex);
249         RETURN_NULL();
250     }
251 }
252 
ZEND_METHOD(Ice_ObjectPrx,ice_facet)253 ZEND_METHOD(Ice_ObjectPrx, ice_facet)
254 {
255     char* name;
256     size_t len;
257 
258     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &name, &len) == FAILURE)
259     {
260         RETURN_NULL();
261     }
262 
263     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
264     assert(_this);
265 
266     try
267     {
268         if(!_this->cloneUntyped(return_value, _this->proxy->ice_facet(name)))
269         {
270             RETURN_NULL();
271         }
272     }
273     catch(const IceUtil::Exception& ex)
274     {
275         throwException(ex);
276         RETURN_NULL();
277     }
278 }
279 
ZEND_METHOD(Ice_ObjectPrx,ice_getAdapterId)280 ZEND_METHOD(Ice_ObjectPrx, ice_getAdapterId)
281 {
282     if(ZEND_NUM_ARGS() != 0)
283     {
284         WRONG_PARAM_COUNT;
285     }
286 
287     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
288     assert(_this);
289 
290     try
291     {
292         string id = _this->proxy->ice_getAdapterId();
293         ZVAL_STRINGL(return_value, STRCAST(id.c_str()), static_cast<int>(id.length()));
294     }
295     catch(const IceUtil::Exception& ex)
296     {
297         throwException(ex);
298         RETURN_NULL();
299     }
300 }
301 
ZEND_METHOD(Ice_ObjectPrx,ice_adapterId)302 ZEND_METHOD(Ice_ObjectPrx, ice_adapterId)
303 {
304     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
305     assert(_this);
306 
307     char* id;
308     size_t len;
309 
310     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &id, &len) == FAILURE)
311     {
312         RETURN_NULL();
313     }
314 
315     try
316     {
317         if(!_this->clone(return_value, _this->proxy->ice_adapterId(id)))
318         {
319             RETURN_NULL();
320         }
321     }
322     catch(const IceUtil::Exception& ex)
323     {
324         throwException(ex);
325         RETURN_NULL();
326     }
327 }
328 
ZEND_METHOD(Ice_ObjectPrx,ice_getEndpoints)329 ZEND_METHOD(Ice_ObjectPrx, ice_getEndpoints)
330 {
331     if(ZEND_NUM_ARGS() != 0)
332     {
333         WRONG_PARAM_COUNT;
334     }
335 
336     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
337     assert(_this);
338 
339     try
340     {
341         Ice::EndpointSeq endpoints = _this->proxy->ice_getEndpoints();
342 
343         array_init(return_value);
344         uint idx = 0;
345         for(Ice::EndpointSeq::const_iterator p = endpoints.begin(); p != endpoints.end(); ++p, ++idx)
346         {
347             zval elem;
348             if(!createEndpoint(&elem, *p))
349             {
350                 zval_ptr_dtor(&elem);
351                 RETURN_NULL();
352             }
353             add_index_zval(return_value, idx, &elem);
354         }
355     }
356     catch(const IceUtil::Exception& ex)
357     {
358         throwException(ex);
359         RETURN_NULL();
360     }
361 }
362 
ZEND_METHOD(Ice_ObjectPrx,ice_endpoints)363 ZEND_METHOD(Ice_ObjectPrx, ice_endpoints)
364 {
365     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
366     assert(_this);
367 
368     zval* zv;
369 
370     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("a"), &zv) == FAILURE)
371     {
372         RETURN_NULL();
373     }
374 
375     Ice::EndpointSeq seq;
376 
377     HashTable* arr = Z_ARRVAL_P(zv);
378     zval* val;
379     ZEND_HASH_FOREACH_VAL(arr, val)
380     {
381         if(Z_TYPE_P(val) != IS_OBJECT)
382         {
383             runtimeError("expected an element of type Ice::Endpoint");
384             RETURN_NULL();
385         }
386 
387         Ice::EndpointPtr endpoint;
388         if(!fetchEndpoint(val, endpoint))
389         {
390             RETURN_NULL();
391         }
392 
393         seq.push_back(endpoint);
394     }
395     ZEND_HASH_FOREACH_END();
396 
397     try
398     {
399         if(!_this->clone(return_value, _this->proxy->ice_endpoints(seq)))
400         {
401             RETURN_NULL();
402         }
403     }
404     catch(const IceUtil::Exception& ex)
405     {
406         throwException(ex);
407         RETURN_NULL();
408     }
409 }
410 
ZEND_METHOD(Ice_ObjectPrx,ice_getLocatorCacheTimeout)411 ZEND_METHOD(Ice_ObjectPrx, ice_getLocatorCacheTimeout)
412 {
413     if(ZEND_NUM_ARGS() != 0)
414     {
415         WRONG_PARAM_COUNT;
416     }
417 
418     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
419     assert(_this);
420 
421     try
422     {
423         Ice::Int timeout = _this->proxy->ice_getLocatorCacheTimeout();
424         ZVAL_LONG(return_value, static_cast<long>(timeout));
425     }
426     catch(const IceUtil::Exception& ex)
427     {
428         throwException(ex);
429         RETURN_NULL();
430     }
431 }
432 
ZEND_METHOD(Ice_ObjectPrx,ice_getConnectionId)433 ZEND_METHOD(Ice_ObjectPrx, ice_getConnectionId)
434 {
435     if(ZEND_NUM_ARGS() != 0)
436     {
437         WRONG_PARAM_COUNT;
438     }
439 
440     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
441     assert(_this);
442 
443     try
444     {
445         string connectionId = _this->proxy->ice_getConnectionId();
446         ZVAL_STRINGL(return_value, STRCAST(connectionId.c_str()), static_cast<int>(connectionId.length()));
447     }
448     catch(const IceUtil::Exception& ex)
449     {
450         throwException(ex);
451         RETURN_NULL();
452     }
453 }
454 
ZEND_METHOD(Ice_ObjectPrx,ice_locatorCacheTimeout)455 ZEND_METHOD(Ice_ObjectPrx, ice_locatorCacheTimeout)
456 {
457     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
458     assert(_this);
459 
460     zend_long l;
461     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("l"), &l) != SUCCESS)
462     {
463         RETURN_NULL();
464     }
465 
466     try
467     {
468         if(!_this->clone(return_value, _this->proxy->ice_locatorCacheTimeout(static_cast<Ice::Int>(l))))
469         {
470             RETURN_NULL();
471         }
472     }
473     catch(const IceUtil::Exception& ex)
474     {
475         throwException(ex);
476         RETURN_NULL();
477     }
478 }
479 
ZEND_METHOD(Ice_ObjectPrx,ice_isConnectionCached)480 ZEND_METHOD(Ice_ObjectPrx, ice_isConnectionCached)
481 {
482     if(ZEND_NUM_ARGS() != 0)
483     {
484         WRONG_PARAM_COUNT;
485     }
486 
487     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
488     assert(_this);
489 
490     try
491     {
492         bool b = _this->proxy->ice_isConnectionCached();
493         ZVAL_BOOL(return_value, b ? 1 : 0);
494     }
495     catch(const IceUtil::Exception& ex)
496     {
497         throwException(ex);
498         RETURN_NULL();
499     }
500 }
501 
ZEND_METHOD(Ice_ObjectPrx,ice_connectionCached)502 ZEND_METHOD(Ice_ObjectPrx, ice_connectionCached)
503 {
504     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
505     assert(_this);
506 
507     zend_bool b;
508     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("b"), &b) != SUCCESS)
509     {
510         RETURN_NULL();
511     }
512 
513     try
514     {
515         if(!_this->clone(return_value, _this->proxy->ice_connectionCached(b ? true : false)))
516         {
517             RETURN_NULL();
518         }
519     }
520     catch(const IceUtil::Exception& ex)
521     {
522         throwException(ex);
523         RETURN_NULL();
524     }
525 }
526 
ZEND_METHOD(Ice_ObjectPrx,ice_getEndpointSelection)527 ZEND_METHOD(Ice_ObjectPrx, ice_getEndpointSelection)
528 {
529     if(ZEND_NUM_ARGS() != 0)
530     {
531         WRONG_PARAM_COUNT;
532     }
533 
534     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
535     assert(_this);
536 
537     try
538     {
539         Ice::EndpointSelectionType type = _this->proxy->ice_getEndpointSelection();
540         ZVAL_LONG(return_value, type == Ice::Random ? 0 : 1);
541     }
542     catch(const IceUtil::Exception& ex)
543     {
544         throwException(ex);
545         RETURN_NULL();
546     }
547 }
548 
ZEND_METHOD(Ice_ObjectPrx,ice_endpointSelection)549 ZEND_METHOD(Ice_ObjectPrx, ice_endpointSelection)
550 {
551     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
552     assert(_this);
553 
554     zend_long l;
555     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("l"), &l) != SUCCESS)
556     {
557         RETURN_NULL();
558     }
559 
560     if(l < 0 || l > 1)
561     {
562         runtimeError("expecting Random or Ordered");
563         RETURN_NULL();
564     }
565 
566     try
567     {
568         Ice::EndpointSelectionType type = l == 0 ? Ice::Random : Ice::Ordered;
569         if(!_this->clone(return_value, _this->proxy->ice_endpointSelection(type)))
570         {
571             RETURN_NULL();
572         }
573     }
574     catch(const IceUtil::Exception& ex)
575     {
576         throwException(ex);
577         RETURN_NULL();
578     }
579 }
580 
ZEND_METHOD(Ice_ObjectPrx,ice_isSecure)581 ZEND_METHOD(Ice_ObjectPrx, ice_isSecure)
582 {
583     if(ZEND_NUM_ARGS() != 0)
584     {
585         WRONG_PARAM_COUNT;
586     }
587 
588     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
589     assert(_this);
590 
591     try
592     {
593         bool b = _this->proxy->ice_isSecure();
594         RETURN_BOOL(b ? 1 : 0);
595     }
596     catch(const IceUtil::Exception& ex)
597     {
598         throwException(ex);
599         RETURN_FALSE;
600     }
601 }
602 
ZEND_METHOD(Ice_ObjectPrx,ice_secure)603 ZEND_METHOD(Ice_ObjectPrx, ice_secure)
604 {
605     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
606     assert(_this);
607 
608     zend_bool b;
609     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("b"), &b) != SUCCESS)
610     {
611         RETURN_NULL();
612     }
613 
614     try
615     {
616         if(!_this->clone(return_value, _this->proxy->ice_secure(b ? true : false)))
617         {
618             RETURN_NULL();
619         }
620     }
621     catch(const IceUtil::Exception& ex)
622     {
623         throwException(ex);
624         RETURN_NULL();
625     }
626 }
627 
ZEND_METHOD(Ice_ObjectPrx,ice_getEncodingVersion)628 ZEND_METHOD(Ice_ObjectPrx, ice_getEncodingVersion)
629 {
630     if(ZEND_NUM_ARGS() != 0)
631     {
632         WRONG_PARAM_COUNT;
633     }
634 
635     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
636     assert(_this);
637 
638     try
639     {
640         if(!createEncodingVersion(return_value, _this->proxy->ice_getEncodingVersion()))
641         {
642             RETURN_NULL();
643         }
644     }
645     catch(const IceUtil::Exception& ex)
646     {
647         throwException(ex);
648         RETURN_NULL();
649     }
650 }
651 
ZEND_METHOD(Ice_ObjectPrx,ice_encodingVersion)652 ZEND_METHOD(Ice_ObjectPrx, ice_encodingVersion)
653 {
654     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
655     assert(_this);
656 
657     zend_class_entry* cls = idToClass("::Ice::EncodingVersion");
658     assert(cls);
659 
660     zval *zv;
661     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O"), &zv, cls) == FAILURE)
662     {
663         RETURN_NULL();
664     }
665 
666     Ice::EncodingVersion v;
667     if(extractEncodingVersion(zv, v))
668     {
669         try
670         {
671             if(!_this->clone(return_value, _this->proxy->ice_encodingVersion(v)))
672             {
673                 RETURN_NULL();
674             }
675         }
676         catch(const IceUtil::Exception& ex)
677         {
678             throwException(ex);
679             RETURN_NULL();
680         }
681     }
682 }
683 
ZEND_METHOD(Ice_ObjectPrx,ice_isPreferSecure)684 ZEND_METHOD(Ice_ObjectPrx, ice_isPreferSecure)
685 {
686     if(ZEND_NUM_ARGS() != 0)
687     {
688         WRONG_PARAM_COUNT;
689     }
690 
691     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
692     assert(_this);
693 
694     try
695     {
696         bool b = _this->proxy->ice_isPreferSecure();
697         RETURN_BOOL(b ? 1 : 0);
698     }
699     catch(const IceUtil::Exception& ex)
700     {
701         throwException(ex);
702         RETURN_FALSE;
703     }
704 }
705 
ZEND_METHOD(Ice_ObjectPrx,ice_preferSecure)706 ZEND_METHOD(Ice_ObjectPrx, ice_preferSecure)
707 {
708     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
709     assert(_this);
710 
711     zend_bool b;
712     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("b"), &b) != SUCCESS)
713     {
714         RETURN_NULL();
715     }
716 
717     try
718     {
719         if(!_this->clone(return_value, _this->proxy->ice_preferSecure(b ? true : false)))
720         {
721             RETURN_NULL();
722         }
723     }
724     catch(const IceUtil::Exception& ex)
725     {
726         throwException(ex);
727         RETURN_NULL();
728     }
729 }
730 
ZEND_METHOD(Ice_ObjectPrx,ice_getRouter)731 ZEND_METHOD(Ice_ObjectPrx, ice_getRouter)
732 {
733     if(ZEND_NUM_ARGS() != 0)
734     {
735         WRONG_PARAM_COUNT;
736     }
737 
738     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
739     assert(_this);
740 
741     try
742     {
743         Ice::RouterPrx router = _this->proxy->ice_getRouter();
744         if(router)
745         {
746             ProxyInfoPtr info = getProxyInfo("::Ice::Router");
747             if(!info)
748             {
749                 RETURN_NULL();
750             }
751 
752             assert(info);
753 
754             if(!createProxy(return_value, router, info, _this->communicator))
755             {
756                 RETURN_NULL();
757             }
758         }
759         else
760         {
761             RETURN_NULL();
762         }
763     }
764     catch(const IceUtil::Exception& ex)
765     {
766         throwException(ex);
767         RETURN_FALSE;
768     }
769 }
770 
ZEND_METHOD(Ice_ObjectPrx,ice_router)771 ZEND_METHOD(Ice_ObjectPrx, ice_router)
772 {
773     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
774     assert(_this);
775 
776     zval* zprx;
777     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!"), &zprx, proxyClassEntry) !=
778         SUCCESS)
779     {
780         RETURN_NULL();
781     }
782 
783     Ice::ObjectPrx proxy;
784     ProxyInfoPtr def;
785     if(zprx && !fetchProxy(zprx, proxy, def))
786     {
787         RETURN_NULL();
788     }
789 
790     Ice::RouterPrx router;
791     if(proxy)
792     {
793         if(!def || !def->isA("::Ice::Router"))
794         {
795             runtimeError("ice_router requires a proxy narrowed to Ice::Router");
796             RETURN_NULL();
797         }
798         router = Ice::RouterPrx::uncheckedCast(proxy);
799     }
800 
801     try
802     {
803         if(!_this->clone(return_value, _this->proxy->ice_router(router)))
804         {
805             RETURN_NULL();
806         }
807     }
808     catch(const IceUtil::Exception& ex)
809     {
810         throwException(ex);
811         RETURN_NULL();
812     }
813 }
814 
ZEND_METHOD(Ice_ObjectPrx,ice_getLocator)815 ZEND_METHOD(Ice_ObjectPrx, ice_getLocator)
816 {
817     if(ZEND_NUM_ARGS() != 0)
818     {
819         WRONG_PARAM_COUNT;
820     }
821 
822     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
823     assert(_this);
824 
825     try
826     {
827         Ice::LocatorPrx locator = _this->proxy->ice_getLocator();
828         if(locator)
829         {
830             ProxyInfoPtr info = getProxyInfo("::Ice::Locator");
831             if(!info)
832             {
833                 RETURN_NULL();
834             }
835 
836             if(!createProxy(return_value, locator, info, _this->communicator))
837             {
838                 RETURN_NULL();
839             }
840         }
841         else
842         {
843             RETURN_NULL();
844         }
845     }
846     catch(const IceUtil::Exception& ex)
847     {
848         throwException(ex);
849         RETURN_FALSE;
850     }
851 }
852 
ZEND_METHOD(Ice_ObjectPrx,ice_locator)853 ZEND_METHOD(Ice_ObjectPrx, ice_locator)
854 {
855     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
856     assert(_this);
857 
858     zval* zprx;
859     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("O!"), &zprx, proxyClassEntry) !=
860         SUCCESS)
861     {
862         RETURN_NULL();
863     }
864 
865     Ice::ObjectPrx proxy;
866     ProxyInfoPtr def;
867     if(zprx && !fetchProxy(zprx, proxy, def))
868     {
869         RETURN_NULL();
870     }
871 
872     Ice::LocatorPrx locator;
873     if(proxy)
874     {
875         if(!def || !def->isA("::Ice::Locator"))
876         {
877             runtimeError("ice_locator requires a proxy narrowed to Ice::Locator");
878             RETURN_NULL();
879         }
880         locator = Ice::LocatorPrx::uncheckedCast(proxy);
881     }
882 
883     try
884     {
885         if(!_this->clone(return_value, _this->proxy->ice_locator(locator)))
886         {
887             RETURN_NULL();
888         }
889     }
890     catch(const IceUtil::Exception& ex)
891     {
892         throwException(ex);
893         RETURN_NULL();
894     }
895 }
896 
ZEND_METHOD(Ice_ObjectPrx,ice_twoway)897 ZEND_METHOD(Ice_ObjectPrx, ice_twoway)
898 {
899     if(ZEND_NUM_ARGS() != 0)
900     {
901         WRONG_PARAM_COUNT;
902     }
903 
904     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
905     assert(_this);
906 
907     try
908     {
909         if(!_this->clone(return_value, _this->proxy->ice_twoway()))
910         {
911             RETURN_NULL();
912         }
913     }
914     catch(const IceUtil::Exception& ex)
915     {
916         throwException(ex);
917         RETURN_NULL();
918     }
919 }
920 
ZEND_METHOD(Ice_ObjectPrx,ice_isTwoway)921 ZEND_METHOD(Ice_ObjectPrx, ice_isTwoway)
922 {
923     if(ZEND_NUM_ARGS() != 0)
924     {
925         WRONG_PARAM_COUNT;
926     }
927 
928     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
929     assert(_this);
930 
931     try
932     {
933         bool b = _this->proxy->ice_isTwoway();
934         RETURN_BOOL(b ? 1 : 0);
935     }
936     catch(const IceUtil::Exception& ex)
937     {
938         throwException(ex);
939         RETURN_FALSE;
940     }
941 }
942 
ZEND_METHOD(Ice_ObjectPrx,ice_oneway)943 ZEND_METHOD(Ice_ObjectPrx, ice_oneway)
944 {
945     if(ZEND_NUM_ARGS() != 0)
946     {
947         WRONG_PARAM_COUNT;
948     }
949 
950     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
951     assert(_this);
952 
953     try
954     {
955         if(!_this->clone(return_value, _this->proxy->ice_oneway()))
956         {
957             RETURN_NULL();
958         }
959     }
960     catch(const IceUtil::Exception& ex)
961     {
962         throwException(ex);
963         RETURN_NULL();
964     }
965 }
966 
ZEND_METHOD(Ice_ObjectPrx,ice_isOneway)967 ZEND_METHOD(Ice_ObjectPrx, ice_isOneway)
968 {
969     if(ZEND_NUM_ARGS() != 0)
970     {
971         WRONG_PARAM_COUNT;
972     }
973 
974     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
975     assert(_this);
976 
977     try
978     {
979         bool b = _this->proxy->ice_isOneway();
980         RETURN_BOOL(b ? 1 : 0);
981     }
982     catch(const IceUtil::Exception& ex)
983     {
984         throwException(ex);
985         RETURN_FALSE;
986     }
987 }
988 
ZEND_METHOD(Ice_ObjectPrx,ice_batchOneway)989 ZEND_METHOD(Ice_ObjectPrx, ice_batchOneway)
990 {
991     if(ZEND_NUM_ARGS() != 0)
992     {
993         WRONG_PARAM_COUNT;
994     }
995 
996     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
997     assert(_this);
998 
999     try
1000     {
1001         if(!_this->clone(return_value, _this->proxy->ice_batchOneway()))
1002         {
1003             RETURN_NULL();
1004         }
1005     }
1006     catch(const IceUtil::Exception& ex)
1007     {
1008         throwException(ex);
1009         RETURN_NULL();
1010     }
1011 }
1012 
ZEND_METHOD(Ice_ObjectPrx,ice_isBatchOneway)1013 ZEND_METHOD(Ice_ObjectPrx, ice_isBatchOneway)
1014 {
1015     if(ZEND_NUM_ARGS() != 0)
1016     {
1017         WRONG_PARAM_COUNT;
1018     }
1019 
1020     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1021     assert(_this);
1022 
1023     try
1024     {
1025         bool b = _this->proxy->ice_isBatchOneway();
1026         RETURN_BOOL(b ? 1 : 0);
1027     }
1028     catch(const IceUtil::Exception& ex)
1029     {
1030         throwException(ex);
1031         RETURN_FALSE;
1032     }
1033 }
1034 
ZEND_METHOD(Ice_ObjectPrx,ice_datagram)1035 ZEND_METHOD(Ice_ObjectPrx, ice_datagram)
1036 {
1037     if(ZEND_NUM_ARGS() != 0)
1038     {
1039         WRONG_PARAM_COUNT;
1040     }
1041 
1042     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1043     assert(_this);
1044 
1045     try
1046     {
1047         if(!_this->clone(return_value, _this->proxy->ice_datagram()))
1048         {
1049             RETURN_NULL();
1050         }
1051     }
1052     catch(const IceUtil::Exception& ex)
1053     {
1054         throwException(ex);
1055         RETURN_NULL();
1056     }
1057 }
1058 
ZEND_METHOD(Ice_ObjectPrx,ice_isDatagram)1059 ZEND_METHOD(Ice_ObjectPrx, ice_isDatagram)
1060 {
1061     if(ZEND_NUM_ARGS() != 0)
1062     {
1063         WRONG_PARAM_COUNT;
1064     }
1065 
1066     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1067     assert(_this);
1068 
1069     try
1070     {
1071         bool b = _this->proxy->ice_isDatagram();
1072         RETURN_BOOL(b ? 1 : 0);
1073     }
1074     catch(const IceUtil::Exception& ex)
1075     {
1076         throwException(ex);
1077         RETURN_FALSE;
1078     }
1079 }
1080 
ZEND_METHOD(Ice_ObjectPrx,ice_batchDatagram)1081 ZEND_METHOD(Ice_ObjectPrx, ice_batchDatagram)
1082 {
1083     if(ZEND_NUM_ARGS() != 0)
1084     {
1085         WRONG_PARAM_COUNT;
1086     }
1087 
1088     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1089     assert(_this);
1090 
1091     try
1092     {
1093         if(!_this->clone(return_value, _this->proxy->ice_batchDatagram()))
1094         {
1095             RETURN_NULL();
1096         }
1097     }
1098     catch(const IceUtil::Exception& ex)
1099     {
1100         throwException(ex);
1101         RETURN_NULL();
1102     }
1103 }
1104 
ZEND_METHOD(Ice_ObjectPrx,ice_isBatchDatagram)1105 ZEND_METHOD(Ice_ObjectPrx, ice_isBatchDatagram)
1106 {
1107     if(ZEND_NUM_ARGS() != 0)
1108     {
1109         WRONG_PARAM_COUNT;
1110     }
1111 
1112     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1113     assert(_this);
1114 
1115     try
1116     {
1117         bool b = _this->proxy->ice_isBatchDatagram();
1118         RETURN_BOOL(b ? 1 : 0);
1119     }
1120     catch(const IceUtil::Exception& ex)
1121     {
1122         throwException(ex);
1123         RETURN_FALSE;
1124     }
1125 }
1126 
ZEND_METHOD(Ice_ObjectPrx,ice_compress)1127 ZEND_METHOD(Ice_ObjectPrx, ice_compress)
1128 {
1129     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1130     assert(_this);
1131 
1132     zend_bool b;
1133     if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("b"), &b) != SUCCESS)
1134     {
1135         RETURN_NULL();
1136     }
1137 
1138     try
1139     {
1140         if(!_this->clone(return_value, _this->proxy->ice_compress(b ? true : false)))
1141         {
1142             RETURN_NULL();
1143         }
1144     }
1145     catch(const IceUtil::Exception& ex)
1146     {
1147         throwException(ex);
1148         RETURN_NULL();
1149     }
1150 }
1151 
ZEND_METHOD(Ice_ObjectPrx,ice_getCompress)1152 ZEND_METHOD(Ice_ObjectPrx, ice_getCompress)
1153 {
1154     if(ZEND_NUM_ARGS() != 0)
1155     {
1156         WRONG_PARAM_COUNT;
1157     }
1158 
1159     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
1160     assert(_this);
1161 
1162     try
1163     {
1164         IceUtil::Optional<bool> compress = _this->proxy->ice_getCompress();
1165         if(compress)
1166         {
1167             RETURN_BOOL(*compress ? 1 : 0);
1168         }
1169         else
1170         {
1171             assignUnset(return_value TSRMLS_CC);
1172         }
1173     }
1174     catch(const IceUtil::Exception& ex)
1175     {
1176         throwException(ex TSRMLS_CC);
1177         RETURN_NULL();
1178     }
1179 }
1180 
ZEND_METHOD(Ice_ObjectPrx,ice_timeout)1181 ZEND_METHOD(Ice_ObjectPrx, ice_timeout)
1182 {
1183     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1184     assert(_this);
1185 
1186     try
1187     {
1188         zend_long l;
1189         if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("l"), &l) != SUCCESS)
1190         {
1191             RETURN_NULL();
1192         }
1193         // TODO: range check?
1194         if(!_this->clone(return_value, _this->proxy->ice_timeout(static_cast<Ice::Int>(l))))
1195         {
1196             RETURN_NULL();
1197         }
1198     }
1199     catch(const IceUtil::Exception& ex)
1200     {
1201         throwException(ex);
1202         RETURN_NULL();
1203     }
1204 }
1205 
ZEND_METHOD(Ice_ObjectPrx,ice_getTimeout)1206 ZEND_METHOD(Ice_ObjectPrx, ice_getTimeout)
1207 {
1208     if(ZEND_NUM_ARGS() != 0)
1209     {
1210         WRONG_PARAM_COUNT;
1211     }
1212 
1213     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
1214     assert(_this);
1215 
1216     try
1217     {
1218         IceUtil::Optional<int> timeout = _this->proxy->ice_getTimeout();
1219         if(timeout)
1220         {
1221             ZVAL_LONG(return_value, static_cast<long>(*timeout));
1222         }
1223         else
1224         {
1225             assignUnset(return_value TSRMLS_CC);
1226         }
1227     }
1228     catch(const IceUtil::Exception& ex)
1229     {
1230         throwException(ex TSRMLS_CC);
1231         RETURN_NULL();
1232     }
1233 }
1234 
ZEND_METHOD(Ice_ObjectPrx,ice_invocationTimeout)1235 ZEND_METHOD(Ice_ObjectPrx, ice_invocationTimeout)
1236 {
1237     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1238     assert(_this);
1239 
1240     try
1241     {
1242         zend_long l;
1243         if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("l"), &l) != SUCCESS)
1244         {
1245             RETURN_NULL();
1246         }
1247         // TODO: range check?
1248         if(!_this->clone(return_value, _this->proxy->ice_invocationTimeout(static_cast<Ice::Int>(l))))
1249         {
1250             RETURN_NULL();
1251         }
1252     }
1253     catch(const IceUtil::Exception& ex)
1254     {
1255         throwException(ex);
1256         RETURN_NULL();
1257     }
1258 }
1259 
ZEND_METHOD(Ice_ObjectPrx,ice_getInvocationTimeout)1260 ZEND_METHOD(Ice_ObjectPrx, ice_getInvocationTimeout)
1261 {
1262     if(ZEND_NUM_ARGS() != 0)
1263     {
1264         WRONG_PARAM_COUNT;
1265     }
1266 
1267     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
1268     assert(_this);
1269 
1270     try
1271     {
1272         ZVAL_LONG(return_value, static_cast<long>(_this->proxy->ice_getInvocationTimeout()));
1273     }
1274     catch(const IceUtil::Exception& ex)
1275     {
1276         throwException(ex TSRMLS_CC);
1277         RETURN_NULL();
1278     }
1279 }
1280 
ZEND_METHOD(Ice_ObjectPrx,ice_connectionId)1281 ZEND_METHOD(Ice_ObjectPrx, ice_connectionId)
1282 {
1283     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1284     assert(_this);
1285 
1286     try
1287     {
1288         char* id;
1289         size_t idLen;
1290         if(zend_parse_parameters(ZEND_NUM_ARGS(), const_cast<char*>("s"), &id, &idLen) != SUCCESS)
1291         {
1292             RETURN_NULL();
1293         }
1294         if(!_this->clone(return_value, _this->proxy->ice_connectionId(id)))
1295         {
1296             RETURN_NULL();
1297         }
1298     }
1299     catch(const IceUtil::Exception& ex)
1300     {
1301         throwException(ex);
1302         RETURN_NULL();
1303     }
1304 }
1305 
ZEND_METHOD(Ice_ObjectPrx,ice_fixed)1306 ZEND_METHOD(Ice_ObjectPrx, ice_fixed)
1307 {
1308     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis() TSRMLS_CC);
1309     assert(_this);
1310 
1311     zval* zcon;
1312     if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("O!"), &zcon, connectionClassEntry TSRMLS_CC) !=
1313         SUCCESS)
1314     {
1315         RETURN_NULL();
1316     }
1317 
1318     Ice::ConnectionPtr connection;
1319     if(zcon && !fetchConnection(zcon, connection TSRMLS_CC))
1320     {
1321         RETURN_NULL();
1322     }
1323 
1324     try
1325     {
1326         if(!_this->clone(return_value, _this->proxy->ice_fixed(connection) TSRMLS_CC))
1327         {
1328             RETURN_NULL();
1329         }
1330     }
1331     catch(const IceUtil::Exception& ex)
1332     {
1333         throwException(ex TSRMLS_CC);
1334         RETURN_NULL();
1335     }
1336 }
1337 
ZEND_METHOD(Ice_ObjectPrx,ice_getConnection)1338 ZEND_METHOD(Ice_ObjectPrx, ice_getConnection)
1339 {
1340     if(ZEND_NUM_ARGS() != 0)
1341     {
1342         WRONG_PARAM_COUNT;
1343     }
1344 
1345     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1346     assert(_this);
1347 
1348     try
1349     {
1350         Ice::ConnectionPtr con = _this->proxy->ice_getConnection();
1351         if(!createConnection(return_value, con))
1352         {
1353             RETURN_NULL();
1354         }
1355     }
1356     catch(const IceUtil::Exception& ex)
1357     {
1358         throwException(ex);
1359         RETURN_NULL();
1360     }
1361 }
1362 
ZEND_METHOD(Ice_ObjectPrx,ice_getCachedConnection)1363 ZEND_METHOD(Ice_ObjectPrx, ice_getCachedConnection)
1364 {
1365     if(ZEND_NUM_ARGS() != 0)
1366     {
1367         WRONG_PARAM_COUNT;
1368     }
1369 
1370     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1371     assert(_this);
1372 
1373     try
1374     {
1375         Ice::ConnectionPtr con = _this->proxy->ice_getCachedConnection();
1376         if(!con || !createConnection(return_value, con))
1377         {
1378             RETURN_NULL();
1379         }
1380     }
1381     catch(const IceUtil::Exception& ex)
1382     {
1383         throwException(ex);
1384         RETURN_NULL();
1385     }
1386 }
1387 
ZEND_METHOD(Ice_ObjectPrx,ice_flushBatchRequests)1388 ZEND_METHOD(Ice_ObjectPrx, ice_flushBatchRequests)
1389 {
1390     if(ZEND_NUM_ARGS() != 0)
1391     {
1392         WRONG_PARAM_COUNT;
1393     }
1394 
1395     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1396     assert(_this);
1397 
1398     try
1399     {
1400         _this->proxy->ice_flushBatchRequests();
1401     }
1402     catch(const IceUtil::Exception& ex)
1403     {
1404         throwException(ex);
1405         RETURN_NULL();
1406     }
1407 }
1408 
1409 static void
do_cast(INTERNAL_FUNCTION_PARAMETERS,bool check)1410 do_cast(INTERNAL_FUNCTION_PARAMETERS, bool check)
1411 {
1412     //
1413     // First argument is required and should be a scoped name. The second and third arguments
1414     // are optional and represent a facet name, a context, or a facet name followed by a context.
1415     //
1416     if(ZEND_NUM_ARGS() < 1 || ZEND_NUM_ARGS() > 3)
1417     {
1418         WRONG_PARAM_COUNT;
1419     }
1420 
1421     char* id;
1422     size_t idLen;
1423     char* facet = 0;
1424     size_t facetLen;
1425     zval* arr = 0;
1426 
1427     if(zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), const_cast<char*>("s|s!a!"), &id,
1428                                 &idLen, &facet, &facetLen, &arr) == FAILURE)
1429     {
1430         facet = 0;
1431         if(zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), const_cast<char*>("s|a!"), &id,
1432                                     &idLen, &arr) == FAILURE)
1433         {
1434             php_error(E_ERROR, "%s() requires a type id followed by an optional facet and/or context",
1435                       get_active_function_name());
1436             return;
1437         }
1438     }
1439 
1440     ProxyPtr _this = Wrapper<ProxyPtr>::value(getThis());
1441     assert(_this);
1442 
1443     //
1444     // Populate the context.
1445     //
1446     Ice::Context ctx;
1447     if(arr && !extractStringMap(arr, ctx))
1448     {
1449         RETURN_NULL();
1450     }
1451 
1452     try
1453     {
1454         ProxyInfoPtr info = getProxyInfo(id);
1455         if(!info)
1456         {
1457             RETURN_NULL();
1458         }
1459 
1460         Ice::ObjectPrx prx = _this->proxy;
1461         if(facet)
1462         {
1463             prx = prx->ice_facet(facet);
1464         }
1465 
1466         if(arr)
1467         {
1468             prx = prx->ice_context(ctx);
1469         }
1470 
1471         if(check)
1472         {
1473             //
1474             // Verify that the object supports the requested type.
1475             //
1476             if(!prx->ice_isA(info->id))
1477             {
1478                 RETURN_NULL();
1479             }
1480         }
1481 
1482         if(!createProxy(return_value, prx, info, _this->communicator))
1483         {
1484             RETURN_NULL();
1485         }
1486     }
1487     catch(const Ice::FacetNotExistException&)
1488     {
1489         // Ignore.
1490     }
1491     catch(const IceUtil::Exception& ex)
1492     {
1493         throwException(ex);
1494         RETVAL_FALSE;
1495     }
1496 }
1497 
ZEND_METHOD(Ice_ObjectPrx,ice_uncheckedCast)1498 ZEND_METHOD(Ice_ObjectPrx, ice_uncheckedCast)
1499 {
1500     do_cast(INTERNAL_FUNCTION_PARAM_PASSTHRU, false);
1501 }
1502 
ZEND_METHOD(Ice_ObjectPrx,ice_checkedCast)1503 ZEND_METHOD(Ice_ObjectPrx, ice_checkedCast)
1504 {
1505     do_cast(INTERNAL_FUNCTION_PARAM_PASSTHRU, true);
1506 }
1507 
Proxy(const Ice::ObjectPrx & p,const ProxyInfoPtr & i,const CommunicatorInfoPtr & comm)1508 IcePHP::Proxy::Proxy(const Ice::ObjectPrx& p, const ProxyInfoPtr& i, const CommunicatorInfoPtr& comm) :
1509     proxy(p), info(i), communicator(comm), connection(0), cachedConnection(0)
1510 {
1511     //
1512     // We want to ensure that the PHP object corresponding to the communicator is
1513     // not destroyed until after this proxy is destroyed.
1514     //
1515     communicator->addRef();
1516 }
1517 
~Proxy()1518 IcePHP::Proxy::~Proxy()
1519 {
1520     communicator->decRef();
1521     if(connection)
1522     {
1523         zval_ptr_dtor(connection);
1524     }
1525     if(cachedConnection)
1526     {
1527         zval_ptr_dtor(cachedConnection);
1528     }
1529 }
1530 
1531 bool
clone(zval * zv,const Ice::ObjectPrx & p)1532 IcePHP::Proxy::clone(zval* zv, const Ice::ObjectPrx& p)
1533 {
1534     return create(zv, p, info, communicator);
1535 }
1536 
1537 bool
cloneUntyped(zval * zv,const Ice::ObjectPrx & p)1538 IcePHP::Proxy::cloneUntyped(zval* zv, const Ice::ObjectPrx& p)
1539 {
1540     return create(zv, p, 0, communicator);
1541 }
1542 
1543 bool
create(zval * zv,const Ice::ObjectPrx & p,const ProxyInfoPtr & info,const CommunicatorInfoPtr & comm)1544 IcePHP::Proxy::create(zval* zv, const Ice::ObjectPrx& p, const ProxyInfoPtr& info, const CommunicatorInfoPtr& comm)
1545 {
1546     ProxyInfoPtr prx = info;
1547     if(!prx)
1548     {
1549         prx = getProxyInfo("::Ice::Object");
1550         assert(prx);
1551     }
1552 
1553     if(object_init_ex(zv, proxyClassEntry) != SUCCESS)
1554     {
1555         runtimeError("unable to initialize proxy");
1556         return false;
1557     }
1558 
1559     Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(zv);
1560     ProxyPtr proxy = new Proxy(p, prx, comm);
1561     assert(!obj->ptr);
1562     obj->ptr = new ProxyPtr(proxy);
1563     return true;
1564 }
1565 
1566 #ifdef _WIN32
1567 extern "C"
1568 #endif
1569 static zend_object*
handleAlloc(zend_class_entry * ce)1570 handleAlloc(zend_class_entry* ce)
1571 {
1572     Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::create(ce);
1573     assert(obj);
1574 
1575     obj->zobj.handlers = &_handlers;
1576 
1577     return &obj->zobj;
1578 }
1579 
1580 #ifdef _WIN32
1581 extern "C"
1582 #endif
1583 static void
handleFreeStorage(zend_object * object)1584 handleFreeStorage(zend_object* object)
1585 {
1586     Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::fetch(object);
1587     delete obj->ptr;
1588     zend_object_std_dtor(object);
1589 }
1590 
1591 #ifdef _WIN32
1592 extern "C"
1593 #endif
1594 static zend_object*
handleClone(zval * zv)1595 handleClone(zval* zv)
1596 {
1597     //
1598     // Create a new object that shares a C++ proxy instance with this object.
1599     //
1600 
1601     ProxyPtr obj = Wrapper<ProxyPtr>::value(zv);
1602     assert(obj);
1603 
1604     zval clone;
1605     if(!obj->clone(&clone, obj->proxy))
1606     {
1607         return 0;
1608     }
1609 
1610     return Z_OBJ(clone);
1611 }
1612 
1613 #ifdef _WIN32
1614 extern "C"
1615 #endif
1616 static union _zend_function*
handleGetMethod(zend_object ** object,zend_string * name,const zval * key)1617 handleGetMethod(zend_object **object, zend_string *name, const zval *key )
1618 {
1619     zend_function* result;
1620     //
1621     // First delegate to the standard implementation of get_method. This will find
1622     // any of our predefined proxy methods. If it returns 0, then we return a
1623     // function that will check the class definition.
1624     //
1625     result = zend_get_std_object_handlers()->get_method(object, name, key);
1626     if(!result)
1627     {
1628         Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::fetch(*object);
1629         assert(obj->ptr);
1630         ProxyPtr _this = *obj->ptr;
1631 
1632         ProxyInfoPtr info = _this->info;
1633         assert(info);
1634 
1635         OperationPtr op = info->getOperation(name->val);
1636         if(!op)
1637         {
1638             //
1639             // Returning 0 causes PHP to report an "undefined method" error.
1640             //
1641             return 0;
1642         }
1643 
1644         result = op->function();
1645     }
1646 
1647     return result;
1648 }
1649 
1650 #ifdef _WIN32
1651 extern "C"
1652 #endif
1653 static int
handleCompare(zval * zobj1,zval * zobj2)1654 handleCompare(zval* zobj1, zval* zobj2)
1655 {
1656     //
1657     // PHP guarantees that the objects have the same class.
1658     //
1659 
1660     Wrapper<ProxyPtr>* obj1 = Wrapper<ProxyPtr>::extract(zobj1);
1661     assert(obj1->ptr);
1662     ProxyPtr _this1 = *obj1->ptr;
1663     Ice::ObjectPrx prx1 = _this1->proxy;
1664 
1665     Wrapper<ProxyPtr>* obj2 = Wrapper<ProxyPtr>::extract(zobj2);
1666     assert(obj2->ptr);
1667     ProxyPtr _this2 = *obj2->ptr;
1668     Ice::ObjectPrx prx2 = _this2->proxy;
1669 
1670     if(prx1 == prx2)
1671     {
1672         return 0;
1673     }
1674     else if(prx1 < prx2)
1675     {
1676         return -1;
1677     }
1678     else
1679     {
1680         return 1;
1681     }
1682 }
1683 
1684 //
1685 // Necessary to suppress warnings from zend_function_entry in php-5.2.
1686 //
1687 #if defined(__GNUC__)
1688 #  pragma GCC diagnostic ignored "-Wwrite-strings"
1689 #endif
1690 
1691 //
1692 // Predefined methods for ObjectPrx.
1693 //
1694 static zend_function_entry _proxyMethods[] =
1695 {
1696     ZEND_ME(Ice_ObjectPrx, __construct, ICE_NULLPTR, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
1697     ZEND_ME(Ice_ObjectPrx, __toString, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1698     ZEND_ME(Ice_ObjectPrx, ice_getCommunicator, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1699     ZEND_ME(Ice_ObjectPrx, ice_toString, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1700     ZEND_ME(Ice_ObjectPrx, ice_getIdentity, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1701     ZEND_ME(Ice_ObjectPrx, ice_identity, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1702     ZEND_ME(Ice_ObjectPrx, ice_getContext, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1703     ZEND_ME(Ice_ObjectPrx, ice_context, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1704     ZEND_ME(Ice_ObjectPrx, ice_getFacet, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1705     ZEND_ME(Ice_ObjectPrx, ice_facet, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1706     ZEND_ME(Ice_ObjectPrx, ice_getAdapterId, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1707     ZEND_ME(Ice_ObjectPrx, ice_adapterId, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1708     ZEND_ME(Ice_ObjectPrx, ice_getEndpoints, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1709     ZEND_ME(Ice_ObjectPrx, ice_endpoints, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1710     ZEND_ME(Ice_ObjectPrx, ice_getLocatorCacheTimeout, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1711     ZEND_ME(Ice_ObjectPrx, ice_getConnectionId, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1712     ZEND_ME(Ice_ObjectPrx, ice_locatorCacheTimeout, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1713     ZEND_ME(Ice_ObjectPrx, ice_isConnectionCached, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1714     ZEND_ME(Ice_ObjectPrx, ice_connectionCached, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1715     ZEND_ME(Ice_ObjectPrx, ice_getEndpointSelection, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1716     ZEND_ME(Ice_ObjectPrx, ice_endpointSelection, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1717     ZEND_ME(Ice_ObjectPrx, ice_isSecure, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1718     ZEND_ME(Ice_ObjectPrx, ice_secure, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1719     ZEND_ME(Ice_ObjectPrx, ice_getEncodingVersion, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1720     ZEND_ME(Ice_ObjectPrx, ice_encodingVersion, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1721     ZEND_ME(Ice_ObjectPrx, ice_isPreferSecure, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1722     ZEND_ME(Ice_ObjectPrx, ice_preferSecure, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1723     ZEND_ME(Ice_ObjectPrx, ice_getRouter, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1724     ZEND_ME(Ice_ObjectPrx, ice_router, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1725     ZEND_ME(Ice_ObjectPrx, ice_getLocator, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1726     ZEND_ME(Ice_ObjectPrx, ice_locator, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1727     ZEND_ME(Ice_ObjectPrx, ice_twoway, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1728     ZEND_ME(Ice_ObjectPrx, ice_isTwoway, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1729     ZEND_ME(Ice_ObjectPrx, ice_oneway, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1730     ZEND_ME(Ice_ObjectPrx, ice_isOneway, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1731     ZEND_ME(Ice_ObjectPrx, ice_batchOneway, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1732     ZEND_ME(Ice_ObjectPrx, ice_isBatchOneway, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1733     ZEND_ME(Ice_ObjectPrx, ice_datagram, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1734     ZEND_ME(Ice_ObjectPrx, ice_isDatagram, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1735     ZEND_ME(Ice_ObjectPrx, ice_batchDatagram, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1736     ZEND_ME(Ice_ObjectPrx, ice_isBatchDatagram, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1737     ZEND_ME(Ice_ObjectPrx, ice_compress, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1738     ZEND_ME(Ice_ObjectPrx, ice_getCompress, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1739     ZEND_ME(Ice_ObjectPrx, ice_timeout, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1740     ZEND_ME(Ice_ObjectPrx, ice_getTimeout, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1741     ZEND_ME(Ice_ObjectPrx, ice_invocationTimeout, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1742     ZEND_ME(Ice_ObjectPrx, ice_getInvocationTimeout, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1743     ZEND_ME(Ice_ObjectPrx, ice_connectionId, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1744     ZEND_ME(Ice_ObjectPrx, ice_fixed, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1745     ZEND_ME(Ice_ObjectPrx, ice_getConnection, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1746     ZEND_ME(Ice_ObjectPrx, ice_getCachedConnection, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1747     ZEND_ME(Ice_ObjectPrx, ice_flushBatchRequests, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1748     ZEND_ME(Ice_ObjectPrx, ice_uncheckedCast, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1749     ZEND_ME(Ice_ObjectPrx, ice_checkedCast, ICE_NULLPTR, ZEND_ACC_PUBLIC)
1750     {0, 0, 0}
1751 };
1752 
1753 //
1754 // enable warning again
1755 //
1756 #if defined(__GNUC__)
1757 #  pragma GCC diagnostic error "-Wwrite-strings"
1758 #endif
1759 
1760 bool
proxyInit(void)1761 IcePHP::proxyInit(void)
1762 {
1763     //
1764     // Register the ObjectPrx class.
1765     //
1766     zend_class_entry ce;
1767 #ifdef ICEPHP_USE_NAMESPACES
1768     INIT_NS_CLASS_ENTRY(ce, "Ice", "ObjectPrx", _proxyMethods);
1769 #else
1770     INIT_CLASS_ENTRY(ce, "Ice_ObjectPrx", _proxyMethods);
1771 #endif
1772     ce.create_object = handleAlloc;
1773     proxyClassEntry = zend_register_internal_class(&ce);
1774     //proxyClassEntry->ce_flags |= ZEND_ACC_EXPLICIT_ABSTRACT_CLASS;
1775     memcpy(&_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
1776     _handlers.clone_obj = handleClone;
1777     _handlers.get_method = handleGetMethod;
1778     _handlers.compare_objects = handleCompare;
1779     _handlers.free_obj = handleFreeStorage;
1780     _handlers.offset =  XtOffsetOf(Wrapper<ProxyPtr>, zobj);
1781 
1782     return true;
1783 }
1784 
1785 bool
createProxy(zval * zv,const Ice::ObjectPrx & p,const CommunicatorInfoPtr & comm)1786 IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const CommunicatorInfoPtr& comm)
1787 {
1788     return Proxy::create(zv, p, 0, comm);
1789 }
1790 
1791 bool
createProxy(zval * zv,const Ice::ObjectPrx & p,const ProxyInfoPtr & info,const CommunicatorInfoPtr & comm)1792 IcePHP::createProxy(zval* zv, const Ice::ObjectPrx& p, const ProxyInfoPtr& info, const CommunicatorInfoPtr& comm
1793                    )
1794 {
1795     return Proxy::create(zv, p, info, comm);
1796 }
1797 
1798 bool
fetchProxy(zval * zv,Ice::ObjectPrx & prx,ProxyInfoPtr & info)1799 IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ProxyInfoPtr& info)
1800 {
1801     CommunicatorInfoPtr comm;
1802     return fetchProxy(zv, prx, info, comm);
1803 }
1804 
1805 bool
fetchProxy(zval * zv,Ice::ObjectPrx & prx,ProxyInfoPtr & info,CommunicatorInfoPtr & comm)1806 IcePHP::fetchProxy(zval* zv, Ice::ObjectPrx& prx, ProxyInfoPtr& info, CommunicatorInfoPtr& comm)
1807 {
1808     if(!ZVAL_IS_NULL(zv))
1809     {
1810         if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != proxyClassEntry)
1811         {
1812             invalidArgument("value is not a proxy");
1813             return false;
1814         }
1815         Wrapper<ProxyPtr>* obj = Wrapper<ProxyPtr>::extract(zv);
1816         if(!obj)
1817         {
1818             runtimeError("unable to retrieve proxy object from object store");
1819             return false;
1820         }
1821         assert(obj->ptr);
1822         prx = (*obj->ptr)->proxy;
1823         info = (*obj->ptr)->info;
1824         comm = (*obj->ptr)->communicator;
1825     }
1826     return true;
1827 }
1828