/
SignpostDemoServerAppDelegate.m
187 lines (149 loc) · 6.64 KB
/
SignpostDemoServerAppDelegate.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
//
// AppDelegate.m
// SignpostDemoServer
//
// Created by Sebastian Eide on 07/05/2012.
// Copyright (c) 2012 Kle.io. All rights reserved.
//
#import "SignpostDemoServerAppDelegate.h"
#import "MetricHTTPServer.h"
#import "ServerSocketHandler.h"
#import "ClientData.h"
#import "SharedCode.h"
@implementation SignpostDemoServerAppDelegate
@synthesize window = _window;
@synthesize port = _port;
@synthesize numBytes = _numBytes;
@synthesize statusMessages = _statusMessages;
@synthesize startStopButton = _startStopButton;
@synthesize jitterLabel = _jitterLabel;
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - Setting up connection
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
socketHandler = [[ServerSocketHandler alloc] initWithLogHandlerMessage:^(NSString *msg) {
dispatch_async(dispatch_get_main_queue(), ^{
@autoreleasepool {
[self logMessage:msg];
}
});
} logHandlerError:^(NSString *errorStr) {
dispatch_async(dispatch_get_main_queue(), ^{
@autoreleasepool {
[self logError:errorStr];
}
});
} logHandlerInfo:^(NSString *infoStr) {
dispatch_async(dispatch_get_main_queue(), ^{
@autoreleasepool {
[self logInfo:infoStr];
}
});
}];
[socketHandler setJitterCallbackUpdate:^(double localJitter, double clientJitter) {
dispatch_async(dispatch_get_main_queue(), ^{
@autoreleasepool {
[self.jitterLabel setStringValue:[NSString stringWithFormat:@"seen locally: %fms, seen by clients: %fms", localJitter, clientJitter]];
}
});
}];
[self.statusMessages setString:@""];
[MetricHTTPServer startHTTPServerForDelegate:self];
}
- (IBAction) pushedStartStopButton:(id)sender
{
NSUInteger port = [self.port integerValue];
NSUInteger numKBytes = [self.numBytes integerValue];
if ([socketHandler startStopSocketForPort:port andNumKBytes:numKBytes])
{
[self.numBytes setEnabled:NO];
[self.port setEnabled:NO];
[self.startStopButton setTitle:@"Stop"];
}
else
{
[self.numBytes setEnabled:YES];
[self.port setEnabled:YES];
[self.startStopButton setTitle:@"Start"];
}
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - Misc for logging and displaying info
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (void)scrollToBottom
{
NSScrollView *scrollView = [self.statusMessages 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];
[[self.statusMessages 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];
[[self.statusMessages 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];
[[self.statusMessages textStorage] appendAttributedString:as];
[self scrollToBottom];
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#pragma mark - MetricHTTPServer delegate methods
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
- (NSData *)dataResponseForHTTPServer:(id)sender
{
NSArray *keys = [NSArray arrayWithObjects:@"timestamp", @"clients", nil];
NSDate *date = [NSDate date];
NSMutableArray *usersData = [[NSMutableArray alloc] init];
[socketHandler executeBlockWithSynchronizedUserData:^(NSMutableDictionary *userData, SharedCode *cf) {
NSEnumerator *enumerator = [userData keyEnumerator];
NSString *hostid;
while (hostid = [enumerator nextObject]) {
ClientData *cd = [userData objectForKey:hostid];
NSNumber *downstreamBw = [NSNumber numberWithFloat:cd.downstreamBandwidth];
NSNumber *upstreamBw = [NSNumber numberWithFloat:cd.upstreamBandwidth];
NSNumber *clientLatency = [NSNumber numberWithFloat:cd.clientLatency];
NSNumber *serverLatency = [NSNumber numberWithFloat:cd.serverLatency];
NSNumber *serverJitter = [cf currentJitterForHost:hostid];
if (serverJitter == nil)
serverJitter = [NSNumber numberWithInt:-1];
NSNumber *clientJitter = [NSNumber numberWithFloat:cd.clientPerceivedJitter];
NSArray *uk = [NSArray arrayWithObjects:@"id", @"downstream-bandwidth", @"upstream-bandwidth", @"latency-as-seen-by-client", @"latency-as-seen-by-server", @"jitter-as-seen-by-server", @"jitter-as-seen-by-client", nil];
NSArray *ud = [NSArray arrayWithObjects:hostid, downstreamBw, upstreamBw, clientLatency, serverLatency, serverJitter, clientJitter, nil];
NSDictionary *dataForUser = [NSDictionary dictionaryWithObjects:ud forKeys:uk];
[usersData addObject:dataForUser];
}
}];
NSArray *vals = [NSArray arrayWithObjects:[date description], usersData, nil];
NSDictionary *dataDict = [NSDictionary dictionaryWithObjects:vals forKeys:keys];
NSError *jsonError;
NSData *returnData = [NSJSONSerialization dataWithJSONObject:dataDict options:NSJSONWritingPrettyPrinted error:&jsonError];
if (jsonError)
{
NSLog(@"Error converting data to JSON: %@", [jsonError description]);
return nil;
}
return returnData;
}
@end