// // Copyright (c) ZeroC, Inc. All rights reserved. // #import #import #import #import #import #import #import #import #import #define CONNECTION dynamic_cast(static_cast(cxxObject_)) namespace { std::vector* connectionInfoClasses = 0; } namespace IceObjC { void registerConnectionInfoClass(Class cl) { if(!connectionInfoClasses) { connectionInfoClasses = new std::vector(); } connectionInfoClasses->push_back(cl); } } @implementation ICEConnectionInfo (ICEInternal) +(id) checkedConnectionInfoWithConnectionInfo:(Ice::ConnectionInfo*)__unused connectionInfo { assert(false); return nil; } +(id) connectionInfoWithConnectionInfo:(NSValue*)v { Ice::ConnectionInfo* info = dynamic_cast(reinterpret_cast(v.pointerValue)); if(!info) { return nil; } Ice::UDPConnectionInfoPtr udpInfo = Ice::UDPConnectionInfoPtr::dynamicCast(info); if(udpInfo) { return [[ICEUDPConnectionInfo alloc] initWithUDPConnectionInfo:udpInfo.get()]; } Ice::WSConnectionInfoPtr wsInfo = Ice::WSConnectionInfoPtr::dynamicCast(info); if(wsInfo) { return [[ICEWSConnectionInfo alloc] initWithWSConnectionInfo:wsInfo.get()]; } Ice::TCPConnectionInfoPtr tcpInfo = Ice::TCPConnectionInfoPtr::dynamicCast(info); if(tcpInfo) { return [[ICETCPConnectionInfo alloc] initWithTCPConnectionInfo:tcpInfo.get()]; } if(connectionInfoClasses) { for(std::vector::const_iterator p = connectionInfoClasses->begin(); p != connectionInfoClasses->end(); ++p) { ICEConnectionInfo* r = [*p checkedConnectionInfoWithConnectionInfo:info]; if(r) { return r; } } } Ice::IPConnectionInfoPtr ipInfo = Ice::IPConnectionInfoPtr::dynamicCast(info); if(ipInfo) { return [[ICEIPConnectionInfo alloc] initWithIPConnectionInfo:ipInfo.get()]; } return [[ICEConnectionInfo alloc] initWithConnectionInfo:info]; } -(id) initWithConnectionInfo:(Ice::ConnectionInfo*)connectionInfo { self = [super initWithCxxObject:connectionInfo]; if(self != nil) { self->underlying = [ICEConnectionInfo localObjectWithCxxObjectNoAutoRelease:connectionInfo->underlying.get() allocator:@selector(connectionInfoWithConnectionInfo:)]; self->incoming = connectionInfo->incoming; self->adapterName = [[NSString alloc] initWithUTF8String:connectionInfo->adapterName.c_str()]; self->connectionId = [[NSString alloc] initWithUTF8String:connectionInfo->connectionId.c_str()]; } return self; } @end @implementation ICEIPConnectionInfo (ICEInternal) -(id) initWithIPConnectionInfo:(Ice::IPConnectionInfo*)ipConnectionInfo { self = [super initWithConnectionInfo:ipConnectionInfo]; if(self) { self->localAddress = [[NSString alloc] initWithUTF8String:ipConnectionInfo->localAddress.c_str()]; self->localPort = ipConnectionInfo->localPort; self->remoteAddress = [[NSString alloc] initWithUTF8String:ipConnectionInfo->remoteAddress.c_str()]; self->remotePort = ipConnectionInfo->remotePort; } return self; } @end @implementation ICETCPConnectionInfo (ICEInternal) -(id) initWithTCPConnectionInfo:(Ice::TCPConnectionInfo*)tcpConnectionInfo { self = [super initWithIPConnectionInfo:tcpConnectionInfo]; if(self) { self->rcvSize = tcpConnectionInfo->rcvSize; self->sndSize = tcpConnectionInfo->sndSize; } return self; } @end @implementation ICEUDPConnectionInfo (ICEInternal) -(id) initWithUDPConnectionInfo:(Ice::UDPConnectionInfo*)udpConnectionInfo { self = [super initWithIPConnectionInfo:udpConnectionInfo]; if(self) { self->mcastAddress = [[NSString alloc] initWithUTF8String:udpConnectionInfo->mcastAddress.c_str()]; self->mcastPort = udpConnectionInfo->mcastPort; self->rcvSize = udpConnectionInfo->rcvSize; self->sndSize = udpConnectionInfo->sndSize; } return self; } @end @implementation ICEWSConnectionInfo (ICEInternal) -(id) initWithWSConnectionInfo:(Ice::WSConnectionInfo*)wsConnectionInfo { self = [super initWithConnectionInfo:wsConnectionInfo]; if(self) { self->headers = toNSDictionary(wsConnectionInfo->headers); } return self; } @end namespace { class CloseCallbackI : public Ice::CloseCallback { public: CloseCallbackI(id connection, ICECloseCallback callback) : _connection(connection), _callback(Block_copy(callback)) { [_connection retain]; } ~CloseCallbackI() { [_connection release]; [_callback release]; } void closed(const Ice::ConnectionPtr&) { NSException* ex = nil; @autoreleasepool { @try { _callback(_connection); } @catch(id e) { ex = [e retain]; } } if(ex != nil) { rethrowCxxException(ex, true); // True = release the exception. } } private: id _connection; ICECloseCallback _callback; }; class HeartbeatCallbackI : public Ice::HeartbeatCallback { public: HeartbeatCallbackI(id connection, ICEHeartbeatCallback callback) : _connection(connection), _callback(Block_copy(callback)) { [_connection retain]; } ~HeartbeatCallbackI() { [_connection release]; [_callback release]; } void heartbeat(const Ice::ConnectionPtr&) { NSException* ex = nil; @autoreleasepool { @try { _callback(_connection); } @catch(id e) { ex = [e retain]; } } if(ex != nil) { rethrowCxxException(ex, true); // True = release the exception. } } private: id _connection; ICEHeartbeatCallback _callback; }; } @implementation ICEConnection -(void) close:(ICEConnectionClose)mode { NSException* nsex = nil; try { CONNECTION->close((Ice::ConnectionClose)mode); } catch(const std::exception& ex) { nsex = toObjCException(ex); } if(nsex != nil) { @throw nsex; } } -(id) createProxy:(ICEIdentity*)identity { NSException* nsex = nil; try { return [ICEObjectPrx iceObjectPrxWithObjectPrx:CONNECTION->createProxy([identity identity])]; } catch(const std::exception& ex) { nsex = toObjCException(ex); } @throw nsex; return nil; // Keep the compiler happy. } -(void) setAdapter:(id)adapter { NSException* nsex = nil; try { CONNECTION->setAdapter([(ICEObjectAdapter*)adapter adapter]); } catch(const std::exception& ex) { nsex = toObjCException(ex); } if(nsex != nil) { @throw nsex; } } -(id) getAdapter { NSException* nsex = nil; try { return [ICEObjectAdapter localObjectWithCxxObject:CONNECTION->getAdapter().get()]; } catch(const std::exception& ex) { nsex = toObjCException(ex); } @throw nsex; return nil; // Keep the compiler happy. } -(void) flushBatchRequests:(ICECompressBatch)compress { NSException* nsex = nil; try { CONNECTION->flushBatchRequests((Ice::CompressBatch)compress); } catch(const std::exception& ex) { nsex = toObjCException(ex); } if(nsex != nil) { @throw nsex; } } -(id) begin_flushBatchRequests:(ICECompressBatch)compress { return beginCppCall(^(Ice::AsyncResultPtr& result) { result = CONNECTION->begin_flushBatchRequests((Ice::CompressBatch)compress); }); } -(id) begin_flushBatchRequests:(ICECompressBatch)compress exception:(void(^)(ICEException*))exception { return [self begin_flushBatchRequests:compress exception:exception sent:nil]; } -(id) begin_flushBatchRequests:(ICECompressBatch)compress exception:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent { return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) { result = CONNECTION->begin_flushBatchRequests((Ice::CompressBatch)compress, cb); }, ^(const Ice::AsyncResultPtr& result) { CONNECTION->end_flushBatchRequests(result); }, exception, sent); } -(void) end_flushBatchRequests:(id)result { endCppCall(^(const Ice::AsyncResultPtr& r) { CONNECTION->end_flushBatchRequests(r); }, result); } -(void) setCloseCallback:(ICECloseCallback)callback { CONNECTION->setCloseCallback(new CloseCallbackI(self, callback)); } -(void) setHeartbeatCallback:(ICEHeartbeatCallback)callback { CONNECTION->setHeartbeatCallback(new HeartbeatCallbackI(self, callback)); } -(void) heartbeat { NSException* nsex = nil; try { CONNECTION->heartbeat(); } catch(const std::exception& ex) { nsex = toObjCException(ex); } if(nsex != nil) { @throw nsex; } } -(id) begin_heartbeat { return beginCppCall(^(Ice::AsyncResultPtr& result) { result = CONNECTION->begin_heartbeat(); }); } -(id) begin_heartbeat:(void(^)(ICEException*))exception { return [self begin_heartbeat:exception sent:nil]; } -(id) begin_heartbeat:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent { return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) { result = CONNECTION->begin_heartbeat(cb); }, ^(const Ice::AsyncResultPtr& result) { CONNECTION->end_heartbeat(result); }, exception, sent); } -(void) end_heartbeat:(id)result { endCppCall(^(const Ice::AsyncResultPtr& r) { CONNECTION->end_heartbeat(r); }, result); } -(void) setACM:(id)timeout close:(id)close heartbeat:(id)heartbeat { IceUtil::Optional to; ICEInt intValue; if([ICEOptionalGetter getInt:timeout value:&intValue]) { to = intValue; } IceUtil::Optional c; if([ICEOptionalGetter getInt:close value:&intValue]) { c = (Ice::ACMClose)intValue; } IceUtil::Optional hb; if([ICEOptionalGetter getInt:heartbeat value:&intValue]) { hb = (Ice::ACMHeartbeat)intValue; } NSException* nsex; try { CONNECTION->setACM(to, c, hb); return; } catch(const std::exception& ex) { nsex = toObjCException(ex); } @throw nsex; } -(ICEACM*) getACM { Ice::ACM acm = CONNECTION->getACM(); return [ICEACM acm:acm.timeout close:(ICEACMClose)acm.close heartbeat:(ICEACMHeartbeat)acm.heartbeat]; } -(NSMutableString*) type { return [toNSMutableString(CONNECTION->type()) autorelease]; } -(ICEInt) timeout { return CONNECTION->timeout(); } -(NSMutableString*) toString { return [toNSMutableString(CONNECTION->toString()) autorelease]; } -(NSString*) description { return [toNSString(CONNECTION->toString()) autorelease]; } -(ICEConnectionInfo*) getInfo { NSException* nsex = nil; try { return [ICEConnectionInfo localObjectWithCxxObject:CONNECTION->getInfo().get() allocator:@selector(connectionInfoWithConnectionInfo:)]; } catch(const std::exception& ex) { nsex = toObjCException(ex); } if(nsex != nil) { @throw nsex; } return nil; } -(void) setBufferSize:(int)rcvSize sndSize:(int)sndSize { NSException* nsex = nil; try { CONNECTION->setBufferSize(rcvSize, sndSize); } catch(const std::exception& ex) { nsex = toObjCException(ex); } if(nsex != nil) { @throw nsex; } } -(void) throwException { NSException* nsex = nil; try { CONNECTION->throwException(); } catch(const std::exception& ex) { nsex = toObjCException(ex); } if(nsex != nil) { @throw nsex; } } -(ICEEndpoint*) getEndpoint { NSException* nsex = nil; try { return [ICEEndpoint localObjectWithCxxObject:CONNECTION->getEndpoint().get()]; } catch(const std::exception& ex) { nsex = toObjCException(ex); } if(nsex != nil) { @throw nsex; } return nil; } @end