Permalink
Browse files

Added master backlog to websocket server

It was possible that a quickly loading remote could send its remoteinfo message before the master websocket connection was established. The remote would then not be recognized. This happened particularly on auto-reload. To solve it, we re-introduce (-_-) the master backlog - messages that arrive for the master before its connection is ready are remembered and delivered when the master websocket ist established.
  • Loading branch information...
BlackWolf committed Jul 4, 2015
1 parent 8a23530 commit c220e1236e15fa84609d778a0dec4c081d58b585
Showing with 51 additions and 28 deletions.
  1. +1 −1 Connichiwa/CWServerManager.h
  2. +50 −27 Connichiwa/CWServerManager.m
@@ -67,7 +67,7 @@ typedef NS_ENUM(NSInteger, CWServerManagerState)
*
* @return A new CWWebserverManager instance
*/
- (instancetype)initWithDocumentRoot:(NSString *)documentRoot;
//- (instancetype)initWithDocumentRoot:(NSString *)documentRoot;
/**
* Calling this method actually launches the webserver and initializes the HTTP and Websocket servers. The root of the webserver will be mapped to the given document root, the HTTP server will run on the given port and the websocket server will run on the given port + 1
@@ -24,6 +24,7 @@ @interface CWServerManager ()
@property (strong, readwrite) BLWebSocketsServer *websocketServer;
@property (readwrite) int localWebsocketID;
@property (strong, readwrite) NSMutableDictionary *websocketIdentifiers;
@property (strong, readwrite) NSMutableArray *masterBacklog;
@end
@@ -32,13 +33,11 @@ @interface CWServerManager ()
@implementation CWServerManager
- (instancetype)initWithDocumentRoot:(NSString *)documentRoot
- (instancetype)init
{
self = [super init];
self.state = CWServerManagerStateStopped;
self.documentRoot = documentRoot;
self.localWebsocketID = -1;
return self;
}
@@ -51,7 +50,9 @@ - (void)startWebserverWithDocumentRoot:(NSString *)documentRoot onPort:(int)port
self.state = CWServerManagerStateStarting;
self.documentRoot = documentRoot;
self.localWebsocketID = -1;
self.websocketIdentifiers = [NSMutableDictionary dictionary];
self.masterBacklog = [NSMutableArray array];
//
// WEBSERVER
@@ -177,41 +178,63 @@ - (BLWebSocketOnMessageHandler)onUnidentifiedWebsocketMessage {
[weakSelf.websocketServer setOnMessageHandler:[weakSelf onIdentifiedWebsocketMessage] forConnection:connectionID];
[weakSelf.websocketServer setOnCloseHandler:[weakSelf onIdentifiedWebsocketClosed] forConnection:connectionID];
}
//If the message identifies the local weblib's websocket, we can send
//any message that arrived for it before this point
if ([[message objectForKey:@"_name"] isEqualToString:@"_master_identification"]) {
for (NSDictionary *backlog in self.masterBacklog) {
int backlogCnnectionID = [[backlog objectForKey:@"connectionID"] intValue];
WSLog(4, @"Delivering backlogged message from %@ to master", [self identifierForConnectionID:backlogCnnectionID]);
[self _deliverMessage:[backlog objectForKey:@"messageData"] fromConnection:backlogCnnectionID];
}
}
};
}
- (BLWebSocketOnMessageHandler)onIdentifiedWebsocketMessage {
__weak typeof(self) weakSelf = self;
return ^void (int connectionID, NSData *messageData) {
NSDictionary *message = [CWUtil dictionaryFromJSONData:messageData];
NSNumber *value = [NSNumber numberWithInt:connectionID];
WSLog(4, @"Websocket message from %@ to %@: %@", [self.websocketIdentifiers allKeysForObject:value][0], [message objectForKey:@"_target"],[[NSString alloc] initWithData:messageData encoding:NSUTF8StringEncoding]);
//For identified websocket messages, the server basically acts as a message relay
//Check where the message is supposed to be sent to and deliver it
NSString *target = [message objectForKey:@"_target"];
//Messages with target broadcast are sent to everyone
//the _broadcastToSource key decides if the messages is sent back to
//its source
if ([target isEqualToString:@"broadcast"]) {
BOOL backToSource = [[message objectForKey:@"_broadcastToSource"] boolValue];
if (backToSource) {
[weakSelf.websocketServer pushMessageToAll:messageData];
} else {
[weakSelf.websocketServer pushMessageToAll:messageData except:@[ @(connectionID) ]];
}
return;
if (self.localWebsocketID < 0) {
//Master is not ready yet, backlog the message until he is
WSLog(4, @"Backlogging message from %@ to master: %@", [self identifierForConnectionID:connectionID],[[NSString alloc] initWithData:messageData encoding:NSUTF8StringEncoding]);
[self.masterBacklog addObject:@{ @"connectionID" : @(connectionID), @"messageData" : messageData}];
} else {
//Everything ready, deliver message
[weakSelf _deliverMessage:messageData fromConnection:connectionID];
}
//For all other targets, just try to deliver to the right websocket
[weakSelf.websocketServer pushMessage:messageData toConnection:[weakSelf connectionIDForIdentifier:target]];
};
}
- (void)_deliverMessage:(NSData *)messageData fromConnection:(int)connectionID {
NSDictionary *message = [CWUtil dictionaryFromJSONData:messageData];
// NSNumber *value = [NSNumber numberWithInt:connectionID];
WSLog(4, @"Websocket message from %@ to %@: %@", [self identifierForConnectionID:connectionID], [message objectForKey:@"_target"],[[NSString alloc] initWithData:messageData encoding:NSUTF8StringEncoding]);
//For identified websocket messages, the server basically acts as a message relay
//Check where the message is supposed to be sent to and deliver it
NSString *target = [message objectForKey:@"_target"];
//Messages with target broadcast are sent to everyone
//the _broadcastToSource key decides if the messages is sent back to
//its source
if ([target isEqualToString:@"broadcast"]) {
BOOL backToSource = [[message objectForKey:@"_broadcastToSource"] boolValue];
if (backToSource) {
[self.websocketServer pushMessageToAll:messageData];
} else {
[self.websocketServer pushMessageToAll:messageData except:@[ @(connectionID) ]];
}
return;
}
//For all other targets, just try to deliver to the right websocket
[self.websocketServer pushMessage:messageData toConnection:[self connectionIDForIdentifier:target]];
}
- (BLWebSocketOnCloseHandler)onIdentifiedWebsocketClosed {
__weak typeof(self) weakSelf = self;

0 comments on commit c220e12

Please sign in to comment.