# HG changeset patch # User koda # Date 1292535998 -3600 # Node ID b70004a576a32368aa8c0021c09da813fbd2425a # Parent a6402b8c2b24e58854da9c28c92c7a613c98d3da move server connection stuff in its own class diff -r a6402b8c2b24 -r b70004a576a3 project_files/HedgewarsMobile/Classes/GameSetup.m --- a/project_files/HedgewarsMobile/Classes/GameSetup.m Thu Dec 16 15:26:19 2010 -0500 +++ b/project_files/HedgewarsMobile/Classes/GameSetup.m Thu Dec 16 22:46:38 2010 +0100 @@ -21,7 +21,6 @@ #import "GameSetup.h" #import "SDL_uikitappdelegate.h" -#import "SDL_net.h" #import "PascalImports.h" #import "CommodityFunctions.h" #import "OverlayViewController.h" @@ -216,13 +215,7 @@ } #pragma mark - -#pragma mark Thread/Network relevant code -// select one of GameSetup method and execute it in a seprate thread --(void) startThread:(NSString *)selector { - SEL usage = NSSelectorFromString(selector); - [NSThread detachNewThreadSelector:usage toTarget:self withObject:nil]; -} - +#pragma mark Network relevant code -(void) dumpRawData:(const uint8_t*)buffer ofSize:(uint8_t) length { // is it performant to reopen the stream every time? NSOutputStream *os = [[NSOutputStream alloc] initToFileAtPath:self.savePath append:YES]; @@ -250,148 +243,6 @@ return SDLNet_TCP_Send(csd, [string UTF8String], length); } --(int) sendToServer:(NSString *)command withArgument:(NSString *)argument { - NSString *message = [[NSString alloc] initWithFormat:@"%@\n%@\n\n",command,argument]; - int result = SDLNet_TCP_Send(esd, [message UTF8String], [message length]); - [message release]; - return result; -} - --(int) sendToServer:(NSString *)command { - NSString *message = [[NSString alloc] initWithFormat:@"%@\n\n",command]; - int result = SDLNet_TCP_Send(esd, [message UTF8String], [message length]); - [message release]; - return result; -} - --(void) serverProtocol { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - IPaddress ip; - BOOL clientQuit = NO; - char *buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE); - int dim = BUFFER_SIZE; - uint8_t msgSize; - NSString *arg = nil; - - if (SDLNet_Init() < 0) { - DLog(@"SDLNet_Init: %s", SDLNet_GetError()); - clientQuit = YES; - } - - // Resolving the host using NULL make network interface to listen - if (SDLNet_ResolveHost(&ip, "netserver.hedgewars.org", DEFAULT_NETGAME_PORT) < 0 && !clientQuit) { - DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError()); - clientQuit = YES; - } - - // Open a connection with the IP provided (listen on the host's port) - if (!(esd = SDLNet_TCP_Open(&ip)) && !clientQuit) { - DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), DEFAULT_NETGAME_PORT); - clientQuit = YES; - } - - DLog(@"Found server on port %d", DEFAULT_NETGAME_PORT); - while (!clientQuit) { - int index = 0; - BOOL exitBufferLoop = NO; - memset(buffer, '\0', dim); - - while (exitBufferLoop != YES) { - msgSize = SDLNet_TCP_Recv(esd, &buffer[index], 2); - - // exit in case of error - if (msgSize <= 0) { - DLog(@"SDLNet_TCP_Recv: %s", SDLNet_GetError()); - clientQuit = YES; - break; - } - - // update index position and check for End-Of-Message - index += msgSize; - if (strncmp(&buffer[index-2], "\n\n", 2) == 0) { - exitBufferLoop = YES; - } - - // if message is too big allocate new space - if (index >= dim) { - dim += BUFFER_SIZE; - buffer = (char *)realloc(buffer, dim); - if (buffer == NULL) { - clientQuit = YES; - break; - } - } - } - - NSString *bufferedMessage = [[NSString alloc] initWithBytes:buffer length:index-2 encoding:NSASCIIStringEncoding]; - NSArray *listOfCommands = [bufferedMessage componentsSeparatedByString:@"\n"]; - [bufferedMessage release]; - NSString *command = [listOfCommands objectAtIndex:0]; - DLog(@"size = %d, %@", index-2, listOfCommands); - if ([command isEqualToString:@"PING"]) { - if ([listOfCommands count] > 1) - [self sendToServer:@"PONG" withArgument:[listOfCommands objectAtIndex:1]]; - else - [self sendToServer:@"PONG"]; - - [arg release]; - } - else if ([command isEqualToString:@"NICK"]) { - //TODO: what is this for? - } - else if ([command isEqualToString:@"PROTO"]) { - if ([[listOfCommands objectAtIndex:1] intValue] == 34) { - //TODO: unused - } - } - else if ([command isEqualToString:@"ROOM"]) { - //TODO: stub - } - else if ([command isEqualToString:@"LOBBY:LEFT"]) { - //TODO: stub - } - else if ([command isEqualToString:@"LOBBY:JOINED"]) { - //TODO: stub - } - else if ([command isEqualToString:@"ASKPASSWORD"]) { - //TODO: store hashed password in settings.plist (nil here will vouluntary trigger an exception) - [self sendToServer:@"PASSWORD" withArgument:nil]; - } - else if ([command isEqualToString:@"CONNECTED"]) { - [self sendToServer:@"NICK" withArgument:@"koda"]; - [self sendToServer:@"PROTO" withArgument:@"34"]; - } - else if ([command isEqualToString:@"SERVER_MESSAGE"]) { - DLog(@"%@", [listOfCommands objectAtIndex:1]); - } - else if ([command isEqualToString:@"WARNING"]) { - if ([listOfCommands count] > 1) - DLog(@"Server warning - %@", [listOfCommands objectAtIndex:1]); - else - DLog(@"Server warning - unknown"); - } - else if ([command isEqualToString:@"ERROR"]) { - DLog(@"Server error - %@", [listOfCommands objectAtIndex:1]); - } - else if ([command isEqualToString:@"BYE"]) { - //TODO: handle "Reconnected too fast" - DLog(@"Server disconnected, reason: %@", [listOfCommands objectAtIndex:1]); - clientQuit = YES; - } - else { - DLog(@"Unknown/Unsupported message received: %@", command); - } - } - DLog(@"Server exited, ending thread"); - - free(buffer); - // Close the client socket - SDLNet_TCP_Close(esd); - SDLNet_Quit(); - - [pool release]; -} - // method that handles net setup with engine and keeps connection alive -(void) engineProtocol { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -494,7 +345,7 @@ [self dumpRawData:buffer ofSize:msgSize]; sscanf((char *)buffer, "%*s %d", &eProto); - short int netProto = 0; + short int netProto; char *versionStr; HW_versionInfo(&netProto, &versionStr); diff -r a6402b8c2b24 -r b70004a576a3 project_files/HedgewarsMobile/Classes/MainMenuViewController.m --- a/project_files/HedgewarsMobile/Classes/MainMenuViewController.m Thu Dec 16 15:26:19 2010 -0500 +++ b/project_files/HedgewarsMobile/Classes/MainMenuViewController.m Thu Dec 16 22:46:38 2010 +0100 @@ -27,6 +27,7 @@ #import "SplitViewRootController.h" #import "AboutViewController.h" #import "SavedGamesViewController.h" +#import "ServerSetup.h" @implementation MainMenuViewController @synthesize gameConfigViewController, settingsViewController, aboutViewController, savedGamesViewController; @@ -124,6 +125,15 @@ [userDefaults synchronize]; [self createNecessaryFiles]; } + + ServerSetup *setup = [[ServerSetup alloc] init]; + if ([setup isNetworkReachable]) { + DLog(@"network is reachable"); + [NSThread detachNewThreadSelector:@selector(serverProtocol) + toTarget:setup + withObject:nil]; + } + [setup release]; } diff -r a6402b8c2b24 -r b70004a576a3 project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m --- a/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m Thu Dec 16 15:26:19 2010 -0500 +++ b/project_files/HedgewarsMobile/Classes/SDL_uikitappdelegate.m Thu Dec 16 22:46:38 2010 +0100 @@ -121,10 +121,10 @@ // pull out useful configuration info from various files GameSetup *setup = [[GameSetup alloc] initWithDictionary:gameDictionary]; NSNumber *isNetGameNum = [gameDictionary objectForKey:@"netgame"]; - - [setup startThread:@"engineProtocol"]; - if ([isNetGameNum boolValue] == YES) - [setup startThread:@"serverProtocol"]; + + [NSThread detachNewThreadSelector:@selector(engineProtocol) + toTarget:setup + withObject:nil]; const char **gameArgs = [setup getSettings:[gameDictionary objectForKey:@"savefile"]]; NSNumber *menuStyle = [NSNumber numberWithBool:setup.menuStyle]; diff -r a6402b8c2b24 -r b70004a576a3 project_files/HedgewarsMobile/Classes/ServerSetup.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/ServerSetup.h Thu Dec 16 22:46:38 2010 +0100 @@ -0,0 +1,35 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2009-2010 Vittorio Giovara + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * File created on 16/12/2010. + */ + + +#import +#import "SDL_net.h" + +@interface ServerSetup : NSObject { + NSDictionary *systemSettings; + + TCPsocket sd; // External socket descriptor +} + +@property (nonatomic, retain) NSDictionary *systemSettings; + +-(BOOL) isNetworkReachable; + +@end diff -r a6402b8c2b24 -r b70004a576a3 project_files/HedgewarsMobile/Classes/ServerSetup.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/ServerSetup.m Thu Dec 16 22:46:38 2010 +0100 @@ -0,0 +1,221 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2009-2010 Vittorio Giovara + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; version 2 of the License + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * File created on 10/01/2010. + */ + + +#import "ServerSetup.h" +#import "PascalImports.h" +#import "CommodityFunctions.h" +#import +#import + +#define BUFFER_SIZE 256 + +@implementation ServerSetup +@synthesize systemSettings; + +-(id) init { + if (self = [super init]) { + NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:SETTINGS_FILE()]; + self.systemSettings = dict; + [dict release]; + } + return self; +} + +-(void) dealloc { + + [super dealloc]; +} + +// reusing appirater method +-(BOOL) isNetworkReachable { + // Create zero addy + struct sockaddr_in zeroAddress; + bzero(&zeroAddress, sizeof(zeroAddress)); + zeroAddress.sin_len = sizeof(zeroAddress); + zeroAddress.sin_family = AF_INET; + + // Recover reachability flags + SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress); + SCNetworkReachabilityFlags flags; + + BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags); + CFRelease(defaultRouteReachability); + + if (!didRetrieveFlags) { + NSLog(@"Error. Could not recover network reachability flags"); + return NO; + } + + BOOL isReachable = flags & kSCNetworkFlagsReachable; + BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired; + BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection; + + NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"]; + NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL + cachePolicy:NSURLRequestReloadIgnoringLocalCacheData + timeoutInterval:20.0]; + NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self]; + + return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO; +} + +-(int) sendToServer:(NSString *)command { + NSString *message = [[NSString alloc] initWithFormat:@"%@\n\n",command]; + int result = SDLNet_TCP_Send(sd, [message UTF8String], [message length]); + [message release]; + return result; +} + +-(int) sendToServer:(NSString *)command withArgument:(NSString *)argument { + NSString *message = [[NSString alloc] initWithFormat:@"%@\n%@\n\n",command,argument]; + int result = SDLNet_TCP_Send(sd, [message UTF8String], [message length]); + [message release]; + return result; +} + +-(void) serverProtocol { + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + IPaddress ip; + BOOL clientQuit = NO; + char *buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE); + int dim = BUFFER_SIZE; + uint8_t msgSize; + + if (SDLNet_Init() < 0) { + DLog(@"SDLNet_Init: %s", SDLNet_GetError()); + clientQuit = YES; + } + + // Resolving the host using NULL make network interface to listen + if (SDLNet_ResolveHost(&ip, "netserver.hedgewars.org", DEFAULT_NETGAME_PORT) < 0 && !clientQuit) { + DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError()); + clientQuit = YES; + } + + // Open a connection with the IP provided (listen on the host's port) + if (!(sd = SDLNet_TCP_Open(&ip)) && !clientQuit) { + DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), DEFAULT_NETGAME_PORT); + clientQuit = YES; + } + + DLog(@"Found server on port %d", DEFAULT_NETGAME_PORT); + while (!clientQuit) { + int index = 0; + BOOL exitBufferLoop = NO; + memset(buffer, '\0', dim); + + while (exitBufferLoop != YES) { + msgSize = SDLNet_TCP_Recv(sd, &buffer[index], 2); + + // exit in case of error + if (msgSize <= 0) { + DLog(@"SDLNet_TCP_Recv: %s", SDLNet_GetError()); + clientQuit = YES; + break; + } + + // update index position and check for End-Of-Message + index += msgSize; + if (strncmp(&buffer[index-2], "\n\n", 2) == 0) { + exitBufferLoop = YES; + } + + // if message is too big allocate new space + if (index >= dim) { + dim += BUFFER_SIZE; + buffer = (char *)realloc(buffer, dim); + if (buffer == NULL) { + clientQuit = YES; + break; + } + } + } + + NSString *bufferedMessage = [[NSString alloc] initWithBytes:buffer length:index-2 encoding:NSASCIIStringEncoding]; + NSArray *listOfCommands = [bufferedMessage componentsSeparatedByString:@"\n"]; + [bufferedMessage release]; + NSString *command = [listOfCommands objectAtIndex:0]; + DLog(@"size = %d, %@", index-2, listOfCommands); + if ([command isEqualToString:@"PING"]) { + if ([listOfCommands count] > 1) + [self sendToServer:@"PONG" withArgument:[listOfCommands objectAtIndex:1]]; + else + [self sendToServer:@"PONG"]; + DLog(@"PONG"); + } + else if ([command isEqualToString:@"NICK"]) { + //what is this for? + } + else if ([command isEqualToString:@"PROTO"]) { + //what is this for? + } + else if ([command isEqualToString:@"ROOM"]) { + //TODO: stub + } + else if ([command isEqualToString:@"LOBBY:LEFT"]) { + //TODO: stub + } + else if ([command isEqualToString:@"LOBBY:JOINED"]) { + //TODO: stub + } + else if ([command isEqualToString:@"ASKPASSWORD"]) { + NSString *pwd = [self.systemSettings objectForKey:@"password"]; + [self sendToServer:@"PASSWORD" withArgument:pwd]; + } + else if ([command isEqualToString:@"CONNECTED"]) { + short int netProto; + char *versionStr; + HW_versionInfo(&netProto, &versionStr); + NSString *nick = [self.systemSettings objectForKey:@"username"]; + [self sendToServer:@"NICK" withArgument:nick]; + [self sendToServer:@"PROTO" withArgument:[NSString stringWithFormat:@"%d",netProto]]; + } + else if ([command isEqualToString:@"SERVER_MESSAGE"]) { + DLog(@"%@", [listOfCommands objectAtIndex:1]); + } + else if ([command isEqualToString:@"WARNING"]) { + if ([listOfCommands count] > 1) + DLog(@"Server warning - %@", [listOfCommands objectAtIndex:1]); + else + DLog(@"Server warning - unknown"); + } + else if ([command isEqualToString:@"ERROR"]) { + DLog(@"Server error - %@", [listOfCommands objectAtIndex:1]); + } + else if ([command isEqualToString:@"BYE"]) { + //TODO: handle "Reconnected too fast" + DLog(@"Server disconnected, reason: %@", [listOfCommands objectAtIndex:1]); + clientQuit = YES; + } + else { + DLog(@"Unknown/Unsupported message received: %@", command); + } + } + DLog(@"Server closed connection, ending thread"); + + free(buffer); + SDLNet_TCP_Close(sd); + SDLNet_Quit(); + + [pool release]; +} + +@end diff -r a6402b8c2b24 -r b70004a576a3 project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj --- a/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj Thu Dec 16 15:26:19 2010 -0500 +++ b/project_files/HedgewarsMobile/Hedgewars.xcodeproj/project.pbxproj Thu Dec 16 22:46:38 2010 +0100 @@ -191,6 +191,7 @@ 61DF0EDC1284DF2300F3F10B /* HelpPageLobbyViewController-iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 61DF0EDB1284DF2300F3F10B /* HelpPageLobbyViewController-iPhone.xib */; }; 61DF0F211284F72A00F3F10B /* HelpPageInGameViewController-iPhone.xib in Resources */ = {isa = PBXBuildFile; fileRef = 61DF0F201284F72A00F3F10B /* HelpPageInGameViewController-iPhone.xib */; }; 61E1F4F811D004240016A5AA /* adler32.pas in Sources */ = {isa = PBXBuildFile; fileRef = 61E1F4F711D004240016A5AA /* adler32.pas */; }; + 61E2E12E12BAAEE30051B659 /* ServerSetup.m in Sources */ = {isa = PBXBuildFile; fileRef = 61E2E12D12BAAEE30051B659 /* ServerSetup.m */; }; 61E2F7441283752C00E12521 /* fb.png in Resources */ = {isa = PBXBuildFile; fileRef = 61E2F7421283752C00E12521 /* fb.png */; }; 61E2F7451283752C00E12521 /* tw.png in Resources */ = {isa = PBXBuildFile; fileRef = 61E2F7431283752C00E12521 /* tw.png */; }; 61E5D68D12AB006F00566F29 /* uLandPainted.pas in Sources */ = {isa = PBXBuildFile; fileRef = 61E5D68C12AB006F00566F29 /* uLandPainted.pas */; }; @@ -971,6 +972,8 @@ 61DF0EDB1284DF2300F3F10B /* HelpPageLobbyViewController-iPhone.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "HelpPageLobbyViewController-iPhone.xib"; path = "../Resources/HelpPageLobbyViewController-iPhone.xib"; sourceTree = ""; }; 61DF0F201284F72A00F3F10B /* HelpPageInGameViewController-iPhone.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "HelpPageInGameViewController-iPhone.xib"; path = "Resources/HelpPageInGameViewController-iPhone.xib"; sourceTree = SOURCE_ROOT; }; 61E1F4F711D004240016A5AA /* adler32.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = adler32.pas; path = ../../hedgewars/adler32.pas; sourceTree = SOURCE_ROOT; }; + 61E2E12C12BAAEE30051B659 /* ServerSetup.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ServerSetup.h; sourceTree = ""; }; + 61E2E12D12BAAEE30051B659 /* ServerSetup.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ServerSetup.m; sourceTree = ""; }; 61E2F7421283752C00E12521 /* fb.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = fb.png; path = Resources/Icons/fb.png; sourceTree = ""; }; 61E2F7431283752C00E12521 /* tw.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = tw.png; path = Resources/Icons/tw.png; sourceTree = ""; }; 61E5D68C12AB006F00566F29 /* uLandPainted.pas */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.pascal; name = uLandPainted.pas; path = ../../hedgewars/uLandPainted.pas; sourceTree = SOURCE_ROOT; }; @@ -1046,6 +1049,8 @@ 6165924C11CA9CB400D6E256 /* MainMenuViewController-iPhone.xib */, 616591E611CA9BA200D6E256 /* GameSetup.h */, 616591E711CA9BA200D6E256 /* GameSetup.m */, + 61E2E12C12BAAEE30051B659 /* ServerSetup.h */, + 61E2E12D12BAAEE30051B659 /* ServerSetup.m */, ); path = Classes; sourceTree = ""; @@ -2418,6 +2423,7 @@ 61E5D68D12AB006F00566F29 /* uLandPainted.pas in Sources */, 61F544C712AF1748007FD913 /* HoldTableViewCell.m in Sources */, 61AC067412B2E32D000B52A2 /* Appirater.m in Sources */, + 61E2E12E12BAAEE30051B659 /* ServerSetup.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; };