1// 2// Copyright (c) ZeroC, Inc. All rights reserved. 3// 4 5#import <ConnectionI.h> 6#import <EndpointI.h> 7#import <IdentityI.h> 8#import <ObjectAdapterI.h> 9#import <ProxyI.h> 10#import <Util.h> 11#import <LocalObjectI.h> 12 13#import <objc/Ice/LocalException.h> 14 15#import <objc/runtime.h> 16 17#define CONNECTION dynamic_cast<Ice::Connection*>(static_cast<IceUtil::Shared*>(cxxObject_)) 18 19namespace 20{ 21 22std::vector<Class>* connectionInfoClasses = 0; 23 24} 25 26namespace IceObjC 27{ 28 29void 30registerConnectionInfoClass(Class cl) 31{ 32 if(!connectionInfoClasses) 33 { 34 connectionInfoClasses = new std::vector<Class>(); 35 } 36 connectionInfoClasses->push_back(cl); 37} 38 39} 40 41@implementation ICEConnectionInfo (ICEInternal) 42 43+(id) checkedConnectionInfoWithConnectionInfo:(Ice::ConnectionInfo*)__unused connectionInfo 44{ 45 assert(false); 46 return nil; 47} 48 49+(id) connectionInfoWithConnectionInfo:(NSValue*)v 50{ 51 Ice::ConnectionInfo* info = dynamic_cast<Ice::ConnectionInfo*>(reinterpret_cast<IceUtil::Shared*>(v.pointerValue)); 52 if(!info) 53 { 54 return nil; 55 } 56 57 Ice::UDPConnectionInfoPtr udpInfo = Ice::UDPConnectionInfoPtr::dynamicCast(info); 58 if(udpInfo) 59 { 60 return [[ICEUDPConnectionInfo alloc] initWithUDPConnectionInfo:udpInfo.get()]; 61 } 62 63 Ice::WSConnectionInfoPtr wsInfo = Ice::WSConnectionInfoPtr::dynamicCast(info); 64 if(wsInfo) 65 { 66 return [[ICEWSConnectionInfo alloc] initWithWSConnectionInfo:wsInfo.get()]; 67 } 68 69 Ice::TCPConnectionInfoPtr tcpInfo = Ice::TCPConnectionInfoPtr::dynamicCast(info); 70 if(tcpInfo) 71 { 72 return [[ICETCPConnectionInfo alloc] initWithTCPConnectionInfo:tcpInfo.get()]; 73 } 74 75 if(connectionInfoClasses) 76 { 77 for(std::vector<Class>::const_iterator p = connectionInfoClasses->begin(); p != connectionInfoClasses->end(); 78 ++p) 79 { 80 ICEConnectionInfo* r = [*p checkedConnectionInfoWithConnectionInfo:info]; 81 if(r) 82 { 83 return r; 84 } 85 } 86 } 87 88 Ice::IPConnectionInfoPtr ipInfo = Ice::IPConnectionInfoPtr::dynamicCast(info); 89 if(ipInfo) 90 { 91 return [[ICEIPConnectionInfo alloc] initWithIPConnectionInfo:ipInfo.get()]; 92 } 93 94 return [[ICEConnectionInfo alloc] initWithConnectionInfo:info]; 95} 96 97-(id) initWithConnectionInfo:(Ice::ConnectionInfo*)connectionInfo 98{ 99 self = [super initWithCxxObject:connectionInfo]; 100 if(self != nil) 101 { 102 self->underlying = [ICEConnectionInfo localObjectWithCxxObjectNoAutoRelease:connectionInfo->underlying.get() 103 allocator:@selector(connectionInfoWithConnectionInfo:)]; 104 self->incoming = connectionInfo->incoming; 105 self->adapterName = [[NSString alloc] initWithUTF8String:connectionInfo->adapterName.c_str()]; 106 self->connectionId = [[NSString alloc] initWithUTF8String:connectionInfo->connectionId.c_str()]; 107 } 108 return self; 109} 110 111@end 112 113@implementation ICEIPConnectionInfo (ICEInternal) 114 115-(id) initWithIPConnectionInfo:(Ice::IPConnectionInfo*)ipConnectionInfo 116{ 117 self = [super initWithConnectionInfo:ipConnectionInfo]; 118 if(self) 119 { 120 self->localAddress = [[NSString alloc] initWithUTF8String:ipConnectionInfo->localAddress.c_str()]; 121 self->localPort = ipConnectionInfo->localPort; 122 self->remoteAddress = [[NSString alloc] initWithUTF8String:ipConnectionInfo->remoteAddress.c_str()]; 123 self->remotePort = ipConnectionInfo->remotePort; 124 } 125 return self; 126} 127 128@end 129 130@implementation ICETCPConnectionInfo (ICEInternal) 131-(id) initWithTCPConnectionInfo:(Ice::TCPConnectionInfo*)tcpConnectionInfo 132{ 133 self = [super initWithIPConnectionInfo:tcpConnectionInfo]; 134 if(self) 135 { 136 self->rcvSize = tcpConnectionInfo->rcvSize; 137 self->sndSize = tcpConnectionInfo->sndSize; 138 } 139 return self; 140} 141@end 142 143@implementation ICEUDPConnectionInfo (ICEInternal) 144 145-(id) initWithUDPConnectionInfo:(Ice::UDPConnectionInfo*)udpConnectionInfo 146{ 147 self = [super initWithIPConnectionInfo:udpConnectionInfo]; 148 if(self) 149 { 150 self->mcastAddress = [[NSString alloc] initWithUTF8String:udpConnectionInfo->mcastAddress.c_str()]; 151 self->mcastPort = udpConnectionInfo->mcastPort; 152 self->rcvSize = udpConnectionInfo->rcvSize; 153 self->sndSize = udpConnectionInfo->sndSize; 154 } 155 return self; 156} 157 158@end 159 160@implementation ICEWSConnectionInfo (ICEInternal) 161-(id) initWithWSConnectionInfo:(Ice::WSConnectionInfo*)wsConnectionInfo 162{ 163 self = [super initWithConnectionInfo:wsConnectionInfo]; 164 if(self) 165 { 166 self->headers = toNSDictionary(wsConnectionInfo->headers); 167 } 168 return self; 169} 170@end 171 172namespace 173{ 174 175class CloseCallbackI : public Ice::CloseCallback 176{ 177public: 178 179 CloseCallbackI(id<ICEConnection> connection, ICECloseCallback callback) : 180 _connection(connection), _callback(Block_copy(callback)) 181 { 182 [_connection retain]; 183 } 184 185 ~CloseCallbackI() 186 { 187 [_connection release]; 188 [_callback release]; 189 } 190 191 void 192 closed(const Ice::ConnectionPtr&) 193 { 194 NSException* ex = nil; 195 @autoreleasepool 196 { 197 @try 198 { 199 _callback(_connection); 200 } 201 @catch(id e) 202 { 203 ex = [e retain]; 204 } 205 } 206 if(ex != nil) 207 { 208 rethrowCxxException(ex, true); // True = release the exception. 209 } 210 } 211 212private: 213 214 id<ICEConnection> _connection; 215 ICECloseCallback _callback; 216}; 217 218class HeartbeatCallbackI : public Ice::HeartbeatCallback 219{ 220public: 221 222 HeartbeatCallbackI(id<ICEConnection> connection, ICEHeartbeatCallback callback) : 223 _connection(connection), _callback(Block_copy(callback)) 224 { 225 [_connection retain]; 226 } 227 228 ~HeartbeatCallbackI() 229 { 230 [_connection release]; 231 [_callback release]; 232 } 233 234 void 235 heartbeat(const Ice::ConnectionPtr&) 236 { 237 NSException* ex = nil; 238 @autoreleasepool 239 { 240 @try 241 { 242 _callback(_connection); 243 } 244 @catch(id e) 245 { 246 ex = [e retain]; 247 } 248 } 249 if(ex != nil) 250 { 251 rethrowCxxException(ex, true); // True = release the exception. 252 } 253 } 254 255private: 256 257 id<ICEConnection> _connection; 258 ICEHeartbeatCallback _callback; 259}; 260 261} 262 263@implementation ICEConnection 264-(void) close:(ICEConnectionClose)mode 265{ 266 NSException* nsex = nil; 267 try 268 { 269 CONNECTION->close((Ice::ConnectionClose)mode); 270 } 271 catch(const std::exception& ex) 272 { 273 nsex = toObjCException(ex); 274 } 275 if(nsex != nil) 276 { 277 @throw nsex; 278 } 279} 280-(id<ICEObjectPrx>) createProxy:(ICEIdentity*)identity 281{ 282 NSException* nsex = nil; 283 try 284 { 285 return [ICEObjectPrx iceObjectPrxWithObjectPrx:CONNECTION->createProxy([identity identity])]; 286 } 287 catch(const std::exception& ex) 288 { 289 nsex = toObjCException(ex); 290 } 291 @throw nsex; 292 return nil; // Keep the compiler happy. 293} 294-(void) setAdapter:(id<ICEObjectAdapter>)adapter 295{ 296 NSException* nsex = nil; 297 try 298 { 299 CONNECTION->setAdapter([(ICEObjectAdapter*)adapter adapter]); 300 } 301 catch(const std::exception& ex) 302 { 303 nsex = toObjCException(ex); 304 } 305 if(nsex != nil) 306 { 307 @throw nsex; 308 } 309} 310-(id<ICEObjectAdapter>) getAdapter 311{ 312 NSException* nsex = nil; 313 try 314 { 315 return [ICEObjectAdapter localObjectWithCxxObject:CONNECTION->getAdapter().get()]; 316 } 317 catch(const std::exception& ex) 318 { 319 nsex = toObjCException(ex); 320 } 321 @throw nsex; 322 return nil; // Keep the compiler happy. 323} 324-(void) flushBatchRequests:(ICECompressBatch)compress 325{ 326 NSException* nsex = nil; 327 try 328 { 329 CONNECTION->flushBatchRequests((Ice::CompressBatch)compress); 330 } 331 catch(const std::exception& ex) 332 { 333 nsex = toObjCException(ex); 334 } 335 if(nsex != nil) 336 { 337 @throw nsex; 338 } 339} 340-(id<ICEAsyncResult>) begin_flushBatchRequests:(ICECompressBatch)compress 341{ 342 return beginCppCall(^(Ice::AsyncResultPtr& result) 343 { 344 result = CONNECTION->begin_flushBatchRequests((Ice::CompressBatch)compress); 345 }); 346} 347-(id<ICEAsyncResult>) begin_flushBatchRequests:(ICECompressBatch)compress exception:(void(^)(ICEException*))exception 348{ 349 return [self begin_flushBatchRequests:compress exception:exception sent:nil]; 350} 351-(id<ICEAsyncResult>) begin_flushBatchRequests:(ICECompressBatch)compress 352 exception:(void(^)(ICEException*))exception 353 sent:(void(^)(BOOL))sent 354{ 355 return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) 356 { 357 result = CONNECTION->begin_flushBatchRequests((Ice::CompressBatch)compress, cb); 358 }, 359 ^(const Ice::AsyncResultPtr& result) { 360 CONNECTION->end_flushBatchRequests(result); 361 }, 362 exception, sent); 363} 364-(void) end_flushBatchRequests:(id<ICEAsyncResult>)result 365{ 366 endCppCall(^(const Ice::AsyncResultPtr& r) 367 { 368 CONNECTION->end_flushBatchRequests(r); 369 }, result); 370} 371-(void) setCloseCallback:(ICECloseCallback)callback 372{ 373 CONNECTION->setCloseCallback(new CloseCallbackI(self, callback)); 374} 375-(void) setHeartbeatCallback:(ICEHeartbeatCallback)callback 376{ 377 CONNECTION->setHeartbeatCallback(new HeartbeatCallbackI(self, callback)); 378} 379-(void) heartbeat 380{ 381 NSException* nsex = nil; 382 try 383 { 384 CONNECTION->heartbeat(); 385 } 386 catch(const std::exception& ex) 387 { 388 nsex = toObjCException(ex); 389 } 390 if(nsex != nil) 391 { 392 @throw nsex; 393 } 394} 395-(id<ICEAsyncResult>) begin_heartbeat 396{ 397 return beginCppCall(^(Ice::AsyncResultPtr& result) 398 { 399 result = CONNECTION->begin_heartbeat(); 400 }); 401} 402-(id<ICEAsyncResult>) begin_heartbeat:(void(^)(ICEException*))exception 403{ 404 return [self begin_heartbeat:exception sent:nil]; 405} 406-(id<ICEAsyncResult>) begin_heartbeat:(void(^)(ICEException*))exception sent:(void(^)(BOOL))sent 407{ 408 return beginCppCall(^(Ice::AsyncResultPtr& result, const Ice::CallbackPtr& cb) 409 { 410 result = CONNECTION->begin_heartbeat(cb); 411 }, 412 ^(const Ice::AsyncResultPtr& result) 413 { 414 CONNECTION->end_heartbeat(result); 415 }, 416 exception, sent); 417} 418-(void) end_heartbeat:(id<ICEAsyncResult>)result 419{ 420 endCppCall(^(const Ice::AsyncResultPtr& r) 421 { 422 CONNECTION->end_heartbeat(r); 423 }, result); 424} 425-(void) setACM:(id)timeout close:(id)close heartbeat:(id)heartbeat 426{ 427 IceUtil::Optional<int> to; 428 ICEInt intValue; 429 if([ICEOptionalGetter getInt:timeout value:&intValue]) 430 { 431 to = intValue; 432 } 433 IceUtil::Optional<Ice::ACMClose> c; 434 if([ICEOptionalGetter getInt:close value:&intValue]) 435 { 436 c = (Ice::ACMClose)intValue; 437 } 438 IceUtil::Optional<Ice::ACMHeartbeat> hb; 439 if([ICEOptionalGetter getInt:heartbeat value:&intValue]) 440 { 441 hb = (Ice::ACMHeartbeat)intValue; 442 } 443 444 NSException* nsex; 445 try 446 { 447 CONNECTION->setACM(to, c, hb); 448 return; 449 } 450 catch(const std::exception& ex) 451 { 452 nsex = toObjCException(ex); 453 } 454 @throw nsex; 455} 456-(ICEACM*) getACM 457{ 458 Ice::ACM acm = CONNECTION->getACM(); 459 return [ICEACM acm:acm.timeout close:(ICEACMClose)acm.close heartbeat:(ICEACMHeartbeat)acm.heartbeat]; 460} 461-(NSMutableString*) type 462{ 463 return [toNSMutableString(CONNECTION->type()) autorelease]; 464} 465-(ICEInt) timeout 466{ 467 return CONNECTION->timeout(); 468} 469-(NSMutableString*) toString 470{ 471 return [toNSMutableString(CONNECTION->toString()) autorelease]; 472} 473-(NSString*) description 474{ 475 return [toNSString(CONNECTION->toString()) autorelease]; 476} 477 478-(ICEConnectionInfo*) getInfo 479{ 480 NSException* nsex = nil; 481 try 482 { 483 return [ICEConnectionInfo localObjectWithCxxObject:CONNECTION->getInfo().get() 484 allocator:@selector(connectionInfoWithConnectionInfo:)]; 485 } 486 catch(const std::exception& ex) 487 { 488 nsex = toObjCException(ex); 489 } 490 if(nsex != nil) 491 { 492 @throw nsex; 493 } 494 return nil; 495} 496 497-(void) setBufferSize:(int)rcvSize sndSize:(int)sndSize 498{ 499 NSException* nsex = nil; 500 try 501 { 502 CONNECTION->setBufferSize(rcvSize, sndSize); 503 } 504 catch(const std::exception& ex) 505 { 506 nsex = toObjCException(ex); 507 } 508 if(nsex != nil) 509 { 510 @throw nsex; 511 } 512} 513 514-(void) throwException 515{ 516 NSException* nsex = nil; 517 try 518 { 519 CONNECTION->throwException(); 520 } 521 catch(const std::exception& ex) 522 { 523 nsex = toObjCException(ex); 524 } 525 if(nsex != nil) 526 { 527 @throw nsex; 528 } 529} 530 531-(ICEEndpoint*) getEndpoint 532{ 533 NSException* nsex = nil; 534 try 535 { 536 return [ICEEndpoint localObjectWithCxxObject:CONNECTION->getEndpoint().get()]; 537 } 538 catch(const std::exception& ex) 539 { 540 nsex = toObjCException(ex); 541 } 542 if(nsex != nil) 543 { 544 @throw nsex; 545 } 546 return nil; 547} 548@end 549