diff -r 6df227b5e4c9 -r 6b2d19ed521a project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m Mon Oct 31 01:44:32 2011 +0100 @@ -0,0 +1,190 @@ +/* + * Hedgewars-iOS, a Hedgewars port for iOS devices + * Copyright (c) 2009-2011 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 "ServerProtocolNetwork.h" +#import "SDL_net.h" +#import "hwconsts.h" + +#define BUFFER_SIZE 256 + +static TCPsocket sd; +static ServerProtocolNetwork *serverConnection; + +@implementation ServerProtocolNetwork +@synthesize serverPort, serverAddress; + +-(id) init { + if (self = [super init]) { + self.serverPort = NETGAME_DEFAULT_PORT; + self.serverAddress = @"netserver.hedgewars.org"; + } + serverConnection = self; + return self; +} + +-(void) dealloc { + releaseAndNil(serverAddress); + [super dealloc]; +} + +-(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; + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + 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, [self.serverAddress UTF8String] , self.serverPort) < 0 && !clientQuit) { + DLog(@"SDLNet_ResolveHost: %s", 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 %d", SDLNet_GetError(), self.serverPort); + clientQuit = YES; + } + + DLog(@"Found server on port %d", self.serverPort); + 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 = [defaults objectForKey:@"password"]; + [self sendToServer:@"PASSWORD" withArgument:pwd]; + } + else if ([command isEqualToString:@"CONNECTED"]) { + int netProto; + char *versionStr; + HW_versionInfo(&netProto, &versionStr); + NSString *nick = [defaults 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