project_files/HedgewarsMobile/Classes/ServerSetup.m
changeset 4547 b70004a576a3
child 4603 d362ab6c7f53
equal deleted inserted replaced
4546:a6402b8c2b24 4547:b70004a576a3
       
     1 /*
       
     2  * Hedgewars-iOS, a Hedgewars port for iOS devices
       
     3  * Copyright (c) 2009-2010 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 "ServerSetup.h"
       
    23 #import "PascalImports.h"
       
    24 #import "CommodityFunctions.h"
       
    25 #import <SystemConfiguration/SCNetworkReachability.h>
       
    26 #import <netinet/in.h>
       
    27 
       
    28 #define BUFFER_SIZE 256
       
    29 
       
    30 @implementation ServerSetup
       
    31 @synthesize systemSettings;
       
    32 
       
    33 -(id) init {
       
    34     if (self = [super init]) {
       
    35         NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:SETTINGS_FILE()];
       
    36         self.systemSettings = dict;
       
    37         [dict release];
       
    38     }
       
    39     return self;
       
    40 }
       
    41 
       
    42 -(void) dealloc {
       
    43 
       
    44     [super dealloc];
       
    45 }
       
    46 
       
    47 // reusing appirater method
       
    48 -(BOOL) isNetworkReachable {
       
    49     // Create zero addy
       
    50     struct sockaddr_in zeroAddress;
       
    51     bzero(&zeroAddress, sizeof(zeroAddress));
       
    52     zeroAddress.sin_len = sizeof(zeroAddress);
       
    53     zeroAddress.sin_family = AF_INET;
       
    54     
       
    55     // Recover reachability flags
       
    56     SCNetworkReachabilityRef defaultRouteReachability = SCNetworkReachabilityCreateWithAddress(NULL, (struct sockaddr *)&zeroAddress);
       
    57     SCNetworkReachabilityFlags flags;
       
    58     
       
    59     BOOL didRetrieveFlags = SCNetworkReachabilityGetFlags(defaultRouteReachability, &flags);
       
    60     CFRelease(defaultRouteReachability);
       
    61     
       
    62     if (!didRetrieveFlags) {
       
    63         NSLog(@"Error. Could not recover network reachability flags");
       
    64         return NO;
       
    65     }
       
    66     
       
    67     BOOL isReachable = flags & kSCNetworkFlagsReachable;
       
    68     BOOL needsConnection = flags & kSCNetworkFlagsConnectionRequired;
       
    69     BOOL nonWiFi = flags & kSCNetworkReachabilityFlagsTransientConnection;
       
    70     
       
    71     NSURL *testURL = [NSURL URLWithString:@"http://www.apple.com/"];
       
    72     NSURLRequest *testRequest = [NSURLRequest requestWithURL:testURL
       
    73                                                  cachePolicy:NSURLRequestReloadIgnoringLocalCacheData
       
    74                                              timeoutInterval:20.0];
       
    75     NSURLConnection *testConnection = [[NSURLConnection alloc] initWithRequest:testRequest delegate:self];
       
    76     
       
    77     return ((isReachable && !needsConnection) || nonWiFi) ? (testConnection ? YES : NO) : NO;
       
    78 }
       
    79 
       
    80 -(int) sendToServer:(NSString *)command {
       
    81     NSString *message = [[NSString alloc] initWithFormat:@"%@\n\n",command];
       
    82     int result = SDLNet_TCP_Send(sd, [message UTF8String], [message length]);
       
    83     [message release];
       
    84     return result;
       
    85 }
       
    86 
       
    87 -(int) sendToServer:(NSString *)command withArgument:(NSString *)argument {
       
    88     NSString *message = [[NSString alloc] initWithFormat:@"%@\n%@\n\n",command,argument];
       
    89     int result = SDLNet_TCP_Send(sd, [message UTF8String], [message length]);
       
    90     [message release];
       
    91     return result;
       
    92 }
       
    93 
       
    94 -(void) serverProtocol {
       
    95     NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
       
    96     IPaddress ip;
       
    97     BOOL clientQuit = NO;
       
    98     char *buffer = (char *)malloc(sizeof(char)*BUFFER_SIZE);
       
    99     int dim = BUFFER_SIZE;
       
   100     uint8_t msgSize;
       
   101 
       
   102     if (SDLNet_Init() < 0) {
       
   103         DLog(@"SDLNet_Init: %s", SDLNet_GetError());
       
   104         clientQuit = YES;
       
   105     }
       
   106 
       
   107     // Resolving the host using NULL make network interface to listen
       
   108     if (SDLNet_ResolveHost(&ip, "netserver.hedgewars.org", DEFAULT_NETGAME_PORT) < 0 && !clientQuit) {
       
   109         DLog(@"SDLNet_ResolveHost: %s\n", SDLNet_GetError());
       
   110         clientQuit = YES;
       
   111     }
       
   112 
       
   113     // Open a connection with the IP provided (listen on the host's port)
       
   114     if (!(sd = SDLNet_TCP_Open(&ip)) && !clientQuit) {
       
   115         DLog(@"SDLNet_TCP_Open: %s %\n", SDLNet_GetError(), DEFAULT_NETGAME_PORT);
       
   116         clientQuit = YES;
       
   117     }
       
   118 
       
   119     DLog(@"Found server on port %d", DEFAULT_NETGAME_PORT);
       
   120     while (!clientQuit) {
       
   121         int index = 0;
       
   122         BOOL exitBufferLoop = NO;
       
   123         memset(buffer, '\0', dim);
       
   124         
       
   125         while (exitBufferLoop != YES) {
       
   126             msgSize = SDLNet_TCP_Recv(sd, &buffer[index], 2);
       
   127             
       
   128             // exit in case of error
       
   129             if (msgSize <= 0) {
       
   130                 DLog(@"SDLNet_TCP_Recv: %s", SDLNet_GetError());
       
   131                 clientQuit = YES;
       
   132                 break;
       
   133             }
       
   134             
       
   135             // update index position and check for End-Of-Message
       
   136             index += msgSize;
       
   137             if (strncmp(&buffer[index-2], "\n\n", 2) == 0) {
       
   138                 exitBufferLoop = YES;
       
   139             }
       
   140             
       
   141             // if message is too big allocate new space
       
   142             if (index >= dim) {
       
   143                 dim += BUFFER_SIZE;
       
   144                 buffer = (char *)realloc(buffer, dim);
       
   145                 if (buffer == NULL) {
       
   146                     clientQuit = YES;
       
   147                     break;
       
   148                 }
       
   149             }
       
   150         }
       
   151 
       
   152         NSString *bufferedMessage = [[NSString alloc] initWithBytes:buffer length:index-2 encoding:NSASCIIStringEncoding];
       
   153         NSArray *listOfCommands = [bufferedMessage componentsSeparatedByString:@"\n"];
       
   154         [bufferedMessage release];
       
   155         NSString *command = [listOfCommands objectAtIndex:0];
       
   156         DLog(@"size = %d, %@", index-2, listOfCommands);
       
   157         if ([command isEqualToString:@"PING"]) {
       
   158             if ([listOfCommands count] > 1)
       
   159                 [self sendToServer:@"PONG" withArgument:[listOfCommands objectAtIndex:1]];
       
   160             else
       
   161                 [self sendToServer:@"PONG"];
       
   162             DLog(@"PONG");
       
   163         }
       
   164         else if ([command isEqualToString:@"NICK"]) {
       
   165             //what is this for?
       
   166         }
       
   167         else if ([command isEqualToString:@"PROTO"]) {
       
   168             //what is this for?
       
   169         }
       
   170         else if ([command isEqualToString:@"ROOM"]) {
       
   171             //TODO: stub
       
   172         }
       
   173         else if ([command isEqualToString:@"LOBBY:LEFT"]) {
       
   174             //TODO: stub
       
   175         }
       
   176         else if ([command isEqualToString:@"LOBBY:JOINED"]) {
       
   177             //TODO: stub
       
   178         }
       
   179         else if ([command isEqualToString:@"ASKPASSWORD"]) {
       
   180             NSString *pwd = [self.systemSettings objectForKey:@"password"];
       
   181             [self sendToServer:@"PASSWORD" withArgument:pwd];
       
   182         }
       
   183         else if ([command isEqualToString:@"CONNECTED"]) {
       
   184             short int netProto;
       
   185             char *versionStr;
       
   186             HW_versionInfo(&netProto, &versionStr);
       
   187             NSString *nick = [self.systemSettings objectForKey:@"username"];
       
   188             [self sendToServer:@"NICK" withArgument:nick];
       
   189             [self sendToServer:@"PROTO" withArgument:[NSString stringWithFormat:@"%d",netProto]];
       
   190         }
       
   191         else if ([command isEqualToString:@"SERVER_MESSAGE"]) {
       
   192             DLog(@"%@", [listOfCommands objectAtIndex:1]);
       
   193         }
       
   194         else if ([command isEqualToString:@"WARNING"]) {
       
   195             if ([listOfCommands count] > 1)
       
   196                 DLog(@"Server warning - %@", [listOfCommands objectAtIndex:1]);
       
   197             else
       
   198                 DLog(@"Server warning - unknown");
       
   199         }
       
   200         else if ([command isEqualToString:@"ERROR"]) {
       
   201             DLog(@"Server error - %@", [listOfCommands objectAtIndex:1]);
       
   202         }
       
   203         else if ([command isEqualToString:@"BYE"]) {
       
   204             //TODO: handle "Reconnected too fast"
       
   205             DLog(@"Server disconnected, reason: %@", [listOfCommands objectAtIndex:1]);
       
   206             clientQuit = YES;
       
   207         }
       
   208         else {
       
   209             DLog(@"Unknown/Unsupported message received: %@", command);
       
   210         }
       
   211     }
       
   212     DLog(@"Server closed connection, ending thread");
       
   213 
       
   214     free(buffer);
       
   215     SDLNet_TCP_Close(sd);
       
   216     SDLNet_Quit();
       
   217 
       
   218     [pool release];
       
   219 }
       
   220 
       
   221 @end