Skip to content

Commit

Permalink
Added master backlog to websocket server
Browse files Browse the repository at this point in the history
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
Mario Schreiner committed Jul 4, 2015
1 parent 8a23530 commit c220e12
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 28 deletions.
2 changes: 1 addition & 1 deletion Connichiwa/CWServerManager.h
Expand Up @@ -67,7 +67,7 @@ typedef NS_ENUM(NSInteger, CWServerManagerState)
* *
* @return A new CWWebserverManager instance * @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 * 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
Expand Down
77 changes: 50 additions & 27 deletions Connichiwa/CWServerManager.m
Expand Up @@ -24,6 +24,7 @@ @interface CWServerManager ()
@property (strong, readwrite) BLWebSocketsServer *websocketServer; @property (strong, readwrite) BLWebSocketsServer *websocketServer;
@property (readwrite) int localWebsocketID; @property (readwrite) int localWebsocketID;
@property (strong, readwrite) NSMutableDictionary *websocketIdentifiers; @property (strong, readwrite) NSMutableDictionary *websocketIdentifiers;
@property (strong, readwrite) NSMutableArray *masterBacklog;


@end @end


Expand All @@ -32,13 +33,11 @@ @interface CWServerManager ()
@implementation CWServerManager @implementation CWServerManager




- (instancetype)initWithDocumentRoot:(NSString *)documentRoot - (instancetype)init
{ {
self = [super init]; self = [super init];


self.state = CWServerManagerStateStopped; self.state = CWServerManagerStateStopped;
self.documentRoot = documentRoot;
self.localWebsocketID = -1;


return self; return self;
} }
Expand All @@ -51,7 +50,9 @@ - (void)startWebserverWithDocumentRoot:(NSString *)documentRoot onPort:(int)port
self.state = CWServerManagerStateStarting; self.state = CWServerManagerStateStarting;


self.documentRoot = documentRoot; self.documentRoot = documentRoot;
self.localWebsocketID = -1;
self.websocketIdentifiers = [NSMutableDictionary dictionary]; self.websocketIdentifiers = [NSMutableDictionary dictionary];
self.masterBacklog = [NSMutableArray array];


// //
// WEBSERVER // WEBSERVER
Expand Down Expand Up @@ -177,41 +178,63 @@ - (BLWebSocketOnMessageHandler)onUnidentifiedWebsocketMessage {
[weakSelf.websocketServer setOnMessageHandler:[weakSelf onIdentifiedWebsocketMessage] forConnection:connectionID]; [weakSelf.websocketServer setOnMessageHandler:[weakSelf onIdentifiedWebsocketMessage] forConnection:connectionID];
[weakSelf.websocketServer setOnCloseHandler:[weakSelf onIdentifiedWebsocketClosed] 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 { - (BLWebSocketOnMessageHandler)onIdentifiedWebsocketMessage {
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;


return ^void (int connectionID, NSData *messageData) { return ^void (int connectionID, NSData *messageData) {
NSDictionary *message = [CWUtil dictionaryFromJSONData:messageData]; if (self.localWebsocketID < 0) {

//Master is not ready yet, backlog the message until he is
NSNumber *value = [NSNumber numberWithInt:connectionID]; WSLog(4, @"Backlogging message from %@ to master: %@", [self identifierForConnectionID:connectionID],[[NSString alloc] initWithData:messageData encoding:NSUTF8StringEncoding]);
WSLog(4, @"Websocket message from %@ to %@: %@", [self.websocketIdentifiers allKeysForObject:value][0], [message objectForKey:@"_target"],[[NSString alloc] initWithData:messageData encoding:NSUTF8StringEncoding]); [self.masterBacklog addObject:@{ @"connectionID" : @(connectionID), @"messageData" : messageData}];

} else {
//For identified websocket messages, the server basically acts as a message relay //Everything ready, deliver message
//Check where the message is supposed to be sent to and deliver it [weakSelf _deliverMessage:messageData fromConnection:connectionID];
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;
} }

//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 { - (BLWebSocketOnCloseHandler)onIdentifiedWebsocketClosed {
__weak typeof(self) weakSelf = self; __weak typeof(self) weakSelf = self;


Expand Down

0 comments on commit c220e12

Please sign in to comment.