1 //
2 // Copyright (c) ZeroC, Inc. All rights reserved.
3 //
4 
5 #include <Connection.h>
6 #include <Endpoint.h>
7 #include <Types.h>
8 #include <Util.h>
9 #include <IceSSL/IceSSL.h>
10 
11 using namespace std;
12 using namespace IcePHP;
13 
14 ZEND_EXTERN_MODULE_GLOBALS(ice)
15 
16 //
17 // Class entries represent the PHP class implementations we have registered.
18 //
19 namespace IcePHP
20 {
21 
22 zend_class_entry* connectionClassEntry = 0;
23 
24 }
25 static zend_class_entry* connectionInfoClassEntry = 0;
26 static zend_class_entry* ipConnectionInfoClassEntry = 0;
27 static zend_class_entry* tcpConnectionInfoClassEntry = 0;
28 static zend_class_entry* udpConnectionInfoClassEntry = 0;
29 static zend_class_entry* wsConnectionInfoClassEntry = 0;
30 static zend_class_entry* sslConnectionInfoClassEntry = 0;
31 
32 //
33 // Ice::Connection support.
34 //
35 static zend_object_handlers _connectionHandlers;
36 static zend_object_handlers _connectionInfoHandlers;
37 
38 extern "C"
39 {
40 static zend_object_value handleConnectionAlloc(zend_class_entry* TSRMLS_DC);
41 static void handleConnectionFreeStorage(void* TSRMLS_DC);
42 static int handleConnectionCompare(zval*, zval* TSRMLS_DC);
43 
44 static zend_object_value handleConnectionInfoAlloc(zend_class_entry* TSRMLS_DC);
45 static void handleConnectionInfoFreeStorage(void* TSRMLS_DC);
46 }
47 
ZEND_METHOD(Ice_Connection,__construct)48 ZEND_METHOD(Ice_Connection, __construct)
49 {
50     runtimeError("Connection cannot be instantiated" TSRMLS_CC);
51 }
52 
ZEND_METHOD(Ice_Connection,__toString)53 ZEND_METHOD(Ice_Connection, __toString)
54 {
55     if(ZEND_NUM_ARGS() > 0)
56     {
57         WRONG_PARAM_COUNT;
58     }
59 
60     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
61     assert(_this);
62 
63     try
64     {
65         string str = _this->toString();
66         RETURN_STRINGL(STRCAST(str.c_str()), static_cast<int>(str.length()), 1);
67     }
68     catch(const IceUtil::Exception& ex)
69     {
70         throwException(ex TSRMLS_CC);
71         RETURN_NULL();
72     }
73 }
74 
ZEND_METHOD(Ice_Connection,close)75 ZEND_METHOD(Ice_Connection, close)
76 {
77     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
78     assert(_this);
79 
80     zval* mode;
81     if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("z"), &mode TSRMLS_CC) != SUCCESS)
82     {
83         RETURN_NULL();
84     }
85 
86     if(Z_TYPE_P(mode) != IS_LONG)
87     {
88         invalidArgument("value for 'mode' argument must be an enumerator of ConnectionClose" TSRMLS_CC);
89         RETURN_NULL();
90     }
91     Ice::ConnectionClose cc = static_cast<Ice::ConnectionClose>(Z_LVAL_P(mode));
92 
93     try
94     {
95         _this->close(cc);
96     }
97     catch(const IceUtil::Exception& ex)
98     {
99         throwException(ex TSRMLS_CC);
100         RETURN_NULL();
101     }
102 }
103 
ZEND_METHOD(Ice_Connection,getEndpoint)104 ZEND_METHOD(Ice_Connection, getEndpoint)
105 {
106     if(ZEND_NUM_ARGS() > 0)
107     {
108         WRONG_PARAM_COUNT;
109     }
110 
111     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
112     assert(_this);
113 
114     try
115     {
116         if(!createEndpoint(return_value, _this->getEndpoint() TSRMLS_CC))
117         {
118             RETURN_NULL();
119         }
120     }
121     catch(const IceUtil::Exception& ex)
122     {
123         throwException(ex TSRMLS_CC);
124         RETURN_NULL();
125     }
126 }
127 
ZEND_METHOD(Ice_Connection,flushBatchRequests)128 ZEND_METHOD(Ice_Connection, flushBatchRequests)
129 {
130     zval* compress;
131     if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("z"), &compress TSRMLS_CC) != SUCCESS)
132     {
133         RETURN_NULL();
134     }
135 
136     if(Z_TYPE_P(compress) != IS_LONG)
137     {
138         invalidArgument("value for 'compress' argument must be an enumerator of CompressBatch" TSRMLS_CC);
139         RETURN_NULL();
140     }
141     Ice::CompressBatch cb = static_cast<Ice::CompressBatch>(Z_LVAL_P(compress));
142 
143     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
144     assert(_this);
145 
146     try
147     {
148         _this->flushBatchRequests(cb);
149     }
150     catch(const IceUtil::Exception& ex)
151     {
152         throwException(ex TSRMLS_CC);
153         RETURN_NULL();
154     }
155 }
156 
ZEND_METHOD(Ice_Connection,heartbeat)157 ZEND_METHOD(Ice_Connection, heartbeat)
158 {
159     if(ZEND_NUM_ARGS() > 0)
160     {
161         WRONG_PARAM_COUNT;
162     }
163 
164     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
165     assert(_this);
166 
167     try
168     {
169         _this->heartbeat();
170     }
171     catch(const IceUtil::Exception& ex)
172     {
173         throwException(ex TSRMLS_CC);
174         RETURN_NULL();
175     }
176 }
177 
ZEND_METHOD(Ice_Connection,setACM)178 ZEND_METHOD(Ice_Connection, setACM)
179 {
180     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
181     assert(_this);
182 
183     zval* t;
184     zval* c;
185     zval* h;
186     if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("zzz"), &t, &c, &h TSRMLS_CC) != SUCCESS)
187     {
188         RETURN_NULL();
189     }
190 
191     IceUtil::Optional<Ice::Int> timeout;
192     IceUtil::Optional<Ice::ACMClose> close;
193     IceUtil::Optional<Ice::ACMHeartbeat> heartbeat;
194 
195     if(!isUnset(t TSRMLS_CC))
196     {
197         if(Z_TYPE_P(t) != IS_LONG)
198         {
199             invalidArgument("value for 'timeout' argument must be Unset or an integer" TSRMLS_CC);
200             RETURN_NULL();
201         }
202         timeout = static_cast<Ice::Int>(Z_LVAL_P(t));
203     }
204 
205     if(!isUnset(c TSRMLS_CC))
206     {
207         if(Z_TYPE_P(c) != IS_LONG)
208         {
209             invalidArgument("value for 'close' argument must be Unset or an enumerator of ACMClose" TSRMLS_CC);
210             RETURN_NULL();
211         }
212         close = static_cast<Ice::ACMClose>(Z_LVAL_P(c));
213     }
214 
215     if(!isUnset(h TSRMLS_CC))
216     {
217         if(Z_TYPE_P(h) != IS_LONG)
218         {
219             invalidArgument("value for 'heartbeat' argument must be Unset or an enumerator of ACMHeartbeat" TSRMLS_CC);
220             RETURN_NULL();
221         }
222         heartbeat = static_cast<Ice::ACMHeartbeat>(Z_LVAL_P(h));
223     }
224 
225     try
226     {
227         _this->setACM(timeout, close, heartbeat);
228     }
229     catch(const IceUtil::Exception& ex)
230     {
231         throwException(ex TSRMLS_CC);
232         RETURN_NULL();
233     }
234 }
235 
ZEND_METHOD(Ice_Connection,getACM)236 ZEND_METHOD(Ice_Connection, getACM)
237 {
238     if(ZEND_NUM_ARGS() > 0)
239     {
240         WRONG_PARAM_COUNT;
241     }
242 
243     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
244     assert(_this);
245 
246     try
247     {
248         Ice::ACM acm = _this->getACM();
249 
250         zend_class_entry* acmClass = idToClass("::Ice::ACM" TSRMLS_CC);
251 
252         if(object_init_ex(return_value, const_cast<zend_class_entry*>(acmClass)) != SUCCESS)
253         {
254             runtimeError("unable to initialize object of type %s" TSRMLS_CC, acmClass->name);
255             RETURN_NULL();
256         }
257 
258         add_property_long(return_value, STRCAST("timeout"), static_cast<long>(acm.timeout));
259         add_property_long(return_value, STRCAST("close"), static_cast<long>(acm.close));
260         add_property_long(return_value, STRCAST("heartbeat"), static_cast<long>(acm.heartbeat));
261     }
262     catch(const IceUtil::Exception& ex)
263     {
264         throwException(ex TSRMLS_CC);
265         RETURN_NULL();
266     }
267 }
268 
ZEND_METHOD(Ice_Connection,type)269 ZEND_METHOD(Ice_Connection, type)
270 {
271     if(ZEND_NUM_ARGS() > 0)
272     {
273         WRONG_PARAM_COUNT;
274     }
275 
276     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
277     assert(_this);
278 
279     try
280     {
281         string str = _this->type();
282         RETURN_STRINGL(STRCAST(str.c_str()), str.length(), 1);
283     }
284     catch(const IceUtil::Exception& ex)
285     {
286         throwException(ex TSRMLS_CC);
287         RETURN_NULL();
288     }
289 }
290 
ZEND_METHOD(Ice_Connection,timeout)291 ZEND_METHOD(Ice_Connection, timeout)
292 {
293     if(ZEND_NUM_ARGS() != 0)
294     {
295         WRONG_PARAM_COUNT;
296     }
297 
298     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
299     assert(_this);
300 
301     try
302     {
303         Ice::Int timeout = _this->timeout();
304         ZVAL_LONG(return_value, static_cast<long>(timeout));
305     }
306     catch(const IceUtil::Exception& ex)
307     {
308         throwException(ex TSRMLS_CC);
309         RETURN_NULL();
310     }
311 }
312 
ZEND_METHOD(Ice_Connection,toString)313 ZEND_METHOD(Ice_Connection, toString)
314 {
315     ZEND_MN(Ice_Connection___toString)(INTERNAL_FUNCTION_PARAM_PASSTHRU);
316 }
317 
ZEND_METHOD(Ice_Connection,getInfo)318 ZEND_METHOD(Ice_Connection, getInfo)
319 {
320     if(ZEND_NUM_ARGS() != 0)
321     {
322         WRONG_PARAM_COUNT;
323     }
324 
325     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
326     assert(_this);
327 
328     try
329     {
330         Ice::ConnectionInfoPtr info = _this->getInfo();
331         if(!createConnectionInfo(return_value, _this->getInfo() TSRMLS_CC))
332         {
333             RETURN_NULL();
334         }
335     }
336     catch(const IceUtil::Exception& ex)
337     {
338         throwException(ex TSRMLS_CC);
339         RETURN_NULL();
340     }
341 }
342 
ZEND_METHOD(Ice_Connection,setBufferSize)343 ZEND_METHOD(Ice_Connection, setBufferSize)
344 {
345     Ice::ConnectionPtr _this = Wrapper<Ice::ConnectionPtr>::value(getThis() TSRMLS_CC);
346     assert(_this);
347 
348     zval* r;
349     zval* s;
350     if(zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, const_cast<char*>("zz"), &r, &s TSRMLS_CC) != SUCCESS)
351     {
352         RETURN_NULL();
353     }
354 
355     int rcvSize = static_cast<int>(Z_LVAL_P(r));
356     int sndSize = static_cast<int>(Z_LVAL_P(s));
357 
358     try
359     {
360         _this->setBufferSize(rcvSize, sndSize);
361     }
362     catch(const IceUtil::Exception& ex)
363     {
364         throwException(ex TSRMLS_CC);
365         RETURN_NULL();
366     }
367 }
368 
369 #ifdef _WIN32
370 extern "C"
371 #endif
372 static zend_object_value
handleConnectionAlloc(zend_class_entry * ce TSRMLS_DC)373 handleConnectionAlloc(zend_class_entry* ce TSRMLS_DC)
374 {
375     zend_object_value result;
376 
377     Wrapper<Ice::ConnectionPtr>* obj = Wrapper<Ice::ConnectionPtr>::create(ce TSRMLS_CC);
378     assert(obj);
379 
380     result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleConnectionFreeStorage,
381                                            0 TSRMLS_CC);
382     result.handlers = &_connectionHandlers;
383 
384     return result;
385 }
386 
387 #ifdef _WIN32
388 extern "C"
389 #endif
390 static void
handleConnectionFreeStorage(void * p TSRMLS_DC)391 handleConnectionFreeStorage(void* p TSRMLS_DC)
392 {
393     Wrapper<Ice::ConnectionPtr>* obj = static_cast<Wrapper<Ice::ConnectionPtr>*>(p);
394     delete obj->ptr;
395     zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC);
396     efree(p);
397 }
398 
399 #ifdef _WIN32
400 extern "C"
401 #endif
402 static int
handleConnectionCompare(zval * zobj1,zval * zobj2 TSRMLS_DC)403 handleConnectionCompare(zval* zobj1, zval* zobj2 TSRMLS_DC)
404 {
405     //
406     // PHP guarantees that the objects have the same class.
407     //
408 
409     Ice::ConnectionPtr con1 = Wrapper<Ice::ConnectionPtr>::value(zobj1 TSRMLS_CC);
410     assert(con1);
411     Ice::ConnectionPtr con2 = Wrapper<Ice::ConnectionPtr>::value(zobj2 TSRMLS_CC);
412     assert(con2);
413 
414     if(con1 == con2)
415     {
416         return 0;
417     }
418     else if(con1 < con2)
419     {
420         return -1;
421     }
422     else
423     {
424         return 1;
425     }
426 }
427 
428 //
429 // Necessary to suppress warnings from zend_function_entry in php-5.2.
430 //
431 #if defined(__GNUC__)
432 #  pragma GCC diagnostic ignored "-Wwrite-strings"
433 #endif
434 
435 //
436 // Predefined methods for Connection.
437 //
438 static zend_function_entry _interfaceMethods[] =
439 {
440     {0, 0, 0}
441 };
442 static zend_function_entry _connectionClassMethods[] =
443 {
444     ZEND_ME(Ice_Connection, __construct, ICE_NULLPTR, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
445     ZEND_ME(Ice_Connection, __toString, ICE_NULLPTR, ZEND_ACC_PUBLIC)
446     ZEND_ME(Ice_Connection, close, ICE_NULLPTR, ZEND_ACC_PUBLIC)
447     ZEND_ME(Ice_Connection, getEndpoint, ICE_NULLPTR, ZEND_ACC_PUBLIC)
448     ZEND_ME(Ice_Connection, flushBatchRequests, ICE_NULLPTR, ZEND_ACC_PUBLIC)
449     ZEND_ME(Ice_Connection, heartbeat, ICE_NULLPTR, ZEND_ACC_PUBLIC)
450     ZEND_ME(Ice_Connection, setACM, ICE_NULLPTR, ZEND_ACC_PUBLIC)
451     ZEND_ME(Ice_Connection, getACM, ICE_NULLPTR, ZEND_ACC_PUBLIC)
452     ZEND_ME(Ice_Connection, type, ICE_NULLPTR, ZEND_ACC_PUBLIC)
453     ZEND_ME(Ice_Connection, timeout, ICE_NULLPTR, ZEND_ACC_PUBLIC)
454     ZEND_ME(Ice_Connection, toString, ICE_NULLPTR, ZEND_ACC_PUBLIC)
455     ZEND_ME(Ice_Connection, getInfo, ICE_NULLPTR, ZEND_ACC_PUBLIC)
456     ZEND_ME(Ice_Connection, setBufferSize, ICE_NULLPTR, ZEND_ACC_PUBLIC)
457     {0, 0, 0}
458 };
459 
ZEND_METHOD(Ice_ConnectionInfo,__construct)460 ZEND_METHOD(Ice_ConnectionInfo, __construct)
461 {
462     runtimeError("ConnectionInfo cannot be instantiated" TSRMLS_CC);
463 }
464 
465 //
466 // Predefined methods for ConnectionInfo.
467 //
468 static zend_function_entry _connectionInfoClassMethods[] =
469 {
470     ZEND_ME(Ice_ConnectionInfo, __construct, ICE_NULLPTR, ZEND_ACC_PRIVATE|ZEND_ACC_CTOR)
471     {0, 0, 0}
472 };
473 //
474 // enable warning again
475 //
476 #if defined(__GNUC__)
477 #  pragma GCC diagnostic error "-Wwrite-strings"
478 #endif
479 
480 #ifdef _WIN32
481 extern "C"
482 #endif
483 static zend_object_value
handleConnectionInfoAlloc(zend_class_entry * ce TSRMLS_DC)484 handleConnectionInfoAlloc(zend_class_entry* ce TSRMLS_DC)
485 {
486     zend_object_value result;
487 
488     Wrapper<Ice::ConnectionInfoPtr>* obj = Wrapper<Ice::ConnectionInfoPtr>::create(ce TSRMLS_CC);
489     assert(obj);
490 
491     result.handle = zend_objects_store_put(obj, 0, (zend_objects_free_object_storage_t)handleConnectionInfoFreeStorage,
492                                            0 TSRMLS_CC);
493     result.handlers = &_connectionInfoHandlers;
494 
495     return result;
496 }
497 
498 #ifdef _WIN32
499 extern "C"
500 #endif
501 static void
handleConnectionInfoFreeStorage(void * p TSRMLS_DC)502 handleConnectionInfoFreeStorage(void* p TSRMLS_DC)
503 {
504     Wrapper<Ice::ConnectionInfoPtr>* obj = static_cast<Wrapper<Ice::ConnectionInfoPtr>*>(p);
505     delete obj->ptr;
506     zend_object_std_dtor(static_cast<zend_object*>(p) TSRMLS_CC);
507     efree(p);
508 }
509 
510 bool
connectionInit(TSRMLS_D)511 IcePHP::connectionInit(TSRMLS_D)
512 {
513     //
514     // We register an interface and a class that implements the interface. This allows
515     // applications to safely include the Slice-generated code for the type.
516     //
517 
518     //
519     // Register the Connection interface.
520     //
521     zend_class_entry ce;
522 #ifdef ICEPHP_USE_NAMESPACES
523     INIT_NS_CLASS_ENTRY(ce, "Ice", "Connection", _interfaceMethods);
524 #else
525     INIT_CLASS_ENTRY(ce, "Ice_Connection", _interfaceMethods);
526 #endif
527     zend_class_entry* interface = zend_register_internal_interface(&ce TSRMLS_CC);
528 
529     //
530     // Register the Connection class.
531     //
532     INIT_CLASS_ENTRY(ce, "IcePHP_Connection", _connectionClassMethods);
533     ce.create_object = handleConnectionAlloc;
534     connectionClassEntry = zend_register_internal_class(&ce TSRMLS_CC);
535     memcpy(&_connectionHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
536     _connectionHandlers.compare_objects = handleConnectionCompare;
537     zend_class_implements(connectionClassEntry TSRMLS_CC, 1, interface);
538 
539     //
540     // Register the ConnectionInfo class.
541     //
542 #ifdef ICEPHP_USE_NAMESPACES
543     INIT_NS_CLASS_ENTRY(ce, "Ice", "ConnectionInfo", _connectionInfoClassMethods);
544 #else
545     INIT_CLASS_ENTRY(ce, "Ice_ConnectionInfo", _connectionInfoClassMethods);
546 #endif
547     ce.create_object = handleConnectionInfoAlloc;
548     connectionInfoClassEntry = zend_register_internal_class(&ce TSRMLS_CC);
549     memcpy(&_connectionInfoHandlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
550     zend_declare_property_null(connectionInfoClassEntry, STRCAST("underlying"), sizeof("underlying") - 1,
551                                ZEND_ACC_PUBLIC TSRMLS_CC);
552     zend_declare_property_bool(connectionInfoClassEntry, STRCAST("incoming"), sizeof("incoming") - 1, 0,
553                                ZEND_ACC_PUBLIC TSRMLS_CC);
554     zend_declare_property_string(connectionInfoClassEntry, STRCAST("adapterName"), sizeof("adapterName") - 1,
555                                  STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC);
556 
557     //
558     // Register the IPConnectionInfo class.
559     //
560 #ifdef ICEPHP_USE_NAMESPACES
561     INIT_NS_CLASS_ENTRY(ce, "Ice", "IPConnectionInfo", ICE_NULLPTR);
562 #else
563     INIT_CLASS_ENTRY(ce, "Ice_IPConnectionInfo", ICE_NULLPTR);
564 #endif
565     ce.create_object = handleConnectionInfoAlloc;
566     ipConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, connectionInfoClassEntry, ICE_NULLPTR TSRMLS_CC);
567     zend_declare_property_string(ipConnectionInfoClassEntry, STRCAST("localAddress"), sizeof("localAddress") - 1,
568                                  STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC);
569     zend_declare_property_long(ipConnectionInfoClassEntry, STRCAST("localPort"), sizeof("localPort") - 1, 0,
570                                ZEND_ACC_PUBLIC TSRMLS_CC);
571     zend_declare_property_string(ipConnectionInfoClassEntry, STRCAST("remoteAddress"), sizeof("remoteAddress") - 1,
572                                  STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC);
573     zend_declare_property_long(ipConnectionInfoClassEntry, STRCAST("remotePort"), sizeof("remotePort") - 1, 0,
574                                ZEND_ACC_PUBLIC TSRMLS_CC);
575 
576     //
577     // Register the TCPConnectionInfo class.
578     //
579 #ifdef ICEPHP_USE_NAMESPACES
580     INIT_NS_CLASS_ENTRY(ce, "Ice", "TCPConnectionInfo", ICE_NULLPTR);
581 #else
582     INIT_CLASS_ENTRY(ce, "Ice_TCPConnectionInfo", ICE_NULLPTR);
583 #endif
584     ce.create_object = handleConnectionInfoAlloc;
585     tcpConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, ipConnectionInfoClassEntry, ICE_NULLPTR TSRMLS_CC);
586 
587     //
588     // Register the UDPConnectionInfo class.
589     //
590 #ifdef ICEPHP_USE_NAMESPACES
591     INIT_NS_CLASS_ENTRY(ce, "Ice", "UDPConnectionInfo", ICE_NULLPTR);
592 #else
593     INIT_CLASS_ENTRY(ce, "Ice_UDPConnectionInfo", ICE_NULLPTR);
594 #endif
595     ce.create_object = handleConnectionInfoAlloc;
596     udpConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, ipConnectionInfoClassEntry, ICE_NULLPTR TSRMLS_CC);
597     zend_declare_property_string(udpConnectionInfoClassEntry, STRCAST("mcastAddress"), sizeof("mcastAddress") - 1,
598                                  STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC);
599     zend_declare_property_long(udpConnectionInfoClassEntry, STRCAST("mcastPort"), sizeof("mcastPort") - 1, 0,
600                                ZEND_ACC_PUBLIC TSRMLS_CC);
601 
602     //
603     // Register the WSConnectionInfo class.
604     //
605 #ifdef ICEPHP_USE_NAMESPACES
606     INIT_NS_CLASS_ENTRY(ce, "Ice", "WSConnectionInfo", ICE_NULLPTR);
607 #else
608     INIT_CLASS_ENTRY(ce, "Ice_WSConnectionInfo", ICE_NULLPTR);
609 #endif
610     ce.create_object = handleConnectionInfoAlloc;
611     wsConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, connectionInfoClassEntry, ICE_NULLPTR TSRMLS_CC);
612     zend_declare_property_string(wsConnectionInfoClassEntry, STRCAST("headers"), sizeof("headers") - 1,
613                                  STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC);
614 
615     //
616     // Register the SSLConnectionInfo class.
617     //
618 #ifdef ICEPHP_USE_NAMESPACES
619     INIT_NS_CLASS_ENTRY(ce, "Ice", "SSLConnectionInfo", ICE_NULLPTR);
620 #else
621     INIT_CLASS_ENTRY(ce, "Ice_SSLConnectionInfo", ICE_NULLPTR);
622 #endif
623     ce.create_object = handleConnectionInfoAlloc;
624     sslConnectionInfoClassEntry = zend_register_internal_class_ex(&ce, connectionInfoClassEntry, ICE_NULLPTR TSRMLS_CC);
625     zend_declare_property_string(sslConnectionInfoClassEntry, STRCAST("cipher"), sizeof("cipher") - 1,
626                                  STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC);
627     zend_declare_property_string(sslConnectionInfoClassEntry, STRCAST("certs"), sizeof("certs") - 1,
628                                  STRCAST(""), ZEND_ACC_PUBLIC TSRMLS_CC);
629     zend_declare_property_bool(sslConnectionInfoClassEntry, STRCAST("verified"), sizeof("verified") - 1, 0,
630                                ZEND_ACC_PUBLIC TSRMLS_CC);
631 
632     return true;
633 }
634 
635 bool
createConnection(zval * zv,const Ice::ConnectionPtr & p TSRMLS_DC)636 IcePHP::createConnection(zval* zv, const Ice::ConnectionPtr& p TSRMLS_DC)
637 {
638     if(object_init_ex(zv, connectionClassEntry) != SUCCESS)
639     {
640         runtimeError("unable to initialize connection" TSRMLS_CC);
641         return false;
642     }
643 
644     Wrapper<Ice::ConnectionPtr>* obj = Wrapper<Ice::ConnectionPtr>::extract(zv TSRMLS_CC);
645     assert(obj);
646     assert(!obj->ptr);
647     obj->ptr = new Ice::ConnectionPtr(p);
648 
649     return true;
650 }
651 
652 bool
fetchConnection(zval * zv,Ice::ConnectionPtr & connection TSRMLS_DC)653 IcePHP::fetchConnection(zval* zv, Ice::ConnectionPtr& connection TSRMLS_DC)
654 {
655     if(ZVAL_IS_NULL(zv))
656     {
657         connection = 0;
658     }
659     else
660     {
661         if(Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != connectionClassEntry)
662         {
663             invalidArgument("value is not a connection" TSRMLS_CC);
664             return false;
665         }
666         Wrapper<Ice::ConnectionPtr>* obj = Wrapper<Ice::ConnectionPtr>::extract(zv TSRMLS_CC);
667         if(!obj)
668         {
669             return false;
670         }
671         connection = *obj->ptr;
672     }
673     return true;
674 }
675 
676 bool
createConnectionInfo(zval * zv,const Ice::ConnectionInfoPtr & p TSRMLS_DC)677 IcePHP::createConnectionInfo(zval* zv, const Ice::ConnectionInfoPtr& p TSRMLS_DC)
678 {
679     if(!p)
680     {
681         ZVAL_NULL(zv);
682         return true;
683     }
684 
685     int status;
686     if(Ice::WSConnectionInfoPtr::dynamicCast(p))
687     {
688         Ice::WSConnectionInfoPtr info = Ice::WSConnectionInfoPtr::dynamicCast(p);
689         if((status = object_init_ex(zv, wsConnectionInfoClassEntry)) == SUCCESS)
690         {
691             zval* zmap;
692             MAKE_STD_ZVAL(zmap);
693             AutoDestroy mapDestroyer(zmap);
694             if(createStringMap(zmap, info->headers TSRMLS_CC))
695             {
696                 add_property_zval(zv, STRCAST("headers"), zmap);
697             }
698             else
699             {
700                 return false;
701             }
702         }
703     }
704     else if(Ice::TCPConnectionInfoPtr::dynamicCast(p))
705     {
706         Ice::TCPConnectionInfoPtr info = Ice::TCPConnectionInfoPtr::dynamicCast(p);
707         if((status = object_init_ex(zv, tcpConnectionInfoClassEntry)) == SUCCESS)
708         {
709             add_property_long(zv, STRCAST("rcvSize"), static_cast<long>(info->rcvSize));
710             add_property_long(zv, STRCAST("sndSize"), static_cast<long>(info->sndSize));
711         }
712     }
713     else if(Ice::UDPConnectionInfoPtr::dynamicCast(p))
714     {
715         Ice::UDPConnectionInfoPtr info = Ice::UDPConnectionInfoPtr::dynamicCast(p);
716         if((status = object_init_ex(zv, udpConnectionInfoClassEntry)) == SUCCESS)
717         {
718             add_property_string(zv, STRCAST("mcastAddress"), const_cast<char*>(info->mcastAddress.c_str()), 1);
719             add_property_long(zv, STRCAST("mcastPort"), static_cast<long>(info->mcastPort));
720             add_property_long(zv, STRCAST("rcvSize"), static_cast<long>(info->rcvSize));
721             add_property_long(zv, STRCAST("sndSize"), static_cast<long>(info->sndSize));
722         }
723     }
724     else if(IceSSL::ConnectionInfoPtr::dynamicCast(p))
725     {
726         status = object_init_ex(zv, sslConnectionInfoClassEntry);
727     }
728     else if(Ice::IPConnectionInfoPtr::dynamicCast(p))
729     {
730         status = object_init_ex(zv, ipConnectionInfoClassEntry);
731     }
732     else
733     {
734         status = object_init_ex(zv, connectionInfoClassEntry);
735     }
736 
737     if(status != SUCCESS)
738     {
739         runtimeError("unable to initialize connection info" TSRMLS_CC);
740         return false;
741     }
742 
743     if(IceSSL::ConnectionInfoPtr::dynamicCast(p))
744     {
745         IceSSL::ConnectionInfoPtr info = IceSSL::ConnectionInfoPtr::dynamicCast(p);
746         add_property_string(zv, STRCAST("cipher"), const_cast<char*>(info->cipher.c_str()), 1);
747         add_property_bool(zv, STRCAST("verified"), info->verified ? 1 : 0);
748 
749         zval* zarr;
750         MAKE_STD_ZVAL(zarr);
751         AutoDestroy listDestroyer(zarr);
752 
753         Ice::StringSeq encoded;
754         for(vector<IceSSL::CertificatePtr>::const_iterator i = info->certs.begin(); i != info->certs.end(); ++i)
755         {
756             encoded.push_back((*i)->encode());
757         }
758 
759         if(createStringArray(zarr, encoded TSRMLS_CC))
760         {
761             add_property_zval(zv, STRCAST("certs"), zarr);
762         }
763         else
764         {
765             return false;
766         }
767     }
768 
769     if(Ice::IPConnectionInfoPtr::dynamicCast(p))
770     {
771         Ice::IPConnectionInfoPtr info = Ice::IPConnectionInfoPtr::dynamicCast(p);
772         add_property_string(zv, STRCAST("localAddress"), const_cast<char*>(info->localAddress.c_str()), 1);
773         add_property_long(zv, STRCAST("localPort"), static_cast<long>(info->localPort));
774         add_property_string(zv, STRCAST("remoteAddress"), const_cast<char*>(info->remoteAddress.c_str()), 1);
775         add_property_long(zv, STRCAST("remotePort"), static_cast<long>(info->remotePort));
776     }
777 
778     zval* underlying;
779     MAKE_STD_ZVAL(underlying);
780     AutoDestroy underlyingDestroyer(underlying);
781     if(!createConnectionInfo(underlying, p->underlying TSRMLS_CC))
782     {
783         runtimeError("unable to initialize connection info" TSRMLS_CC);
784         return false;
785     }
786     add_property_zval(zv, STRCAST("underlying"), underlying);
787     add_property_bool(zv, STRCAST("incoming"), p->incoming ? 1 : 0);
788     add_property_string(zv, STRCAST("adapterName"), const_cast<char*>(p->adapterName.c_str()), 1);
789 
790     Wrapper<Ice::ConnectionInfoPtr>* obj = Wrapper<Ice::ConnectionInfoPtr>::extract(zv TSRMLS_CC);
791     assert(obj);
792     assert(!obj->ptr);
793     obj->ptr = new Ice::ConnectionInfoPtr(p);
794 
795     return true;
796 }
797