project_files/HedgewarsMobile/Classes/ServerProtocolNetwork.m
changeset 6246 6b2d19ed521a
parent 6078 8c0cc07731e5
child 6320 238a6dc0e7ad
equal deleted inserted replaced
6245:6df227b5e4c9 6246:6b2d19ed521a
       
     1 /*
       
     2  * Hedgewars-iOS, a Hedgewars port for iOS devices
       
     3  * Copyright (c) 2009-2011 Vittorio Giovara <vittorio.giovara@gmail.com>
       
     4  *
       
     5  * This program is free software; you can redistribute it and/or modify
       
     6  * it under the terms of the GNU General Public License as published by
       
     7  * the Free Software Foundation; version 2 of the License
       
     8  *
       
     9  * This program is distributed in the hope that it will be useful,
       
    10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
       
    11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       
    12  * GNU General Public License for more details.
       
    13  *
       
    14  * You should have received a copy of the GNU General Public License
       
    15  * along with this program; if not, write to the Free Software
       
    16  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
       
    17  *
       
    18  * File created on 10/01/2010.
       
    19  */
       
    20 
       
    21 
       
    22 #import "ServerProtocolNetwork.h"
       
    23 #import "SDL_net.h"
       
    24 #import "hwconsts.h"
       
    25 
       
    26 #define BUFFER_SIZE 256
       
    27 
       
    28 static TCPsocket sd;
       
    29 static ServerProtocolNetwork *serverConnection;
       
    30 
       
    31 @implementation ServerProtocolNetwork
       
    32 @synthesize serverPort, serverAddress;
       
    33 
       
    34 -(id) init {
       
    35     if (self = [super init]) {
       
    36         self.serverPort = NETGAME_DEFAULT_PORT;
       
    37         self.serverAddress = @"netserver.hedgewars.org";
       
    38     }
       
    39     serverConnection = self;
       
    40     return self;
       
    41 }
       
    42 
       
    43 -(void) dealloc {
       
    44     releaseAndNil(serverAddress);
       
    45     [super dealloc];
       
    46 }
       
    47 
       
    48 -(int) sendToServer:(NSString *)command {
       
    49     NSString *message = [[NSString alloc] initWithFormat:@"%@\n\n",command];
       
    50     int result = SDLNet_TCP_Send(sd, [message UTF8String], [message length]);
       
    51     [message release];
       
    52     return result;
       
    53 }
       
    54 
       
    55 -(int) sendToServer:(NSString *)command withArgument:(NSString *)argument {
       
    56     NSString *message = [[NSString alloc] initWithFormat:@"%@\n%@\n\n",command,argument];
       
    57     int result = SDLNet_TCP_Send(sd, [message UTF8String], [message length]);
       
    58     [message release];
       
    59     return result;
       
    60 }
       
    61 
       
    62 -(void) serverProtocol {
       
    63     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
    64     IPaddress ip;
       
    65     BOOL clientQuit = NO;
       
    66     char *buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE);
       
    67     int dim = BUFFER_SIZE;
       
    68     uint8_t msgSize;
       
    69     NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
       
    70 
       
    71     if (SDLNet_Init() < 0) {
       
    72         DLog(@"SDLNet_Init: %s", SDLNet_GetError());
       
    73         clientQuit = YES;
       
    74     }
       
    75 
       
    76     // Resolving the host using NULL make network interface to listen
       
    77     if (SDLNet_ResolveHost(&ip, [self.serverAddress UTF8String] , self.serverPort) < 0 && !clientQuit) {
       
    78         DLog(@"SDLNet_ResolveHost: %s", SDLNet_GetError());
       
    79         clientQuit = YES;
       
    80     }
       
    81 
       
    82     // Open a connection with the IP provided (listen on the host's port)
       
    83     if (!(sd = SDLNet_TCP_Open(&ip)) && !clientQuit) {
       
    84         DLog(@"SDLNet_TCP_Open: %s %d", SDLNet_GetError(), self.serverPort);
       
    85         clientQuit = YES;
       
    86     }
       
    87 
       
    88     DLog(@"Found server on port %d", self.serverPort);
       
    89     while (!clientQuit) {
       
    90         int index = 0;
       
    91         BOOL exitBufferLoop = NO;
       
    92         memset(buffer, '\0', dim);
       
    93 
       
    94         while (exitBufferLoop != YES) {
       
    95             msgSize = SDLNet_TCP_Recv(sd, &buffer[index], 2);
       
    96 
       
    97             // exit in case of error
       
    98             if (msgSize <= 0) {
       
    99                 DLog(@"SDLNet_TCP_Recv: %s", SDLNet_GetError());
       
   100                 clientQuit = YES;
       
   101                 break;
       
   102             }
       
   103 
       
   104             // update index position and check for End-Of-Message
       
   105             index += msgSize;
       
   106             if (strncmp(&buffer[index-2], "\n\n", 2) == 0) {
       
   107                 exitBufferLoop = YES;
       
   108             }
       
   109 
       
   110             // if message is too big allocate new space
       
   111             if (index >= dim) {
       
   112                 dim += BUFFER_SIZE;
       
   113                 buffer = (char *)realloc(buffer, dim);
       
   114                 if (buffer == NULL) {
       
   115                     clientQuit = YES;
       
   116                     break;
       
   117                 }
       
   118             }
       
   119         }
       
   120 
       
   121         NSString *bufferedMessage = [[NSString alloc] initWithBytes:buffer length:index-2 encoding:NSASCIIStringEncoding];
       
   122         NSArray *listOfCommands = [bufferedMessage componentsSeparatedByString:@"\n"];
       
   123         [bufferedMessage release];
       
   124         NSString *command = [listOfCommands objectAtIndex:0];
       
   125         DLog(@"size = %d, %@", index-2, listOfCommands);
       
   126         if ([command isEqualToString:@"PING"]) {
       
   127             if ([listOfCommands count] > 1)
       
   128                 [self sendToServer:@"PONG" withArgument:[listOfCommands objectAtIndex:1]];
       
   129             else
       
   130                 [self sendToServer:@"PONG"];
       
   131             DLog(@"PONG");
       
   132         }
       
   133         else if ([command isEqualToString:@"NICK"]) {
       
   134             //what is this for?
       
   135         }
       
   136         else if ([command isEqualToString:@"PROTO"]) {
       
   137             //what is this for?
       
   138         }
       
   139         else if ([command isEqualToString:@"ROOM"]) {
       
   140             //TODO: stub
       
   141         }
       
   142         else if ([command isEqualToString:@"LOBBY:LEFT"]) {
       
   143             //TODO: stub
       
   144         }
       
   145         else if ([command isEqualToString:@"LOBBY:JOINED"]) {
       
   146             //TODO: stub
       
   147         }
       
   148         else if ([command isEqualToString:@"ASKPASSWORD"]) {
       
   149             NSString *pwd = [defaults objectForKey:@"password"];
       
   150             [self sendToServer:@"PASSWORD" withArgument:pwd];
       
   151         }
       
   152         else if ([command isEqualToString:@"CONNECTED"]) {
       
   153             int netProto;
       
   154             char *versionStr;
       
   155             HW_versionInfo(&netProto, &versionStr);
       
   156             NSString *nick = [defaults objectForKey:@"username"];
       
   157             [self sendToServer:@"NICK" withArgument:nick];
       
   158             [self sendToServer:@"PROTO" withArgument:[NSString stringWithFormat:@"%d",netProto]];
       
   159         }
       
   160         else if ([command isEqualToString:@"SERVER_MESSAGE"]) {
       
   161             DLog(@"%@", [listOfCommands objectAtIndex:1]);
       
   162         }
       
   163         else if ([command isEqualToString:@"WARNING"]) {
       
   164             if ([listOfCommands count] > 1)
       
   165                 DLog(@"Server warning - %@", [listOfCommands objectAtIndex:1]);
       
   166             else
       
   167                 DLog(@"Server warning - unknown");
       
   168         }
       
   169         else if ([command isEqualToString:@"ERROR"]) {
       
   170             DLog(@"Server error - %@", [listOfCommands objectAtIndex:1]);
       
   171         }
       
   172         else if ([command isEqualToString:@"BYE"]) {
       
   173             //TODO: handle "Reconnected too fast"
       
   174             DLog(@"Server disconnected, reason: %@", [listOfCommands objectAtIndex:1]);
       
   175             clientQuit = YES;
       
   176         }
       
   177         else {
       
   178             DLog(@"Unknown/Unsupported message received: %@", command);
       
   179         }
       
   180     }
       
   181     DLog(@"Server closed connection, ending thread");
       
   182 
       
   183     free(buffer);
       
   184     SDLNet_TCP_Close(sd);
       
   185     SDLNet_Quit();
       
   186 
       
   187     [pool release];
       
   188 }
       
   189 
       
   190 @end