Permalink
Browse files

Fixing WebServerIPhone example

  • Loading branch information...
robbiehanson committed Mar 29, 2012
1 parent ae1e2ef commit d982c56709ac1e7df929f6e9610df8d540f9bef1
Showing with 853 additions and 896 deletions.
  1. +0 −1 Xcode/WebServerIPhone/Classes/MyHTTPConnection.h
  2. +113 −35 Xcode/WebServerIPhone/Classes/MyHTTPConnection.m
  3. +2 −0 Xcode/WebServerIPhone/Classes/WebSocketLogger.h
  4. +9 −14 Xcode/WebServerIPhone/Classes/WebSocketLogger.m
  5. +79 −27 Xcode/WebServerIPhone/Vendor/CocoaAsyncSocket/GCDAsyncSocket.h
  6. +411 −507 Xcode/WebServerIPhone/Vendor/CocoaAsyncSocket/GCDAsyncSocket.m
  7. +3 −2 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/Categories/DDData.m
  8. +13 −23 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/HTTPAuthenticationRequest.m
  9. +4 −4 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/HTTPConnection.h
  10. +95 −126 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/HTTPConnection.m
  11. +1 −1 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/HTTPLogging.h
  12. +23 −12 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/HTTPMessage.m
  13. +1 −1 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/HTTPResponse.h
  14. +45 −77 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/HTTPServer.m
  15. +5 −6 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/Responses/HTTPAsyncFileResponse.m
  16. +5 −3 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/Responses/HTTPDataResponse.m
  17. +6 −6 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/Responses/HTTPDynamicFileResponse.m
  18. +4 −4 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/Responses/HTTPFileResponse.m
  19. +4 −2 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/Responses/HTTPRedirectResponse.m
  20. +2 −2 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/WebSocket.h
  21. +10 −25 Xcode/WebServerIPhone/Vendor/CocoaHTTPServer/WebSocket.m
  22. +18 −18 Xcode/WebServerIPhone/WebServerIPhone.xcodeproj/project.pbxproj
