RoUTP 1.1.0

RoUTP 1.1.0

TestsTested
LangLanguage Obj-CObjective C
License MIT
ReleasedLast Release Dec 2014

Maintained by Yan Rabovik.



RoUTP 1.1.0

  • By
  • Yan Rabovik

Reliable-over-Unreliable Transport Protocol

RoUTP is an Objective-C implementation of a simple Reliable-over-Unreliable Transport Protocol. Its primary goal is a workaround for «GKMatch GKMatchSendDataReliable packet loss bug» in Apple Game Center (see SO question & confirming example). But generally it may be used over any other unreliable protocol.

How it works

RoUTP acts as an additional transport layer between your app and unreliable transport. It saves all sent messages until acknowledgement for each received, resends lost and buffers received messages in case of broken sequence. Technically the sender numbers all sent messages and the receiver regularly sends positive selective acknowledgments.

Integration

Here is an example of using RoUTP in 2-player Game Center game. Suppose the code looks like

@interface MyController : UIViewController <GKMatchDelegate>
@property (nonatomic,strong) GKMatch *gkMatch;
@end

@implementation MyController
-(void)sendData:(NSData *)data{
    NSError *error;
    [self.gkMatch sendDataToAllPlayers:data
                          withDataMode:GKMatchSendDataReliable
                                 error:&error];
    // …
}
-(void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID{
    [self doSomethingWithReceivedData:data];
}
@end

Let's add RoUTP

// 1. Import ROUSession.h header
#import "ROUSession.h"
@interface MyController : UIViewController <GKMatchDelegate,
                        ROUSessionDelegate> // 2. implement its delegate
@property (nonatomic,strong) GKMatch *gkMatch;
@property (nonatomic,strong) ROUSession *rouSession; // 3. add ROUSession property
@end

@implementation MyController
-(void)startGame{
    // 4. Make a ROUSession instance and set its delegate
    self.rouSession = [ROUSession new];
    self.rouSession.delegate = self;
}
-(void)sendData:(NSData *)data{
    // 5. Send data to ROUSession instead of GKMatch
    [self.rouSession sendData:data];
}
-(void)match:(GKMatch *)match didReceiveData:(NSData *)data fromPlayer:(NSString *)playerID{
    // 6. Send data from GKMatch to ROUSession
    [self.rouSession receiveData:data];
}
-(void)session:(ROUSession *)session preparedDataForSending:(NSData *)data{
    // 7. Send prepared data from ROUSession to GKMatch
    NSError *error;
    [self.gkMatch sendDataToAllPlayers:data
                          withDataMode:GKMatchSendDataUnreliable // we can use unreliable mode now
                                 error:&error];
    // …    
}
-(void)session:(ROUSession *)session receivedData:(NSData *)data{
    // 8. Process ready data from ROUSession
    [self doSomethingWithReceivedData:data];
}
-(void)endGame{
    // 9. Clean delegate and release session when it is no more needed.
    self.rouSession.delegate = nil;
    self.rouSession = nil;
}
@end

Requirements

  • iOS 5.0 and later
  • ARC

License

MIT License.