00001
00002
00003
00004
00005
00006
00007
00008
00009 #import "Communication.h"
00010 #import "ServerReaderTcp.h"
00011 #import "ServerReaderUdp.h"
00012 #import "ServerSenderTcp.h"
00013 #import "ServerSenderUdp.h"
00014 #import <Math.h>
00015
00016 @implementation Communication
00017
00018
00019 bool multiThreaded = NO;
00020
00021
00022 bool ping = NO;
00023
00024
00025
00026 bool forceState = NO;
00027
00028 int fSpeed = -1;
00029 int fShield = -1;
00030 int fOrbit = -1;
00031 int fRepair = -1;
00032 int fBeamup = -1;
00033 int fBeamdown = -1;
00034 int fCloak = -1;
00035 int fBomb = -1;
00036 int fDockperm = -1;
00037 int fPhaser = -1;
00038 int fPlasma = -1;
00039 int fPlayLock = -1;
00040 int fPlanLock = -1;
00041 int fTractor = -1;
00042 int fRepressor = -1;
00043
00044
00045 int baseLocalUdpPort = 0;
00046 int localUdpPort = 0;
00047 int updatesPerSecond = COMM_UPDATES_PER_SECOND;
00048 char buffer;
00049
00050
00051 int nextPort = 0;
00052 ServerReaderTcp *tcpReader;
00053 ServerReaderUdp *udpReader;
00054 ServerSenderTcp *tcpSender;
00055 ServerSenderUdp *udpSender;
00056
00057
00058 bool isRunning;
00059 bool keepRunning;
00060
00061 - (id) init {
00062 self = [super init];
00063 if (self != nil) {
00064 ghostSlot = -1;
00065 commMode = COMM_TCP;
00066 commStatus = 0;
00067 commModeRequest;
00068 shortVersion = COMM_SHORTVERSION;
00069 receiveShort = NO;
00070 fList = [[FeatureList alloc] init];
00071 pStats = [[PingStats alloc] init];
00072 udpStats = [[UdpStats alloc] init];
00073 notificationCenter = [LLNotificationCenter defaultCenter];
00074 tcpReader = nil;
00075 udpReader = nil;
00076 [self subscribeToNotifications];
00077 isRunning = NO;
00078 keepRunning = YES;
00079 }
00080 return self;
00081 }
00082
00083 - (id)initWithUniverse:(Universe*)newUniverse baseUdpPort:(int)basePort {
00084 self = [self init];
00085 if (self != nil) {
00086 [universe release];
00087 universe = newUniverse;
00088 [universe retain];
00089 baseLocalUdpPort = basePort;
00090 }
00091 return self;
00092 }
00093
00094 - (void) setMultiThreaded:(bool) multi {
00095 multiThreaded = multi;
00096 }
00097
00098 - (void)subscribeToNotifications {
00099
00100
00101
00102
00103 [notificationCenter addObserver:self selector:@selector(readFromServer:)
00104 name:@"COMM_READ_FROM_SERVER" object:nil useLocks:multiThreaded];
00105 [notificationCenter addObserver:self selector:@selector(cleanUp:)
00106 name:@"COMM_CLEAN_UP" object:nil useLocks:multiThreaded];
00107 [notificationCenter addObserver:self selector:@selector(readFromServer:)
00108 name:@"COMM_READ_FROM_SERVER" object:nil useLocks:multiThreaded];
00109 [notificationCenter addObserver:self selector:@selector(sendSpeedReq:)
00110 name:@"COMM_SEND_SPEED_REQ" object:nil useLocks:multiThreaded];
00111 [notificationCenter addObserver:self selector:@selector(sendDockingReq:)
00112 name:@"COMM_SEND_DOCK_REQ" object:nil useLocks:multiThreaded];
00113 [notificationCenter addObserver:self selector:@selector(sendCloakReq:)
00114 name:@"COMM_SEND_CLOAK_REQ" object:nil useLocks:multiThreaded];
00115 [notificationCenter addObserver:self selector:@selector(sendRefitReq:)
00116 name:@"COMM_SEND_REFIT_REQ" object:nil useLocks:multiThreaded];
00117 [notificationCenter addObserver:self selector:@selector(sendDirReq:)
00118 name:@"COMM_SEND_DIR_REQ" object:nil useLocks:multiThreaded];
00119 [notificationCenter addObserver:self selector:@selector(sendPhaserReq:)
00120 name:@"COMM_SEND_PHASER_REQ" object:nil useLocks:multiThreaded];
00121 [notificationCenter addObserver:self selector:@selector(sendTorpReq:)
00122 name:@"COMM_SEND_TORPS_REQ" object:nil useLocks:multiThreaded];
00123 [notificationCenter addObserver:self selector:@selector(sendPlasmaReq:)
00124 name:@"COMM_SEND_PLASMA_REQ" object:nil useLocks:multiThreaded];
00125 [notificationCenter addObserver:self selector:@selector(sendShieldReq:)
00126 name:@"COMM_SEND_SHIELD_REQ" object:nil useLocks:multiThreaded];
00127 [notificationCenter addObserver:self selector:@selector(sendBombReq:)
00128 name:@"COMM_SEND_BOMB_REQ" object:nil useLocks:multiThreaded];
00129 [notificationCenter addObserver:self selector:@selector(sendBeamReq:)
00130 name:@"COMM_SEND_BEAM_REQ" object:nil useLocks:multiThreaded];
00131 [notificationCenter addObserver:self selector:@selector(sendRepairReq:)
00132 name:@"COMM_SEND_REPAIR_REQ" object:nil useLocks:multiThreaded];
00133 [notificationCenter addObserver:self selector:@selector(sendOrbitReq:)
00134 name:@"COMM_SEND_ORBIT_REQ" object:nil useLocks:multiThreaded];
00135 [notificationCenter addObserver:self selector:@selector(sendQuitReq:)
00136 name:@"COMM_SEND_QUIT_REQ" object:nil useLocks:multiThreaded];
00137 [notificationCenter addObserver:self selector:@selector(sendCoupReq:)
00138 name:@"COMM_SEND_COUP_REQ" object:nil useLocks:multiThreaded];
00139 [notificationCenter addObserver:self selector:@selector(sendByeReq:)
00140 name:@"COMM_SEND_BYE_REQ" object:nil useLocks:multiThreaded];
00141 [notificationCenter addObserver:self selector:@selector(sendPractrReq:)
00142 name:@"COMM_SEND_PRACTICE_REQ" object:nil useLocks:multiThreaded];
00143 [notificationCenter addObserver:self selector:@selector(sendDetonateReq:)
00144 name:@"COMM_SEND_DETONATE_REQ" object:nil useLocks:multiThreaded];
00145 [notificationCenter addObserver:self selector:@selector(sendDetMineReq:)
00146 name:@"COMM_SEND_DET_MINE_REQ" object:nil useLocks:multiThreaded];
00147 [notificationCenter addObserver:self selector:@selector(sendDetonateMyTorpsReq:)
00148 name:@"COMM_SEND_DET_MINE_ALL_REQ" object:nil useLocks:multiThreaded];
00149 [notificationCenter addObserver:self selector:@selector(sendPlaylockReq:)
00150 name:@"COMM_SEND_PLAYER_LOCK_REQ" object:nil useLocks:multiThreaded];
00151 [notificationCenter addObserver:self selector:@selector(sendPlanlockReq:)
00152 name:@"COMM_SEND_PLANET_LOCK_REQ" object:nil useLocks:multiThreaded];
00153 [notificationCenter addObserver:self selector:@selector(sendResetStatsReq:)
00154 name:@"COMM_SEND_RESET_STATS_REQ" object:nil useLocks:multiThreaded];
00155 [notificationCenter addObserver:self selector:@selector(sendWarReq:)
00156 name:@"COMM_SEND_WAR_REQ" object:nil useLocks:multiThreaded];
00157 [notificationCenter addObserver:self selector:@selector(sendTractorOnReq:)
00158 name:@"COMM_SEND_TRACTOR_ON_REQ" object:nil useLocks:multiThreaded];
00159 [notificationCenter addObserver:self selector:@selector(sendTractorOffReq:)
00160 name:@"COMM_SEND_TRACTOR_OFF_REQ" object:nil useLocks:multiThreaded];
00161 [notificationCenter addObserver:self selector:@selector(sendRepressorOnReq:)
00162 name:@"COMM_SEND_REPRESSOR_ON_REQ" object:nil useLocks:multiThreaded];
00163 [notificationCenter addObserver:self selector:@selector(sendRepressorOffReq:)
00164 name:@"COMM_SEND_REPRESSOR_OFF_REQ" object:nil useLocks:multiThreaded];
00165 [notificationCenter addObserver:self selector:@selector(sendTeamReq:)
00166 name:@"COMM_SEND_TEAM_REQ" object:nil useLocks:multiThreaded];
00167 [notificationCenter addObserver:self selector:@selector(sendFeatureReq:)
00168 name:@"COMM_SEND_FEATURE_REQ" object:nil useLocks:multiThreaded];
00169 [notificationCenter addObserver:self selector:@selector(sendLoginReq:)
00170 name:@"COMM_SEND_LOGIN_REQ" object:nil useLocks:multiThreaded];
00171 [notificationCenter addObserver:self selector:@selector(sendPingReq:)
00172 name:@"COMM_SEND_PING_REQ" object:nil useLocks:multiThreaded];
00173 [notificationCenter addObserver:self selector:@selector(sendServerPingResponse:)
00174 name:@"COMM_SEND_PING_RESPONSE" object:nil useLocks:multiThreaded];
00175 [notificationCenter addObserver:self selector:@selector(sendMessage:)
00176 name:@"COMM_SEND_MESSAGE" object:nil useLocks:multiThreaded];
00177 [notificationCenter addObserver:self selector:@selector(sendUpdatePacket:)
00178 name:@"COMM_SEND_UPDATE_PACKET" object:nil useLocks:multiThreaded];
00179 [notificationCenter addObserver:self selector:@selector(sendUpdatePacket:)
00180 name:@"COMM_SEND_TRESHOLD" object:nil useLocks:multiThreaded];
00181 [notificationCenter addObserver:self selector:@selector(sendOptionsPacket:)
00182 name:@"COMM_SEND_OPTIONS_PACKET" object:nil useLocks:multiThreaded];
00183 [notificationCenter addObserver:self selector:@selector(sendPickSocketReq:)
00184 name:@"COMM_SEND_PICK_SOCKET" object:nil useLocks:multiThreaded];
00185 [notificationCenter addObserver:self selector:@selector(sendUdpReq:)
00186 name:@"COMM_SEND_UDP_REQ" object:nil useLocks:multiThreaded];
00187 [notificationCenter addObserver:self selector:@selector(sendShortReq:)
00188 name:@"COMM_SEND_SHORT_REQ" object:nil useLocks:multiThreaded];
00189 [notificationCenter addObserver:self selector:@selector(sendUdpVerify:)
00190 name:@"COMM_SEND_VERIFY" object:nil useLocks:multiThreaded];
00191
00192
00193 [notificationCenter addObserver:self selector:@selector(closeUdpConn:)
00194 name:@"SP_SWITCHED_DENIED" object:nil useLocks:multiThreaded];
00195 [notificationCenter addObserver:self selector:@selector(closeUdpConn:)
00196 name:@"SP_UDP_SWITCHED_TO_TCP" object:nil useLocks:multiThreaded];
00197 [notificationCenter addObserver:self selector:@selector(sendUdpVerify:)
00198 name:@"SP_TCP_SWITCHED_TO_UDP" object:nil useLocks:multiThreaded];
00199 [notificationCenter addObserver:self selector:@selector(sendShortReq:)
00200 name:@"SP_S_REPLY_SPK_OLD" object:nil useLocks:multiThreaded];
00201 [notificationCenter addObserver:self selector:@selector(sendUdpReq:)
00202 name:@"SP_S_REPLY_SPK_VOFF" object:nil useLocks:multiThreaded];
00203 [notificationCenter addObserver:self selector:@selector(sendShortReq:)
00204 name:@"SP_S_REPLY_SPK_VON" object:nil useLocks:multiThreaded];
00205
00206 [notificationCenter addObserver:self selector:@selector(stopCommunicationThread)
00207 name:@"COMM_RESURRECT_FAILED" object:nil useLocks:multiThreaded];
00208 }
00209
00210 -(char*) bigEndianInteger:(int) value inBuffer:(char*) dst withOffset:(int)dst_begin {
00211 dst = (char)((value >> 24) & 0xFF);
00212 dst = (char)((value >> 16) & 0xFF);
00213 dst = (char)((value >> 8 ) & 0xFF);
00214 dst = (char)(value & 0xFF);
00215 return dst;
00216 }
00217
00218 -(PingStats*) pingStats {
00219 return pStats;
00220 }
00221
00222 -(UdpStats*)udpStats {
00223 return udpStats;
00224 }
00225
00226 - (int) updatesPerSecond {
00227 return updatesPerSecond;
00228 }
00229
00230 - (int) ghostSlot {
00231 return ghostSlot;
00232 }
00233
00234 - (void) setGhostSlot:(int) slot {
00235 ghostSlot = slot;
00236 }
00237
00238 -(int)commMode {
00239 return commMode;
00240 }
00241
00242 -(void)setCommMode:(int)mode {
00243 commMode = mode;
00244 }
00245 -(int)commModeRequest {
00246 return commModeRequest;
00247 }
00248
00249 -(void)setCommModeRequest:(int)mode {
00250 commModeRequest = mode;
00251 }
00252
00253 -(FeatureList*) featureList {
00254 return fList;
00255 }
00256
00257 -(int)commStatus {
00258 return commStatus;
00259 }
00260
00261 -(void)setCommStatus:(int)status {
00262 commStatus = status;
00263 }
00264
00265 -(int)shortVersion {
00266 return shortVersion;
00267 }
00268
00269 -(void)setShortVersion:(int)ver {
00270 shortVersion = ver;
00271 }
00272
00273 -(bool)receiveShort {
00274 return receiveShort;
00275 }
00276
00277 -(void)setReceiveShort:(bool)rs {
00278 receiveShort = rs;
00279 }
00280
00281 -(void) setPing:(bool) received withResponse:(int)response {
00282
00283 }
00284
00285 -(int) packetsReceived {
00286 return [udpStats packetsReceived];
00287 }
00288
00289 -(void)increasePacketsReceived {
00290 [udpStats setPacketsReceived: [udpStats packetsReceived] + 1];
00291 }
00292
00293 -(void)decreasePacketsReceived {
00294 [udpStats setPacketsReceived: [udpStats packetsReceived] - 1];
00295 }
00296
00297 -(char *) insertString:(NSString *)str inBuffer:(char*)buffer offset:(int)offset maxLength:(int)max {
00298
00299 max = (max > [str length] ? [str length] : max);
00300
00301 const char *input = [str cString];
00302
00303 strncpy(buffer+offset, input, max);
00304
00305 buffer[offset+max] = 0;
00306 return buffer;
00307 }
00308
00309
00310 - (void) sendShortPacketWithId:(char) type {
00311 [self sendShortPacketWithId:type state: 0];
00312 }
00313
00314 - (void) sendShortPacketNoForceWithId:(char) type state:(char) state {
00315 buffer = type;
00316 buffer = state;
00317 [self sendServerPacketWithBuffer:buffer length:4];
00318 }
00319
00320 - (void) sendShortPacketWithId:(char) type boolState:(bool) state {
00321 [self sendShortPacketWithId:type state: (state ? 1 :0 ) ];
00322 }
00323
00324
00325 - (void) sendShortPacketWithId:(char) type state:(char) state {
00326
00327 [self sendShortPacketNoForceWithId:type state:state];
00328
00329
00330
00331 if (commMode == COMM_UDP && forceState) {
00332 switch (type) {
00333 case CP_SPEED:
00334 fSpeed = state | 0x100;
00335 break;
00336 case CP_SHIELD:
00337 fShield = state | 0xA00;
00338 break;
00339 case CP_ORBIT:
00340 fOrbit = state | 0xA00;
00341 break;
00342 case CP_REPAIR:
00343 fRepair = state | 0xA00;
00344 break;
00345 case CP_CLOAK:
00346 fCloak = state | 0xA00;
00347 break;
00348 case CP_BOMB:
00349 fBomb = state | 0xA00;
00350 break;
00351 case CP_DOCKPERM:
00352 fDockperm = state | 0xA00;
00353 break;
00354 case CP_PLAYLOCK:
00355 fPlayLock = state | 0xA00;
00356 break;
00357 case CP_PLANLOCK:
00358 fPlanLock = state | 0xA00;
00359 break;
00360 case CP_BEAM:
00361 if (state == 1)
00362 fBeamup = 1 | 0x500;
00363 else
00364 fBeamdown = 2 | 0x500;
00365 break;
00366 case CP_PHASER:
00367 fPhaser = state | 0x100;
00368 break;
00369 case CP_PLASMA:
00370 fPlasma = state | 0x100;
00371 break;
00372 }
00373 }
00374 }
00375
00376 - (void) sendServerPacketWithBuffer:(char*)buffer length:(int) size {
00377 if(commMode == COMM_UDP) {
00378
00379 switch (buffer[0]) {
00380 case CP_SPEED:
00381 case CP_DIRECTION:
00382 case CP_PHASER:
00383 case CP_PLASMA:
00384 case CP_TORP:
00385 case CP_QUIT:
00386 case CP_PRACTR:
00387 case CP_SHIELD:
00388 case CP_REPAIR:
00389 case CP_ORBIT:
00390 case CP_PLANLOCK:
00391 case CP_PLAYLOCK:
00392 case CP_BOMB:
00393 case CP_BEAM:
00394 case CP_CLOAK:
00395 case CP_DET_TORPS:
00396 case CP_DET_MYTORP:
00397 case CP_REFIT:
00398 case CP_TRACTOR:
00399 case CP_REPRESS:
00400 case CP_COUP:
00401 case CP_DOCKPERM:
00402 case CP_PING_RESPONSE:
00403
00404 [udpStats increasePacketsSendBy:1];
00405 if ((udpSender == nil) || (![udpSender sendBuffer:buffer length:size])) {
00406 [notificationCenter postNotificationName:@"COMM_UDP_LINK_SEVERED" object:self
00407 userInfo:@"UDP link severed"];
00408 commModeRequest = commMode;
00409 commStatus = STAT_CONNECTED;
00410 [self sendUdpReq:COMM_TCP];
00411 [self closeUdpConn];
00412 }
00413 return;
00414 break;
00415 default:
00416 NSLog(@"Communications.sendServerPacketWithBuffer unknown UDP packet");
00417 break;
00418 }
00419 }
00420
00421
00422 if ((tcpSender == nil) || (![tcpSender sendBuffer:buffer length:size])) {
00423 NSLog(@"Communications.sendServerPacketWithBuffer TCP write error");
00424 [notificationCenter postNotificationName:@"COMM_TCP_WRITE_ERROR" object:self
00425 userInfo:@"TCP write error"];
00426 }
00427 }
00428
00429 - (void) resetForce {
00430 fSpeed = fShield = fOrbit = fRepair = fBeamup = fBeamdown = fCloak
00431 = fBomb = fDockperm = fPhaser = fPlasma = fPlayLock = fPlanLock
00432 = fTractor = fRepressor = -1;
00433 }
00434
00441 - (int) forceCheckFlags:(int) flag force:(int) force type:(char)type {
00442 if (force > 0) {
00443 if (([[universe playerThatIsMe] flags] & flag) != (force & 0xFF)) {
00444 [self sendShortPacketNoForceWithId:type state: (force & 0xFF)];
00445 force -= 0x100;
00446 if (force < 0x100) {
00447 force = -1;
00448 }
00449 }
00450 else {
00451 force = -1;
00452 }
00453 }
00454 return force;
00455 }
00456
00457 - (int) forceCheckValue:(int) value force:(int) force type:(char) type {
00458 if (force > 0) {
00459 if (value != (force & 0xFF)) {
00460 [self sendShortPacketNoForceWithId:type state:(force & 0xFF)];
00461 force -= 0x100;
00462 if (force < 0x100) {
00463 force = -1;
00464 }
00465 }
00466 else {
00467 force = -1;
00468 }
00469 }
00470 return force;
00471 }
00472
00473 - (int) forceCheckTractFlag:(int) flag force:(int) force type:(char) type {
00474 if (force > 0) {
00475 if ((([[universe playerThatIsMe] flags] & flag) != 0) ^ ((force & 0xFF) != 0)) {
00476 int state = ((force & 0xFF) >= 0x40) ? 1 : 0;
00477 int pnum = (force & 0xFF) & (~0x40);
00478 buffer = type;
00479 buffer = (char)state;
00480 buffer = (char)pnum;
00481 [self sendServerPacketWithBuffer:buffer length:4];
00482 force -= 0x100;
00483 if (force < 0x100) {
00484 force = -1;
00485 }
00486 }
00487 else {
00488 force = -1;
00489 }
00490 }
00491 return force;
00492 }
00493
00494 - (void) checkForce {
00495
00496
00497
00498 Player *me= [universe playerThatIsMe];
00499 fSpeed = [self forceCheckValue: [me speed] force:fSpeed type: CP_SPEED];
00500 fShield = [self forceCheckFlags: PLAYER_SHIELD force:fShield type:CP_SHIELD];
00501 fOrbit = [self forceCheckFlags: PLAYER_ORBIT force:fOrbit type:CP_ORBIT];
00502 fRepair = [self forceCheckFlags: PLAYER_REPAIR force:fRepair type:CP_REPAIR];
00503 fBeamup = [self forceCheckFlags: PLAYER_BEAMUP force:fBeamup type:CP_BEAM];
00504 fBeamdown = [self forceCheckFlags: PLAYER_BEAMDOWN force:fBeamdown type:CP_BEAM];
00505 fCloak = [self forceCheckFlags: PLAYER_CLOAK force:fCloak type:CP_CLOAK];
00506 fBomb = [self forceCheckFlags: PLAYER_BOMB force:fBomb type:CP_BOMB];
00507 fDockperm = [self forceCheckFlags: PLAYER_DOCKOK force:fDockperm type:CP_DOCKPERM];
00508 fPhaser = [self forceCheckValue: [[universe phaserWithId:[me phaserId]] status] force:fPhaser type:CP_PHASER];
00509 fPlasma = [self forceCheckValue: [[universe plasmaWithId:[me plasmaId]] status] force:fPlasma type:CP_PLASMA];
00510 fPlayLock = [self forceCheckFlags: PLAYER_PLOCK force:fPlayLock type:CP_PLAYLOCK];
00511 fPlanLock = [self forceCheckFlags: PLAYER_PLLOCK force:fPlanLock type:CP_PLANLOCK];
00512 fTractor = [self forceCheckTractFlag: PLAYER_TRACT force:fTractor type:CP_TRACTOR];
00513 fRepressor= [self forceCheckTractFlag: PLAYER_PRESS force:fRepressor type:CP_REPRESS];
00514 }
00515
00516
00517
00518
00519
00520
00521 -(void)cleanUp:(id)sender {
00522 if (tcpReader != nil) {
00523 [self sendByeReq:self];
00524 [tcpReader close];
00525 [tcpReader release];
00526 tcpReader = nil;
00527 }
00528 if (udpReader != nil) {
00529 [udpReader close];
00530 [udpReader release];
00531 udpReader = nil;
00532 }
00533 if (udpSender != nil) {
00534 [udpSender close];
00535 [udpSender release];
00536 udpSender = nil;
00537 }
00538 if (tcpSender != nil) {
00539 [tcpSender close];
00540 [tcpSender release];
00541 tcpSender = nil;
00542 }
00543
00544
00545
00546 }
00547
00548 -(void)readFromServer {
00549
00550
00551
00552
00553
00554
00555
00556 if(udpReader != nil && commStatus != STAT_SWITCH_TCP) {
00557 @try {
00558 [udpReader readFromServer];
00559 }
00560 @catch(NSException *e) {
00561 [notificationCenter postNotificationName:@"COMM_UDP_LINK_SEVERED" object:self
00562 userInfo:@"UDP link severed"];
00563 [self sendUdpReq:COMM_TCP];
00564 [self closeUdpConn];
00565 }
00566
00567 if (commStatus == STAT_VERIFY_UDP) {
00568 [notificationCenter postNotificationName:@"COMM_UDP_LINK_ESTABLISHED" object:self
00569 userInfo:@"UDP link established"];
00570 [udpStats setSequence:0];
00571 [self resetForce];
00572
00573 commMode = COMM_UDP;
00574 commStatus = STAT_CONNECTED;
00575 }
00576
00577 [self checkForce];
00578 }
00579
00580
00581 @try {
00582 if(tcpReader != nil) {
00583 [tcpReader readFromServer];
00584 }
00585 }
00586 @catch(NSException *e) {
00587 NSLog(@"Communication.readFromServer exception %@: %@", [e name], [e reason] );
00588 [notificationCenter postNotificationName:@"COMM_GHOSTBUSTED" object:self
00589 userInfo:@"Whoops! We've been ghostbusted!"];
00590 if (commMode == COMM_UDP) {
00591 [self closeUdpConn];
00592 }
00593 commMode = commModeRequest = COMM_TCP;
00594
00595 if([self connectToServerUsingNextPort]) {
00596 [notificationCenter postNotificationName:@"COMM_RESURRECTED" object:self
00597 userInfo:@"Yea! We've been resurrected!"];
00598 }
00599 else {
00600 [notificationCenter postNotificationName:@"COMM_RESURRECT_FAILED" object:self
00601 userInfo:@"Sorry, We could not be resurrected!"];
00602 }
00603 }
00604
00605
00606
00607 }
00608
00609
00610 -(void)readFromServer:(id)sender {
00611 [self readFromServer];
00612 }
00613
00614 - (void) sendSpeedReq:(NSNumber*) speed {
00615 [self sendShortPacketWithId:CP_SPEED state: (char)[speed intValue]];
00616 }
00617
00618 - (void) sendDockingReq:(NSNumber*) on {
00619 [self sendShortPacketWithId:CP_DOCKPERM boolState:[on boolValue]];
00620 }
00621
00622 - (void) sendCloakReq:(NSNumber*) on {
00623 [self sendShortPacketWithId:CP_CLOAK boolState:[on boolValue]];
00624 }
00625
00626 - (void) sendRefitReq:(NSNumber *) ship {
00627 [self sendShortPacketWithId:CP_REFIT state:[ship charValue]];
00628 }
00629
00630 - (void) sendDirReq:(NSNumber *) dir {
00631 [self sendShortPacketWithId:CP_DIRECTION state:[dir charValue]];
00632 }
00633
00634 - (void) sendPhaserReq:(NSNumber *) dir {
00635 [self sendShortPacketWithId:CP_PHASER state:[dir charValue]];
00636 }
00637
00638 - (void) sendTorpReq:(NSNumber *) dir {
00639 [self sendShortPacketWithId:CP_TORP state:[dir charValue]];
00640 }
00641
00642 - (void) sendPlasmaReq:(NSNumber *) dir {
00643 [self sendShortPacketWithId:CP_PLASMA state:[dir charValue]];
00644 }
00645
00646 - (void) sendShieldReq:(NSNumber*) on {
00647 [self sendShortPacketWithId:CP_SHIELD boolState:[on boolValue]];
00648 }
00649
00650 - (void) sendBombReq:(NSNumber*) bomb {
00651 [self sendShortPacketWithId:CP_BOMB boolState:[bomb boolValue]];
00652 }
00653
00654 - (void) sendBeamReq:(NSNumber*) up {
00655 [self sendShortPacketWithId:CP_BEAM state:(char)([up boolValue] ? 1 : 2)];
00656 }
00657
00658 - (void) sendRepairReq:(NSNumber*) on {
00659 [self sendShortPacketWithId:CP_REPAIR boolState:[on boolValue]];
00660 }
00661
00662 - (void) sendOrbitReq:(NSNumber*) orbit {
00663 [self sendShortPacketWithId:CP_ORBIT boolState:[orbit boolValue]];
00664 }
00665
00666 - (void) sendQuitReq:(id)sender {
00667 [self sendShortPacketWithId:CP_QUIT];
00668 }
00669
00670 - (void) sendCoupReq:(id)sender {
00671 [self sendShortPacketWithId:CP_COUP];
00672 }
00673
00674 - (void) sendByeReq:(id)sender {
00675 [self sendShortPacketWithId:CP_BYE];
00676 }
00677
00678 - (void) sendPractrReq:(id)sender {
00679 [self sendShortPacketWithId:CP_PRACTR];
00680 }
00681
00682 - (void) sendDetonateReq:(id)sender {
00683 [self sendShortPacketWithId:CP_DET_TORPS];
00684 }
00685
00686 - (void) sendPlaylockReq:(NSNumber *) player {
00687 [self sendShortPacketWithId:CP_PLAYLOCK state:(char)[player intValue]];
00688 }
00689
00690 - (void) sendPlanlockReq:(NSNumber *) planet {
00691 [self sendShortPacketWithId:CP_PLANLOCK state:(char)[planet intValue]];
00692 }
00693
00694 - (void) sendResetStatsReq:(NSNumber *) verify {
00695 [self sendShortPacketWithId:CP_RESETSTATS state:[verify charValue]];
00696 }
00697
00698 - (void) sendWarReq:(NSNumber *) mask {
00699 [self sendShortPacketWithId:CP_WAR state:[mask charValue]];
00700 }
00701
00702 - (void) sendTractorOnReq:(NSNumber *) player {
00703 buffer = CP_TRACTOR;
00704 buffer = 1;
00705 buffer = [player charValue];
00706 [self sendServerPacketWithBuffer:buffer length:4];
00707
00708 fRepressor = 0;
00709 fTractor = [player charValue] | 0x40;
00710 }
00711
00712 - (void) sendTractorOffReq:(NSNumber *) player {
00713 buffer = CP_TRACTOR;
00714 buffer = 0;
00715 buffer = [player charValue];
00716 [self sendServerPacketWithBuffer:buffer length:4];
00717 fTractor = 0;
00718 }
00719
00720 - (void) sendRepressorOnReq:(NSNumber *) player {
00721 buffer = CP_REPRESS;
00722 buffer = 1;
00723 buffer = [player charValue];
00724 [self sendServerPacketWithBuffer:buffer length:4];
00725
00726 fTractor = 0;
00727 fRepressor = [player charValue] | 0x40;
00728 }
00729
00730 - (void) sendRepressorOffReq:(NSNumber *) player {
00731 buffer = CP_REPRESS;
00732 buffer = 0;
00733 buffer = [player charValue];
00734 [self sendServerPacketWithBuffer:buffer length:4];
00735 fRepressor = 0;
00736 }
00737
00738 - (void) sendTeamReq:(NSDictionary *)newTeam {
00739 buffer = CP_OUTFIT;
00740 buffer = [[newTeam valueForKey:@"team"] charValue];
00741 buffer = [[newTeam valueForKey:@"ship"] charValue];
00742 [self sendServerPacketWithBuffer:buffer length:4];
00743 }
00744
00745 -(void) sendDetMineReq:(NSNumber *) torpId {
00746 buffer = CP_DET_MYTORP;
00747 buffer = (char)(([torpId intValue] >> 8) & 0xFF);
00748 buffer = (char)([torpId intValue] & 0xFF);
00749 [self sendServerPacketWithBuffer:buffer length:4];
00750 }
00751
00752 - (void) sendFeature:(NSDictionary *)newFeature {
00753 buffer= CP_FEATURE;
00754 buffer = [[newFeature valueForKey:@"type"] charValue];
00755 buffer = [[newFeature valueForKey:@"arg1"] charValue];
00756 buffer = [[newFeature valueForKey:@"arg2"] charValue];
00757 [self bigEndianInteger:[[newFeature valueForKey:@"value"] intValue] inBuffer:buffer withOffset:4];
00758 NSString *name = [newFeature valueForKey:@"name"];
00759 [self insertString:name inBuffer:buffer offset:8 maxLength:79];
00760 [self sendServerPacketWithBuffer:buffer length:88];
00761 }
00762
00763 - (void) sendLoginReq:(NSDictionary *)login {
00764 buffer= CP_LOGIN;
00765 buffer = (char)([login valueForKey:@"query"] ? 1 : 0);
00766 NSString *name = [login valueForKey:@"name"];
00767 NSString *pass = [login valueForKey:@"pass"];
00768 NSString *log = [login valueForKey:@"login"];
00769 [self insertString:name inBuffer:buffer offset:4 maxLength:15];
00770 [self insertString:pass inBuffer:buffer offset:20 maxLength:15];
00771 [self insertString:log inBuffer:buffer offset:36 maxLength:15];
00772 [self sendServerPacketWithBuffer:buffer length:52];
00773 }
00774
00807 - (void) sendPingReq:(NSNumber *)start {
00808 buffer = CP_PING_RESPONSE;
00809 buffer = (char)([start boolValue] ? 1 : 0);
00810
00811
00812
00813 [self sendServerPacketWithBuffer:buffer length:12];
00814 }
00815
00816 - (void) sendServerPingResponse:(NSNumber *) number {
00817 buffer = CP_PING_RESPONSE;
00818 buffer = [number charValue];
00819 buffer = (char)(ping ? 1 : 0);
00820 [self bigEndianInteger:[udpStats packetsSent] + (commMode == COMM_UDP ? 1 : 0) inBuffer:buffer withOffset:4];
00821 [self bigEndianInteger:[udpStats packetsReceived] inBuffer:buffer withOffset:8];
00822 [self sendServerPacketWithBuffer:buffer length:12];
00823 }
00824
00825 - (void) sendMessage:(NSDictionary *)mess {
00826 buffer = CP_MESSAGE;
00827 buffer = [[mess valueForKey:@"group"] charValue];
00828 buffer = [[mess valueForKey:@"indiv"] charValue];
00829 NSString *message = [mess valueForKey:@"message"];
00830 [self insertString:message inBuffer:buffer offset:4 maxLength:79];
00831 [self sendServerPacketWithBuffer:buffer length:84];
00832 }
00833
00834 - (void) sendUpdatePacket:(NSNumber *) updates_per_second {
00835
00836 if(updatesPerSecond == [updates_per_second intValue]) {
00837 return;
00838 }
00839 updatesPerSecond = [updates_per_second intValue];
00840 buffer= CP_UPDATES;
00841 [self bigEndianInteger:1000000 / [updates_per_second intValue] inBuffer:buffer withOffset:4];
00842 [self sendServerPacketWithBuffer:buffer length:8];
00843 }
00844
00845 - (void) sendShortReq:(NSNumber *) state {
00846 buffer = CP_S_REQ;
00847 buffer = [state charValue];
00848 buffer = shortVersion;
00849 [self sendServerPacketWithBuffer:buffer length:4];
00850
00851
00852 switch ([state charValue]) {
00853 case SPK_VON :
00854 [notificationCenter postNotificationName:@"COMM_PACKET_REQUEST_SHORT_SENT" object:self
00855 userInfo:@"Sending short packet request"];
00856 break;
00857 case SPK_VOFF :
00858 [notificationCenter postNotificationName:@"COMM_PACKET_REQUEST_OLD_SENT" object:self
00859 userInfo:@"Sending old style packet request"];
00860 break;
00861 }
00862
00863
00864 if(receiveShort && ([state charValue] == SPK_SALL || [state charValue] == SPK_ALL)) {
00865
00866 [universe setAllTorpsStatus:TORP_FREE];
00867 [universe setAllPlasmasStatus:PLASMA_FREE];
00868 [universe setAllPhasersStatus:PHASER_FREE];
00869
00870 [notificationCenter postNotificationName:@"COMM_PACKET_REQUEST_SMALL_UPDATE" object:self
00871 userInfo:@"Sending small update request"];
00872 }
00873 }
00874
00875 - (void) sendThreshold:(NSNumber*) threshold {
00876 buffer = CP_S_THRS;
00877 buffer = (char)(([threshold intValue] >> 8) & 0xFF);
00878 buffer = (char)( [threshold intValue] & 0xFF);
00879 [self sendServerPacketWithBuffer:buffer length:4];
00880 }
00881
00882 - (void) sendDetonateMyTorpsReq:(id)sender {
00883 Torp *torp;
00884 NSArray *torps = [[universe playerThatIsMe] torps];
00885 for (int t = 0; t < [torps count]; t++) {
00886 torp = [torps objectAtIndex:t];
00887 if ([torp status] == TORP_MOVE || [torp status] == TORP_STRAIGHT) {
00888 [self sendDetMineReq: [NSNumber numberWithChar:(char)[torp weaponId]]];
00889 if (receiveShort) {
00890
00891
00892 break;
00893 }
00894 }
00895 }
00896 }
00897
00898 - (void) sendOptionsPacket:(id)sender {
00899 buffer = CP_OPTIONS;
00900
00901 int flags =
00902 (STATS_MAPMODE
00903 + STATS_NAMEMODE
00904 + STATS_SHOWSHIELDS
00905 + STATS_KEEPPEACE
00906 + STATS_SHOWLOCAL
00907 + STATS_SHOWGLOBAL);
00908 [self bigEndianInteger:flags inBuffer:buffer withOffset:4];
00909
00910
00911 [self insertString:@"" inBuffer:buffer offset:8 maxLength:96];
00912 [self sendServerPacketWithBuffer:buffer length:104];
00913 }
00914
00916 - (int) sendSocketVersionAndNumberReq:(int)port {
00917 return [self sendPickSocketReq:[NSNumber numberWithInt:port]];
00918 }
00919
00920 - (int) sendPickSocketReq {
00921 return [self sendPickSocketReq:[NSNumber numberWithInt:nextPort]];
00922 }
00923
00924 - (int) sendPickSocketReq:(NSNumber*) startAtPort {
00925 int old_port = [startAtPort intValue];
00926
00927 nextPort = (int)(random() * 32767);
00928 while (nextPort < 2048 || nextPort == old_port) {
00929 nextPort = ((nextPort + 10687) & 32767);
00930 }
00931 buffer = CP_SOCKET;
00932 buffer = SOCKVERSION;
00933 buffer = UDPVERSION;
00934 [self bigEndianInteger:nextPort inBuffer:buffer withOffset:4];
00935 [self sendServerPacketWithBuffer:buffer length:8];
00936
00937
00938 [notificationCenter postNotificationName:@"COMM_PICK_SOCKET_SENT" object:self
00939 userInfo:[NSNumber numberWithInt:nextPort]];
00940
00941 return nextPort;
00942 }
00943
00944 - (void) sendUdpReq:(NSNumber*) request {
00945 char req = [request charValue];
00946
00947 buffer = CP_UDP_REQ;
00948 buffer = (char)(req & 0xFF);
00949
00950
00951 if (req >= COMM_MODE) {
00952 buffer[1] = COMM_MODE;
00953 buffer = (char)((req - COMM_MODE) & 0xFF);
00954 [self sendServerPacketWithBuffer:buffer length:8];
00955 return;
00956 }
00957
00958 if (req == COMM_UPDATE) {
00959 if (receiveShort) {
00960
00961 [universe resetWeaponInfo];
00962 }
00963
00964 [self sendServerPacketWithBuffer:buffer length:8];
00965 [notificationCenter postNotificationName:@"COMM_UPDATE_REQ_SENT" object:self
00966 userInfo:@"Sent request for full update"];
00967 return;
00968 }
00969
00970 if (req == commModeRequest) {
00971 [notificationCenter postNotificationName:@"COMM_UPDATE_REQ_DUPLICATE" object:self
00972 userInfo:@"Request is in progress, do not disturb"];
00973 return;
00974 }
00975
00976
00977
00978 if (req == COMM_UDP) {
00979
00980 if([self openUdpConn]) {
00981 NSLog([NSString stringWithFormat:@"Communication.sendUdpReq: bind to local port %d success", localUdpPort]);
00982 [notificationCenter postNotificationName:@"COMM_UDP_REQ_SUCCESS" object:self
00983 userInfo:@"UDP connection established"];
00984 }
00985 else {
00986 NSLog([NSString stringWithFormat:@"Communication.sendUdpReq: bind to local port %d failed", localUdpPort]);
00987 commModeRequest = COMM_TCP;
00988 commStatus = STAT_CONNECTED;
00989 [notificationCenter postNotificationName:@"COMM_UDP_REQ_FAILED" object:self
00990 userInfo:@"Unable to establish UDP connection"];
00991 return;
00992 }
00993 }
00994
00995
00996 buffer = CP_UDP_REQ;
00997 buffer = req;
00998 buffer = CONNMODE_PORT;
00999 [self bigEndianInteger:localUdpPort inBuffer:buffer withOffset:4];
01000 [self sendServerPacketWithBuffer:buffer length:8];
01001
01002
01003 commModeRequest = req;
01004 if (req == COMM_TCP) {
01005 commStatus = STAT_SWITCH_TCP;
01006 }
01007 else {
01008 commStatus = STAT_SWITCH_UDP;
01009 }
01010
01011 NSString *message = [NSString stringWithFormat:@"UDP: Sent request for %@ mode", (req == COMM_TCP ? @"TCP" : @"UDP")];
01012 NSLog([NSString stringWithFormat:@"Communication.sendUdpReq: %@", message]);
01013
01014 [notificationCenter postNotificationName:@"COMM_UDP_REQ_FOR_MODE" object:self
01015 userInfo:message];
01016 }
01017
01018 - (void) sendUdpVerify:(id)sender {
01019 buffer = CP_UDP_REQ;
01020 buffer = COMM_VERIFY;
01021 buffer = (char)0;
01022 [self bigEndianInteger:0 inBuffer:buffer withOffset:4];
01023 if (![udpSender sendBuffer:buffer length:8]) {
01024 NSLog(@"Communication.sendUdpVerify: UDP: send failed. Closing UDP connection");
01025
01026 [notificationCenter postNotificationName:@"COMM_UDP_LINK_SEVERED" object:self
01027 userInfo:@"UDP link severed"];
01028
01029 commModeRequest = commMode;
01030 commStatus = STAT_CONNECTED;
01031
01032
01033 [self sendUdpReq:COMM_TCP];
01034 [self closeUdpConn];
01035 }
01036 }
01037
01038
01039
01040
01041 - (bool) callServer:(NSString *)server port:(int) port {
01042
01043 ONTCPSocket *socket;
01044 ONHost *hostName;
01045
01046 NSLog([NSString stringWithFormat:@"Communication.callServer: %@ at %d", server, port]);
01047 @try {
01048
01049 hostName = [ONHost hostForHostname:server];
01050
01051 }
01052 @catch (NSException * e) {
01053 NSLog([NSString stringWithFormat:@"Communication.callServer: %@", [e reason]]);
01054 return NO;
01055 }
01056
01057 @try {
01058
01059 socket = [ONTCPSocket tcpSocket];
01060 [socket connectToHost:hostName port:port];
01061 NSLog(@"Communication.callServer: got connection parameters");
01062
01063 [tcpSender release];
01064 tcpSender = [[ServerSenderTcp alloc] initWithSocket:socket];
01065 [tcpReader release];
01066 tcpReader = [[ServerReaderTcp alloc] initWithUniverse:universe communication:self socket:socket];
01067
01068 [self sendSocketVersionAndNumberReq:port];
01069 }
01070 @catch (NSException * e) {
01071 NSLog([NSString stringWithFormat:@"Communication.callServer: error connecting to %@", hostName]);
01072 return NO;
01073 }
01074
01075
01076 [self sendFeature:[NSDictionary dictionaryWithObjectsAndKeys:
01077 @"FEATURE_PACKETS", @"name",
01078 [NSNumber numberWithChar:'S'], @"type",
01079 [NSNumber numberWithInt:1] , @"value",
01080 [NSNumber numberWithInt:0], @"arg1",
01081 [NSNumber numberWithInt:0], @"arg2", nil]];
01082
01083 return YES;
01084 }
01085
01086
01087
01088 - (bool) connectToServerUsingNextPort {
01089
01090 return [self connectToServerUsingPort:[self sendPickSocketReq]];
01091 }
01092
01093 - (bool) connectToServerUsingPort:(int) port {
01094 return [self connectToServerUsingPort:port expectedHost:nil];
01095 }
01096
01097
01098 - (bool) connectToServerUsingPort:(int) port expectedHost:(NSString *) host {
01099
01100 ONHost *hostName;
01101
01102 NSLog([NSString stringWithFormat:@"Communication.connectToServer: (%@) Waiting for connection at port %d", host, port]);
01103
01104
01105 ONTCPSocket *serverTCPSocket, *connectionTCPSocket;
01106
01107 @try {
01108 serverTCPSocket = (ONTCPSocket *)[ONTCPSocket tcpSocket];
01109 [serverTCPSocket startListeningOnLocalPort:port allowingAddressReuse:YES];
01110 }
01111 @catch (NSException * e) {
01112 NSLog(@"Communication.connectToServer: error creating socket %d", port);
01113 return false;
01114 }
01115
01116 @try {
01117 [serverTCPSocket setTimeOut:240000];
01118 connectionTCPSocket = [serverTCPSocket acceptConnectionOnNewSocket];
01119 NSLog(@"Communication.connectToServer: got connection");
01120 }
01121 @catch (NSException * e) {
01122 NSLog(@"Communication.connectToServer: error accepting connection on socket %d", port);
01123 return false;
01124 }
01125
01126
01127
01128 if(host == nil) {
01129 hostName = [connectionTCPSocket remoteAddressHost];
01130 } else {
01131 hostName = [ONHost hostForHostname:host];
01132 }
01133
01134 @try {
01135
01136 [tcpSender release];
01137 tcpSender = [[ServerSenderTcp alloc] initWithSocket:connectionTCPSocket];
01138 [tcpReader release];
01139 tcpReader = [[ServerReaderTcp alloc] initWithUniverse:universe communication:self socket:connectionTCPSocket];
01140
01141 [self sendSocketVersionAndNumberReq:port];
01142 }
01143 @catch (NSException * e) {
01144 NSLog([NSString stringWithFormat:@"Communication.connectToServer: error connecting to %@", hostName]);
01145 return false;
01146 }
01147 NSLog([NSString stringWithFormat:@"Communication.connectToServer: got connection to %@ at %d", hostName, port]);
01148 return YES;
01149 }
01150
01151
01152 - (bool) openUdpConn {
01153
01154
01155 if(baseLocalUdpPort > 0) {
01156 localUdpPort = baseLocalUdpPort;
01157 NSLog([NSString stringWithFormat:@"Communication.openUdp: UDP: using base port %d", baseLocalUdpPort]);
01158 }
01159 else {
01160 localUdpPort = (int)(random() * 32767);
01161 }
01162
01163 for(int attempts = 0; attempts < MAX_PORT_RETRY; ++attempts) {
01164 while(localUdpPort < 2048) {
01165 localUdpPort = ((localUdpPort + 10687) & 32767);
01166 }
01167
01168 @try {
01169
01170 ONUDPSocket *udpSocket = (ONUDPSocket *)[ONUDPSocket socket];
01171 [udpSocket setLocalPortNumber: localUdpPort allowingAddressReuse: YES];
01172 [udpSocket setAllowsBroadcast: YES];
01173
01174 [udpSocket setTimeOut:5000];
01175 NSLog([NSString stringWithFormat:@"Communication.openUdp: UDP: port is %d", localUdpPort]);
01176
01177
01178 [udpReader release];
01179 udpReader = [[ServerReaderUdp alloc] initWithUniverse:universe communication:self socket:udpSocket udpStats:udpStats];
01180 [udpSender release];
01181 udpSender = [[ServerSenderTcp alloc] initWithSocket:udpSocket];
01182
01183 return true;
01184 }
01185 @catch(NSException *e) {
01186
01187
01188
01189 if(baseLocalUdpPort > 0) {
01190 ++localUdpPort;
01191 }
01192 else {
01193 localUdpPort = ((localUdpPort + 10687) & 32767);
01194 }
01195 }
01196 }
01197 NSLog(@"Communication.openUdp: UDP: Unable to find a local port to bind to");
01198 return false;
01199 }
01200
01201 - (void) closeUdpConn {
01202 NSLog(@"Communication.closeUdpConn: UDP: Closing UDP socket");
01203 [udpReader close];
01204 [udpReader release];
01205 [udpSender close];
01206 [udpSender release];
01207 }
01208
01209 - (void) forceResetToTCP {
01210 NSLog(@"Communication.forceResetToTCP: UDP: FORCE RESET REQUESTED");
01211 [self sendUdpReq:[NSNumber numberWithChar:COMM_TCP]];
01212
01213 commMode = commModeRequest = COMM_TCP;
01214 commStatus = STAT_CONNECTED;
01215 [self closeUdpConn];
01216 }
01217
01218
01219 - (void) setUpAndRunThread:(id)sender {
01220
01221
01222 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
01223
01224 NSLog(@"Communication.setUpAndRunThread: start running");
01225 [notificationCenter postNotificationName:@"COMM_STARTED_THREAD" object:self userInfo:nil];
01226
01227
01228 [[NSRunLoop currentRunLoop] run];
01229
01230 NSLog(@"Communication.setUpAndRunThread: stop running");
01231 isRunning = NO;
01232 [notificationCenter postNotificationName:@"COMM_STOPPED_THREAD" object:self userInfo:nil];
01233
01234
01235 [pool release];
01236 }
01237
01238 - (void) run {
01239 [self run:self];
01240 }
01241
01242 - (void) run:(id)sender {
01243 NSLog(@"Communication.run started");
01244
01245
01246
01247
01248 if (multiThreaded) {
01249
01250 while (keepRunning) {
01251
01252
01253 [self readFromServer];
01254
01255
01256 }
01257 NSLog(@"Communication.run stopped");
01258 isRunning = NO;
01259 } else {
01260
01261 [NSTimer scheduledTimerWithTimeInterval: 0.001
01262 target:self selector:@selector(readFromServer)
01263 userInfo:nil
01264 repeats:YES];
01265 }
01266 }
01267
01268
01269 - (void) periodicReadFromServer {
01270 if (isRunning && keepRunning) {
01271 [self readFromServer];
01272 }
01273 }
01274
01275 - (bool) startCommunicationThread {
01276
01277 if (isRunning) {
01278 NSLog(@"Communication.startCommunicationThread: already running");
01279 return NO;
01280 }
01281
01282 isRunning = YES;
01283 keepRunning = YES;
01284
01285
01287 [LLThreadWorker workOn:self
01288 withSelector:@selector(run:)
01289 withObject:nil
01290 didEndSelector:nil];
01291
01292 return YES;
01293 }
01294
01295 - (bool) stopCommunicationThread {
01296 if (!isRunning) {
01297 NSLog(@"Communication.stopCommunicationThread: not running");
01298 return NO;
01299 }
01300 NSLog(@"Communication.stopCommunicationThread: asking thread to stop wait for notification");
01301 keepRunning = NO;
01302
01303 return YES;
01304 }
01305
01306
01307 @end