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