@@ -4,5 +4,4 @@
@interface MyHTTPConnection : HTTPConnection
-
@end
@@ -13,6 +13,59 @@
@implementation MyHTTPConnection
+static NSMutableSet *webSocketLoggers;
+
+/**
+ * The runtime sends initialize to each class in a program exactly one time just before the class,
+ * or any class that inherits from it, is sent its first message from within the program. (Thus the
+ * method may never be invoked if the class is not used.) The runtime sends the initialize message to
+ * classes in a thread-safe manner. Superclasses receive this message before their subclasses.
+ *
+ * This method may also be called directly (assumably by accident), hence the safety mechanism.
+**/
++ (void)initialize
+{
+ static dispatch_once_t onceToken;
+ dispatch_once(&onceToken, ^{
+
+ // We need some place to store the webSocketLogger instances.
+ // So we'll store them here, in a class variable.
+ //
+ // We'll also use a simple notification system to release them when they die.
+
+ webSocketLoggers = [[NSMutableSet alloc] init];
+
+ [[NSNotificationCenter defaultCenter] addObserver:self
+ selector:@selector(webSocketLoggerDidDie:)
+ name:WebSocketLoggerDidDieNotification
+ object:nil];
+ });
+}
+
++ (void)addWebSocketLogger:(WebSocketLogger *)webSocketLogger
+{
+ @synchronized(webSocketLoggers)
+ {
+ [webSocketLoggers addObject:webSocketLogger];
+ }
+}
+
++ (void)webSocketLoggerDidDie:(NSNotification *)notification
+{
+ @synchronized(webSocketLoggers)
+ {
+ [webSocketLoggers removeObject:[notification object]];
+ }
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark Utilities
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Returns the logFileManager, which is a part of the DDFileLogger system.
+ * The DDLogFileManager is the subsystem which manages the location and creation of log files.
+**/
- (id <DDLogFileManager>)logFileManager
{
WebServerIPhoneAppDelegate *appDelegate;
@@ -21,6 +74,38 @@ @implementation MyHTTPConnection
return appDelegate.fileLogger.logFileManager;
}
+/**
+ * Dynamic discovery of proper websocket href.
+**/
+- (NSString *)wsLocation
+{
+ NSString *port = [NSString stringWithFormat:@"%hu", [asyncSocket localPort]];
+
+ NSString *wsLocation;
+ NSString *wsHost = [request headerField:@"Host"];
+
+ if (wsHost == nil)
+ {
+ wsLocation = [NSString stringWithFormat:@"ws://localhost:%@/livelog", port];
+ }
+ else
+ {
+ wsLocation = [NSString stringWithFormat:@"ws://%@/livelog", wsHost];
+ }
+
+ return wsLocation;
+}
+
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark /logs.html
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Returns the response body for requests to "/logs/index.html".
+ *
+ * The response is generated dynamically.
+ * It returns the list of log files currently on the system, along with their creation date and file size.
+**/
- (NSData *)generateIndexData
{
NSArray *sortedLogFileInfos = [[self logFileManager] sortedLogFileInfos];
@@ -83,40 +168,37 @@ - (NSData *)generateIndexData
return [response dataUsingEncoding:NSUTF8StringEncoding];
}
-- (NSString *)filePathForURI:(NSString *)path
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+#pragma mark HTTPConnection
+////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+/**
+ * Overrides method in HTTPConnection.
+ *
+ * This method is invoked to retrieve the filePath for a given URI.
+ * We override it to provide proper mapping for log file paths.
+**/
+- (NSString *)filePathForURI:(NSString *)path allowDirectory:(BOOL)allowDirectory
{
if ([path hasPrefix:@"/logs/"])
{
NSString *logsDir = [[self logFileManager] logsDirectory];
return [logsDir stringByAppendingPathComponent:[path lastPathComponent]];
}
- return [super filePathForURI:path];
-}
-
-- (NSString *)wsLocation
-{
- NSString *port = [NSString stringWithFormat:@"%hu", [asyncSocket localPort]];
-
- NSString *wsLocation;
- NSString *wsHost = [request headerField:@"Host"];
-
- if (wsHost == nil)
- {
- wsLocation = [NSString stringWithFormat:@"ws://localhost:%@/livelog", port];
- }
- else
- {
- wsLocation = [NSString stringWithFormat:@"ws://%@/livelog", wsHost];
- }
-
- return wsLocation;
+ // Fall through
+ return [super filePathForURI:path allowDirectory:allowDirectory];
}
+/**
+ * Overrides method in HTTPConnection.
+**/
- (NSObject<HTTPResponse> *)httpResponseForMethod:(NSString *)method URI:(NSString *)path
{
if ([path isEqualToString:@"/logs.html"])
{
+ // Dynamically generate html response with list of available log files
+
NSData *indexData = [self generateIndexData];
return [[HTTPDataResponse alloc] initWithData:indexData];
}
@@ -139,30 +221,26 @@ - (NSString *)wsLocation
separator:@"%%"
replacementDictionary:replacementDict];
}
- else
- {
- return [super httpResponseForMethod:method URI:path];
- }
+
+ // Fall through
+ return [super httpResponseForMethod:method URI:path];
}
+/**
+ * Overrides method in HTTPConnection.
+**/
- (WebSocket *)webSocketForURI:(NSString *)path
{
if ([path isEqualToString:@"/livelog"])
{
// Create the WebSocket
- WebSocket *ws = [[WebSocket alloc] initWithRequest:request socket:asyncSocket];
+ WebSocket *webSocket = [[WebSocket alloc] initWithRequest:request socket:asyncSocket];
// Create the WebSocketLogger
- WebSocketLogger *wsLogger = [[WebSocketLogger alloc] initWithWebSocket:ws];
-
- // Todo - Broken under ARC. Needs a fix. Commens below from pre-arc.
- //
- // Memory management:
- // The WebSocket will be retained by the HTTPServer and the WebSocketLogger.
- // The WebSocketLogger will be retained by the logging framework,
- // as it adds itself to the list of active loggers from within its init method.
+ WebSocketLogger *webSocketLogger = [[WebSocketLogger alloc] initWithWebSocket:webSocket];
- return ws;
+ [[self class] addWebSocketLogger:webSocketLogger];
+ return webSocket;
}
return [super webSocketForURI:path];
@@ -3,6 +3,8 @@
#import "WebSocket.h"
+#define WebSocketLoggerDidDieNotification @"WebSocketLoggerDidDie"
+
@interface WebSocketLogger : DDAbstractLogger <DDLogger>
{
WebSocket *websocket;
@@ -12,21 +12,13 @@ - (id)initWithWebSocket:(WebSocket *)ws
websocket.delegate = self;
formatter = [[WebSocketFormatter alloc] init];
-
- // Add our logger
- //
- // We do this here (as opposed to in webSocketDidOpen:) so the logging framework will retain us.
- // This is important as nothing else is retaining us.
- // It may be a bit hackish, but it's also the simplest solution.
- [DDLog addLogger:self];
}
return self;
}
- (void)dealloc
{
[websocket setDelegate:nil];
-
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -38,6 +30,9 @@ - (void)webSocketDidOpen:(WebSocket *)ws
// This method is invoked on the websocketQueue
isWebSocketOpen = YES;
+
+ // Add our logger
+ [DDLog addLogger:self];
}
- (void)webSocketDidClose:(WebSocket *)ws
@@ -48,6 +43,9 @@ - (void)webSocketDidClose:(WebSocket *)ws
// Remove our logger
[DDLog removeLogger:self];
+
+ // Post notification
+ [[NSNotificationCenter defaultCenter] postNotificationName:WebSocketLoggerDidDieNotification object:self];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -73,17 +71,14 @@ - (void)logMessage:(DDLogMessage *)logMessage
if (logMsg)
{
- dispatch_async(websocket.websocketQueue, ^{
+ dispatch_async(websocket.websocketQueue, ^{ @autoreleasepool {
if (isWebSocketOpen)
{
- @autoreleasepool {
-
- [websocket sendMessage:logMsg];
+ [websocket sendMessage:logMsg];
- }
}
- });
+ }});
}
}
Oops, something went wrong.

0 comments on commit d982c56

Please sign in to comment.