mirror of
https://github.com/dsward2/macSVG.git
synced 2026-03-02 18:23:58 +01:00
223 lines
5.8 KiB
Objective-C
Executable File
223 lines
5.8 KiB
Objective-C
Executable File
#import "AppController.h"
|
|
#import "AsyncSocket.h"
|
|
|
|
#define WELCOME_MSG 0
|
|
#define ECHO_MSG 1
|
|
#define WARNING_MSG 2
|
|
|
|
#define READ_TIMEOUT 15.0
|
|
#define READ_TIMEOUT_EXTENSION 10.0
|
|
|
|
#define FORMAT(format, ...) [NSString stringWithFormat:(format), ##__VA_ARGS__]
|
|
|
|
@interface AppController (PrivateAPI)
|
|
- (void)logError:(NSString *)msg;
|
|
- (void)logInfo:(NSString *)msg;
|
|
- (void)logMessage:(NSString *)msg;
|
|
@end
|
|
|
|
|
|
@implementation AppController
|
|
|
|
- (id)init
|
|
{
|
|
if((self = [super init]))
|
|
{
|
|
listenSocket = [[AsyncSocket alloc] initWithDelegate:self];
|
|
connectedSockets = [[NSMutableArray alloc] initWithCapacity:1];
|
|
|
|
isRunning = NO;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)awakeFromNib
|
|
{
|
|
[logView setString:@""];
|
|
}
|
|
|
|
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
|
{
|
|
NSLog(@"Ready");
|
|
|
|
// Advanced options - enable the socket to contine operations even during modal dialogs, and menu browsing
|
|
[listenSocket setRunLoopModes:[NSArray arrayWithObject:NSRunLoopCommonModes]];
|
|
}
|
|
|
|
- (void)scrollToBottom
|
|
{
|
|
NSScrollView *scrollView = [logView enclosingScrollView];
|
|
NSPoint newScrollOrigin;
|
|
|
|
if ([[scrollView documentView] isFlipped])
|
|
newScrollOrigin = NSMakePoint(0.0F, NSMaxY([[scrollView documentView] frame]));
|
|
else
|
|
newScrollOrigin = NSMakePoint(0.0F, 0.0F);
|
|
|
|
[[scrollView documentView] scrollPoint:newScrollOrigin];
|
|
}
|
|
|
|
- (void)logError:(NSString *)msg
|
|
{
|
|
NSString *paragraph = [NSString stringWithFormat:@"%@\n", msg];
|
|
|
|
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:1];
|
|
[attributes setObject:[NSColor redColor] forKey:NSForegroundColorAttributeName];
|
|
|
|
NSAttributedString *as = [[NSAttributedString alloc] initWithString:paragraph attributes:attributes];
|
|
|
|
[[logView textStorage] appendAttributedString:as];
|
|
[self scrollToBottom];
|
|
}
|
|
|
|
- (void)logInfo:(NSString *)msg
|
|
{
|
|
NSString *paragraph = [NSString stringWithFormat:@"%@\n", msg];
|
|
|
|
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:1];
|
|
[attributes setObject:[NSColor purpleColor] forKey:NSForegroundColorAttributeName];
|
|
|
|
NSAttributedString *as = [[NSAttributedString alloc] initWithString:paragraph attributes:attributes];
|
|
|
|
[[logView textStorage] appendAttributedString:as];
|
|
[self scrollToBottom];
|
|
}
|
|
|
|
- (void)logMessage:(NSString *)msg
|
|
{
|
|
NSString *paragraph = [NSString stringWithFormat:@"%@\n", msg];
|
|
|
|
NSMutableDictionary *attributes = [NSMutableDictionary dictionaryWithCapacity:1];
|
|
[attributes setObject:[NSColor blackColor] forKey:NSForegroundColorAttributeName];
|
|
|
|
NSAttributedString *as = [[NSAttributedString alloc] initWithString:paragraph attributes:attributes];
|
|
|
|
[[logView textStorage] appendAttributedString:as];
|
|
[self scrollToBottom];
|
|
}
|
|
|
|
- (IBAction)startStop:(id)sender
|
|
{
|
|
if(!isRunning)
|
|
{
|
|
int port = [portField intValue];
|
|
|
|
if(port < 0 || port > 65535)
|
|
{
|
|
port = 0;
|
|
}
|
|
|
|
NSError *error = nil;
|
|
if(![listenSocket acceptOnPort:port error:&error])
|
|
{
|
|
[self logError:FORMAT(@"Error starting server: %@", error)];
|
|
return;
|
|
}
|
|
|
|
[self logInfo:FORMAT(@"Echo server started on port %hu", [listenSocket localPort])];
|
|
isRunning = YES;
|
|
|
|
[portField setEnabled:NO];
|
|
[startStopButton setTitle:@"Stop"];
|
|
}
|
|
else
|
|
{
|
|
// Stop accepting connections
|
|
[listenSocket disconnect];
|
|
|
|
// Stop any client connections
|
|
NSUInteger i;
|
|
for(i = 0; i < [connectedSockets count]; i++)
|
|
{
|
|
// Call disconnect on the socket,
|
|
// which will invoke the onSocketDidDisconnect: method,
|
|
// which will remove the socket from the list.
|
|
[[connectedSockets objectAtIndex:i] disconnect];
|
|
}
|
|
|
|
[self logInfo:@"Stopped Echo server"];
|
|
isRunning = false;
|
|
|
|
[portField setEnabled:YES];
|
|
[startStopButton setTitle:@"Start"];
|
|
}
|
|
}
|
|
|
|
- (void)onSocket:(AsyncSocket *)sock didAcceptNewSocket:(AsyncSocket *)newSocket
|
|
{
|
|
[connectedSockets addObject:newSocket];
|
|
}
|
|
|
|
- (void)onSocket:(AsyncSocket *)sock didConnectToHost:(NSString *)host port:(UInt16)port
|
|
{
|
|
[self logInfo:FORMAT(@"Accepted client %@:%hu", host, port)];
|
|
|
|
NSString *welcomeMsg = @"Welcome to the AsyncSocket Echo Server\r\n";
|
|
NSData *welcomeData = [welcomeMsg dataUsingEncoding:NSUTF8StringEncoding];
|
|
|
|
[sock writeData:welcomeData withTimeout:-1 tag:WELCOME_MSG];
|
|
|
|
[sock readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:0];
|
|
}
|
|
|
|
- (void)onSocket:(AsyncSocket *)sock didWriteDataWithTag:(long)tag
|
|
{
|
|
if(tag == ECHO_MSG)
|
|
{
|
|
[sock readDataToData:[AsyncSocket CRLFData] withTimeout:READ_TIMEOUT tag:0];
|
|
}
|
|
}
|
|
|
|
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag
|
|
{
|
|
NSData *strData = [data subdataWithRange:NSMakeRange(0, [data length] - 2)];
|
|
NSString *msg = [[NSString alloc] initWithData:strData encoding:NSUTF8StringEncoding];
|
|
if(msg)
|
|
{
|
|
[self logMessage:msg];
|
|
}
|
|
else
|
|
{
|
|
[self logError:@"Error converting received data into UTF-8 String"];
|
|
}
|
|
|
|
// Even if we were unable to write the incoming data to the log,
|
|
// we're still going to echo it back to the client.
|
|
[sock writeData:data withTimeout:-1 tag:ECHO_MSG];
|
|
}
|
|
|
|
/**
|
|
* This method is called if a read has timed out.
|
|
* It allows us to optionally extend the timeout.
|
|
* We use this method to issue a warning to the user prior to disconnecting them.
|
|
**/
|
|
- (NSTimeInterval)onSocket:(AsyncSocket *)sock
|
|
shouldTimeoutReadWithTag:(long)tag
|
|
elapsed:(NSTimeInterval)elapsed
|
|
bytesDone:(NSUInteger)length
|
|
{
|
|
if(elapsed <= READ_TIMEOUT)
|
|
{
|
|
NSString *warningMsg = @"Are you still there?\r\n";
|
|
NSData *warningData = [warningMsg dataUsingEncoding:NSUTF8StringEncoding];
|
|
|
|
[sock writeData:warningData withTimeout:-1 tag:WARNING_MSG];
|
|
|
|
return READ_TIMEOUT_EXTENSION;
|
|
}
|
|
|
|
return 0.0;
|
|
}
|
|
|
|
- (void)onSocket:(AsyncSocket *)sock willDisconnectWithError:(NSError *)err
|
|
{
|
|
[self logInfo:FORMAT(@"Client Disconnected: %@:%hu", [sock connectedHost], [sock connectedPort])];
|
|
}
|
|
|
|
- (void)onSocketDidDisconnect:(AsyncSocket *)sock
|
|
{
|
|
[connectedSockets removeObject:sock];
|
|
}
|
|
|
|
@end
|