You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
729 lines
24 KiB
729 lines
24 KiB
//
|
|
// DDWRT_MonitorAppDelegate.m
|
|
// DDWRT-Monitor
|
|
//
|
|
// Created by Matthieu Lalonde & Spike Grobstein on 11-05-27.
|
|
// Copyleft 2011 Spurf CC BY-SH-NC. Some rights reserved.
|
|
//
|
|
|
|
#import "DDWRT_MonitorAppDelegate.h"
|
|
|
|
@implementation DDWRT_MonitorAppDelegate
|
|
|
|
# pragma mark -
|
|
# pragma mark Application Delegates:
|
|
- (void) awakeFromNib
|
|
{
|
|
// Insert code here to initialize your application
|
|
|
|
defaults = [NSUserDefaults standardUserDefaults];
|
|
|
|
// check if the app is configured yet
|
|
if (![defaults boolForKey:@"configured"] || [[defaults stringForKey:@"hostname"] length] == 0) {
|
|
[self showInitAlert];
|
|
[self initDefaults];
|
|
} else {
|
|
[self initialize];
|
|
}
|
|
|
|
[self showMenubar];
|
|
}
|
|
|
|
- (void) dealloc {
|
|
[AppMenu release];
|
|
[_appMenu release];
|
|
[ConfigPanel release];
|
|
[BandwidthViewer release];
|
|
|
|
[super dealloc];
|
|
}
|
|
|
|
- (void) terminate:(id)sender {
|
|
[self deinitialize];
|
|
|
|
[[NSUserDefaults standardUserDefaults] synchronize];
|
|
[self dealloc];
|
|
[[NSApplication sharedApplication] terminate:self];
|
|
}
|
|
|
|
- (void) initialize
|
|
{
|
|
NSLog(@"Reading defaults...");
|
|
[self readDefaults];
|
|
|
|
_statusDataRequestNumber = 0;
|
|
_statusStringData = @"";
|
|
|
|
wrt_update_client = [[WRTStatusClient alloc] initWithHostname:hostname port:port protocol:protocol username:username password:password];
|
|
wrt_request_client = [[WRTStatusClient alloc] initWithHostname:hostname port:port protocol:protocol username:username password:password];
|
|
|
|
[wrt_update_client registerStatusCallback:self callback:@selector(cbUpdateStatus)];
|
|
|
|
[wrt_update_client getConnectionStatus];
|
|
}
|
|
|
|
- (void) deinitialize
|
|
{
|
|
if (_updateTimer != nil) {
|
|
[_updateTimer invalidate];
|
|
_updateTimer = nil;
|
|
[_updateTimer release];
|
|
}
|
|
|
|
[wrt_update_client release];
|
|
wrt_update_client = nil;
|
|
|
|
[wrt_request_client release];
|
|
wrt_request_client = nil;
|
|
}
|
|
|
|
- (void) showInitAlert
|
|
{
|
|
NSAlert *alert = [[[NSAlert alloc] init] autorelease];
|
|
[alert addButtonWithTitle:@"OK"];
|
|
[alert setMessageText:@"First Launch!"];
|
|
[alert setInformativeText:@"In order to conitnue, you must first provide your router settings."];
|
|
[alert setAlertStyle:NSInformationalAlertStyle];
|
|
[alert runModal];
|
|
}
|
|
|
|
- (IBAction) showBandwidthViewer:(id)sender
|
|
{
|
|
[ [BandwidthViewerWebView mainFrame] loadRequest: [wrt_update_client requestForBandwidthViewerForInterface:[wrt_update_client getWanPort]] ];
|
|
|
|
// Failed attempt at automagically setting the bit/byte mode in the svg graph
|
|
//WebScriptObject *scriptObject = [BandwidthViewerWebView windowScriptObject];
|
|
//[scriptObject callWebScriptMethod:@"alert" withArguments:[NSArray arrayWithObject:@"Will"]];
|
|
//[scriptObject setValue:@"bits" forKey:@"unit"];
|
|
|
|
[BandwidthViewer makeKeyAndOrderFront:nil];
|
|
}
|
|
|
|
# pragma mark -
|
|
# pragma mark Menu Methods:
|
|
- (void) showMenubar
|
|
{
|
|
NSLog(@"Showing Menu Item");
|
|
|
|
NSStatusBar *bar = [NSStatusBar systemStatusBar];
|
|
_appMenu = [bar statusItemWithLength:NSVariableStatusItemLength];
|
|
[_appMenu setAction:@selector(refreshMenu:)];
|
|
[_appMenu setTarget:self];
|
|
[_appMenu retain];
|
|
|
|
[self showMenubarIcon:false];
|
|
|
|
[_appMenu setHighlightMode:YES];
|
|
//[_appMenu setMenu:AppMenu];
|
|
}
|
|
|
|
- (void) hideMenubar
|
|
{
|
|
[_appMenu release];
|
|
_appMenu = nil;
|
|
[AppMenu release];
|
|
AppMenu = nil;
|
|
}
|
|
|
|
- (void) showMenubarIcon:(BOOL)enabled
|
|
{
|
|
NSImage* icon = [NSImage imageNamed:(enabled == true ? @"MenuIcon" : @"MenuIconDisabled")];
|
|
[_appMenu setImage:icon];
|
|
[_appMenu setAlternateImage:nil];
|
|
[icon release];
|
|
}
|
|
|
|
- (void) hideMenubarIcon
|
|
{
|
|
[_appMenu setImage:nil];
|
|
[_appMenu setAlternateImage:nil];
|
|
}
|
|
|
|
- (void) setMenubarText:(NSString *)menubarText
|
|
{
|
|
// TODO set proper line height and proper right align
|
|
NSFontManager *fontManager = [NSFontManager sharedFontManager];
|
|
NSFont *menuFont = [fontManager fontWithFamily:@"Lucida Grande" traits:NSBoldFontMask weight:10 size:8 ];
|
|
|
|
NSDictionary *titleAttributes = [[NSDictionary alloc] initWithObjectsAndKeys:menuFont, NSFontAttributeName,
|
|
[NSColor blackColor], NSForegroundColorAttributeName, nil];
|
|
NSAttributedString *menuTitle = [[NSAttributedString alloc] initWithString:menubarText attributes:titleAttributes];
|
|
|
|
[_appMenu setAttributedTitle:menuTitle];
|
|
|
|
[fontManager release];
|
|
[menuFont release];
|
|
[menuTitle release];
|
|
}
|
|
|
|
|
|
- (void) disableDynamicMenus
|
|
{
|
|
[menuSystem setEnabled:false];
|
|
[menuWan setEnabled:false];
|
|
[menuClientsItem setEnabled:false];
|
|
}
|
|
|
|
- (void) enableDynamicMenus
|
|
{
|
|
[menuSystem setEnabled:true];
|
|
[menuWan setEnabled:true];
|
|
[menuClientsItem setEnabled:true];
|
|
}
|
|
|
|
# pragma mark -
|
|
# pragma mark Configs Methods:
|
|
- (void) initDefaults
|
|
{
|
|
NSLog(@"Creating new user defaults");
|
|
|
|
// do any other initialization you want to do here - e.g. the starting default values.
|
|
[defaults setValue:@"http" forKey:@"protocol"];
|
|
[defaults setValue:@"" forKey:@"hostname"];
|
|
[defaults setInteger:80 forKey:@"port"];
|
|
[defaults setValue:@"" forKey:@"username"];
|
|
[defaults setValue:@"" forKey:@"password"];
|
|
|
|
[defaults setBool:YES forKey:@"showMenuIcon"];
|
|
[defaults setBool:YES forKey:@"useBytes"];
|
|
[defaults setInteger:4 forKey:@"refreshTime"];
|
|
|
|
[defaults setBool:YES forKey:@"configured"];
|
|
|
|
[self showConfigPanel:self];
|
|
}
|
|
|
|
- (void) readDefaults
|
|
{
|
|
hostname = [defaults valueForKey:@"hostname"];
|
|
protocol = [defaults valueForKey:@"protocol"];
|
|
port = [defaults integerForKey:@"port"];
|
|
username = [defaults valueForKey:@"username"];
|
|
password = [defaults valueForKey:@"password"];
|
|
|
|
showMenuIcon = [defaults boolForKey:@"showMenuIcon"];
|
|
useBytes = [defaults boolForKey:@"useBytes"];
|
|
refreshTime = [defaults integerForKey:@"refreshTime"];
|
|
}
|
|
|
|
- (void) writeDefaults
|
|
{
|
|
// do any other initialization you want to do here - e.g. the starting default values.
|
|
[defaults setValue:hostname forKey:@"hostname"];
|
|
[defaults setValue:protocol forKey:@"protocol"];
|
|
[defaults setInteger:port forKey:@"port"];
|
|
[defaults setValue:username forKey:@"username"];
|
|
[defaults setValue:password forKey:@"password"];
|
|
|
|
[defaults setBool:showMenuIcon forKey:@"showMenuIcon"];
|
|
[defaults setBool:useBytes forKey:@"useBytes"];
|
|
[defaults setInteger:refreshTime forKey:@"refreshTime"];
|
|
|
|
// sync the defaults to disk
|
|
[defaults synchronize];
|
|
}
|
|
|
|
|
|
- (IBAction) showConfigPanel:(id)sender
|
|
{
|
|
[configFieldShowIcon setState:([defaults boolForKey:@"showMenuIcon"] ? 1 : 0)];
|
|
[configFieldUseBytes setState:([defaults boolForKey:@"useBytes"] ? 1 : 0)];
|
|
|
|
if (hostname != nil) {
|
|
[configFieldHostname setStringValue:hostname];
|
|
}
|
|
|
|
[configFieldPort setIntValue:[defaults integerForKey:@"port"]];
|
|
|
|
[configFieldRefresh setIntegerValue:[defaults integerForKey:@"refreshTime"]];
|
|
|
|
[configLabelRefresh setStringValue:[NSString stringWithFormat:@"%d s", ([defaults integerForKey:@"refreshTime"] + 1)]];
|
|
|
|
if ([protocol isEqualToString:@"http"] == true) {
|
|
[configFieldProtocolHTTP setState:1];
|
|
[configFieldProtocolHTTPS setState:0];
|
|
} else if ([protocol isEqualToString:@"https"] == true) {
|
|
[configFieldProtocolHTTP setState:0];
|
|
[configFieldProtocolHTTPS setState:1];
|
|
}
|
|
|
|
[ConfigPanel makeKeyAndOrderFront:nil];
|
|
}
|
|
|
|
- (IBAction) hideConfigPanel:(id)sender
|
|
{
|
|
if ([hostname length] == 0 && [[sender title] isEqualToString:@"Cancel"]) {
|
|
NSAlert *alert = [NSAlert alertWithMessageText:@"Application Not Configured!"
|
|
defaultButton:@"Cancel" alternateButton:@"Ok" otherButton:nil
|
|
informativeTextWithFormat:@"The application will quit now."
|
|
];
|
|
|
|
[alert setAlertStyle:NSCriticalAlertStyle];
|
|
|
|
NSInteger button = [alert runModal];
|
|
|
|
if (button != NSAlertDefaultReturn) {
|
|
[self terminate:nil];
|
|
[ConfigPanel orderOut:nil];
|
|
}
|
|
} else {
|
|
[ConfigPanel orderOut:nil];
|
|
}
|
|
}
|
|
|
|
- (IBAction) setConfigProtocol:(id)sender
|
|
{
|
|
if ([configFieldProtocolHTTP state] == 1 && [[configFieldPort stringValue] isEqualToString:@"443"] == true) {
|
|
[configFieldPort setStringValue:@"80"];
|
|
} else if ([configFieldProtocolHTTPS state] == 1 && [[configFieldPort stringValue] isEqualToString:@"80"] == true) {
|
|
[configFieldPort setStringValue:@"443"];
|
|
}
|
|
}
|
|
|
|
- (IBAction) setConfigRefresh:(id)sender
|
|
{
|
|
[configLabelRefresh setStringValue:[NSString stringWithFormat:@"%u s", ([sender integerValue] + 1)]];
|
|
}
|
|
|
|
- (IBAction) saveConfig:(id)sender
|
|
{
|
|
[self deinitialize];
|
|
|
|
[configStateStatus startAnimation:nil];
|
|
[configStateStatus setHidden:false];
|
|
|
|
hostname = [configFieldHostname stringValue];
|
|
|
|
port = [configFieldPort intValue];
|
|
|
|
if ([configFieldProtocolHTTP state] == 1) {
|
|
protocol = @"http";
|
|
} else if ([configFieldProtocolHTTPS state] == 1) {
|
|
protocol = @"https";
|
|
}
|
|
|
|
refreshTime = [configFieldRefresh integerValue];
|
|
|
|
useBytes = ([configFieldUseBytes state] == 1 ? true: false);
|
|
|
|
showMenuIcon = ([configFieldShowIcon state] == 1 ? true: false);
|
|
|
|
[configStateStatus stopAnimation:nil];
|
|
[configStateStatus setHidden:true];
|
|
|
|
[self writeDefaults];
|
|
|
|
[defaults synchronize];
|
|
|
|
[self initialize];
|
|
|
|
[self hideConfigPanel:nil];
|
|
}
|
|
|
|
# pragma mark -
|
|
# pragma mark Request Handlers:
|
|
- (void) cbUpdateStatus
|
|
{
|
|
NSLog(@"Status %@ wan port: %@", ([wrt_update_client getWrtReachable] ? @"Up" : @"Down"), [wrt_update_client getWanPort]);
|
|
if ([wrt_update_client getWrtReachable] == true) {
|
|
if (showMenuIcon == true) {
|
|
[self showMenubarIcon:true];
|
|
} else {
|
|
[self hideMenubarIcon];
|
|
}
|
|
|
|
[self enableDynamicMenus];
|
|
|
|
if (_updateTimer != nil) {
|
|
[_updateTimer invalidate];
|
|
_updateTimer = nil;
|
|
}
|
|
|
|
_updateTimer = [NSTimer scheduledTimerWithTimeInterval:refreshTime+1 target:self selector:@selector(getThroughput:) userInfo:nil repeats:YES];
|
|
[_updateTimer fire];
|
|
} else if ([wrt_update_client getWrtReachable] == false) {
|
|
[self showMenubarIcon:false];
|
|
[self setMenubarText:@""];
|
|
|
|
[self disableDynamicMenus];
|
|
|
|
if (_updateTimer != nil) {
|
|
[_updateTimer invalidate];
|
|
_updateTimer = nil;
|
|
}
|
|
|
|
_updateTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:wrt_update_client selector:@selector(getConnectionStatus:) userInfo:nil repeats:NO];
|
|
[_updateTimer fire];
|
|
}
|
|
}
|
|
|
|
- (void) getThroughput:(NSTimer *)timer
|
|
{
|
|
//NSLog(@"Status %@ wan port: %@", ([wrt_client getWrtReachable] ? @"Up" : @"Down"), [wrt_client getWanPort]);
|
|
[wrt_update_client getStatusUpdate:[NSString stringWithFormat:@"fetchif.cgi?%@", [wrt_update_client getWanPort]] delegate:self callback:@selector(cbThroughput:)];
|
|
}
|
|
|
|
- (void) cbThroughput:(NSData *)data
|
|
{
|
|
NSString *stringData = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
|
|
|
|
NSString *key = [NSString stringWithFormat:@"%@:", [wrt_update_client getWanPort]];
|
|
stringData = [stringData substringFromIndex:([stringData rangeOfString:key].location + [key length])];
|
|
|
|
NSArray *parts = [stringData componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
|
NSArray *listItems = [parts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != ''"]];
|
|
|
|
uint64_t ifIn = strtoull([[listItems objectAtIndex:0] UTF8String], NULL, 0);
|
|
uint64_t ifOut = strtoull([[listItems objectAtIndex:8] UTF8String], NULL, 0);
|
|
|
|
if (_lastInThroughput != 0) {
|
|
uint64_t diffIn = ifIn - _lastInThroughput;
|
|
uint64_t diffOut = ifOut - _lastOutThroughput;
|
|
|
|
double timeDiff = fabs([_lastDateThroughput timeIntervalSinceNow]);
|
|
_lastDateThroughput = [[NSDate date] retain];
|
|
|
|
if (timeDiff <= 0)
|
|
timeDiff = 1; // avoid division by zero
|
|
|
|
double speedIn = diffIn / timeDiff;
|
|
double speedOut = diffOut / timeDiff;
|
|
speedIn = round(2.2f * speedIn) / 2.2f;
|
|
speedOut = round(2.2f * speedOut) / 2.2f;
|
|
|
|
[ self setMenubarText:[NSString stringWithFormat:@"%@s\n%@s", [self stringFromSpeed:speedOut], [self stringFromSpeed:speedIn]] ];
|
|
|
|
//NSLog(@"In %llu Out %llu Last In %llu Last Out %llu diffIn %llu diffOut %llu In %f Out %f Interval %f", ifIn, ifOut, _lastInThroughput,
|
|
// _lastOutThroughput, diffIn, diffOut, speedIn, speedOut, timeDiff);
|
|
}
|
|
|
|
_lastInThroughput = ifIn;
|
|
_lastOutThroughput = ifOut;
|
|
}
|
|
|
|
- (void) getRouterData:(NSData *)data
|
|
{
|
|
if (data != nil) {
|
|
NSString *stringData = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
|
|
|
|
NSString *newStringData = [_statusStringData stringByAppendingString:stringData];
|
|
|
|
_statusStringData = [newStringData retain];
|
|
[stringData release];
|
|
} else {
|
|
_statusStringData = @"";
|
|
_statusDataRequestNumber = 0;
|
|
}
|
|
|
|
switch (_statusDataRequestNumber++) {
|
|
case 0:
|
|
[wrt_request_client getStatusUpdate:@"Status_Router.live.asp" delegate:self callback:@selector(getRouterData:)];
|
|
break;
|
|
case 1:
|
|
[wrt_request_client getStatusUpdate:@"Status_Internet.live.asp" delegate:self callback:@selector(getRouterData:)];
|
|
break;
|
|
case 2:
|
|
[wrt_request_client getStatusUpdate:@"Status_Lan.live.asp" delegate:self callback:@selector(getRouterData:)];
|
|
break;
|
|
case 3:
|
|
[wrt_request_client getStatusUpdate:@"Status_Wireless.live.asp" delegate:self callback:@selector(getRouterData:)];
|
|
break;
|
|
case 4:/*
|
|
// All the information here is redundant anyway... except possibly GPS data if some routers have that populated
|
|
[wrt_request_client getStatusUpdate:@"Info.live.htm" delegate:self callback:@selector(getRouterData:)];
|
|
break;
|
|
case 5:*/
|
|
default:
|
|
//NSLog(@"%@", _statusStringData);
|
|
|
|
// Populate the menu items
|
|
[self populateMenuSystem];
|
|
[self populateMenuWan];
|
|
[self populateMenuClients];
|
|
|
|
[_appMenu popUpStatusItemMenu:AppMenu];
|
|
break;
|
|
}
|
|
}
|
|
|
|
# pragma mark -
|
|
# pragma mark Menu Handlers:
|
|
- (IBAction) refreshMenu:(id)sender
|
|
{
|
|
NSLog(@"Refresh Menu");
|
|
if ([wrt_update_client getWrtReachable] == true) {
|
|
[self getRouterData:nil];
|
|
} else {
|
|
[_appMenu popUpStatusItemMenu:AppMenu];
|
|
}
|
|
}
|
|
|
|
- (void) populateMenuSystem
|
|
{
|
|
NSString *uptime = [wrt_request_client getKey:_statusStringData key:@"uptime"];
|
|
NSString *loadSplit = @", load average: ";
|
|
if ([uptime length] > 0) {
|
|
NSString *load = [uptime substringFromIndex:[uptime rangeOfString:loadSplit].location+[loadSplit length]];
|
|
uptime = [uptime substringToIndex:[uptime rangeOfString:@", load"].location]; // Cut the load
|
|
uptime = [uptime substringFromIndex:[uptime rangeOfString:@" "].location+1]; // Trim
|
|
uptime = [uptime stringByReplacingCharactersInRange:NSMakeRange(0,1) withString:[[uptime substringToIndex:1] uppercaseString]]; // UCFirst
|
|
|
|
[menuSystemUptime setTitle:uptime];
|
|
[menuSystemLoad setTitle:[NSString stringWithFormat:@"Load %@", load]];
|
|
[menuSystemLoad setHidden:false];
|
|
} else {
|
|
[menuSystemUptime setTitle:@"Connected"];
|
|
[menuSystemLoad setHidden:true];
|
|
}
|
|
|
|
NSString *memInfo = [wrt_request_client getKey:_statusStringData key:@"mem_info"];
|
|
|
|
// Remove any white spaces
|
|
NSArray *parts = [memInfo componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
|
NSArray *filteredArray = [parts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != ''"]];
|
|
memInfo = [filteredArray componentsJoinedByString:@" "];
|
|
parts = nil;
|
|
filteredArray = nil;
|
|
|
|
// Remove any quotes
|
|
parts = [memInfo componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\'"]];
|
|
filteredArray = [parts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != ''"]];
|
|
memInfo = [filteredArray componentsJoinedByString:@""];
|
|
|
|
NSArray *memData = [memInfo componentsSeparatedByString:@","];
|
|
uint32_t memTotal = strtoull([[memData objectAtIndex:8] UTF8String], NULL, 0);
|
|
uint32_t memFree = strtoull([[memData objectAtIndex:9] UTF8String], NULL, 0);
|
|
|
|
NSString *memTitle = [NSString stringWithFormat:@"Memory %@/%@", [self stringFromSize:memFree withUnits:false], [self stringFromSize:memTotal]];
|
|
[menuSystemMemory setTitle:memTitle];
|
|
}
|
|
|
|
- (void) populateMenuWan
|
|
{
|
|
NSString *wanip = [wrt_request_client getKey:_statusStringData key:@"ipinfo"];
|
|
NSRange startRange = [wanip rangeOfString:@" "];
|
|
wanip = [wanip substringFromIndex:(startRange.location+1)];
|
|
[menuWanIP setTitle:wanip];
|
|
|
|
NSString *wanStatus = [wrt_request_client getKey:_statusStringData key:@"wan_status"];
|
|
NSString *wanName = [wrt_request_client getKey:_statusStringData key:@"wan_shortproto"];
|
|
if ([wanName isEqualToString:@"pppoe"] == true) {
|
|
wanName = @"PPPoE";
|
|
} else if ([wanName isEqualToString:@"static"] == true) {
|
|
wanName = @"Static";
|
|
} else {
|
|
wanName = [wanName uppercaseString];
|
|
}
|
|
|
|
wanStatus = [wanStatus substringToIndex:[wanStatus rangeOfString:@"&"].location];
|
|
[menuWanStatus setTitle:[NSString stringWithFormat:@"%@ %@", wanName, wanStatus]];
|
|
|
|
//if ([_appMenu image] != nil) {
|
|
// [self showMenubarIcon:[wanStatus isEqualToString:@"Connected"]];
|
|
//}
|
|
|
|
NSString *wanUptime = [wrt_request_client getKey:_statusStringData key:@"wan_uptime"];
|
|
if ([wanStatus isEqualToString:@"Connected"] == true) {
|
|
[menuWanUptime setTitle:wanUptime];
|
|
[menuWanUptime setHidden:false];
|
|
[menuWanSeparator setHidden:false];
|
|
[menuWanBandwidthGraph setEnabled:true];
|
|
[menuWanTrafficIn setHidden:false];
|
|
[menuWanTrafficOut setHidden:false];
|
|
} else {
|
|
[menuWanUptime setHidden:true];
|
|
[menuWanSeparator setHidden:true];
|
|
[menuWanBandwidthGraph setEnabled:false];
|
|
[menuWanTrafficIn setHidden:true];
|
|
[menuWanTrafficOut setHidden:true];
|
|
|
|
}
|
|
|
|
NSString *trafficIn = [wrt_request_client getKey:_statusStringData key:@"ttraff_in"];
|
|
NSString *trafficOut = [wrt_request_client getKey:_statusStringData key:@"ttraff_out"];
|
|
trafficIn = [self stringFromSize:([trafficIn longLongValue] * 1024 * 1024)];
|
|
trafficOut = [self stringFromSize:([trafficOut longLongValue] * 1024 * 1024)];
|
|
|
|
[menuWanTrafficIn setTitle:[NSString stringWithFormat:@"In: %@", trafficIn]];
|
|
[menuWanTrafficOut setTitle:[NSString stringWithFormat:@"Out: %@", trafficOut]];
|
|
|
|
NSString *wanDNS0 = [wrt_request_client getKey:_statusStringData key:@"wan_dns0"];
|
|
NSString *wanDNS1 = [wrt_request_client getKey:_statusStringData key:@"wan_dns1"];
|
|
NSString *wanDNS2 = [wrt_request_client getKey:_statusStringData key:@"wan_dns2"];
|
|
|
|
if ([wanDNS0 length] > 0) {
|
|
[menuWanDNS setEnabled:true];
|
|
[menuWanDNSItem0 setTitle: wanDNS0];
|
|
[menuWanDNSItem0 setHidden:false];
|
|
}
|
|
|
|
if ([wanDNS1 length] > 0) {
|
|
[menuWanDNS setEnabled:true];
|
|
[menuWanDNSItem1 setTitle: wanDNS1];
|
|
[menuWanDNSItem1 setHidden:false];
|
|
}
|
|
|
|
if ([wanDNS2 length] > 0) {
|
|
[menuWanDNS setEnabled:true];
|
|
[menuWanDNSItem2 setTitle: wanDNS2];
|
|
[menuWanDNSItem2 setHidden:false];
|
|
}
|
|
}
|
|
|
|
- (void) populateMenuClients
|
|
{
|
|
NSString * clientsStringData;
|
|
|
|
NSString *keyData = @"{arp_table::";
|
|
|
|
clientsStringData = [ _statusStringData substringFromIndex:([_statusStringData rangeOfString:keyData].location + [keyData length]) ];
|
|
clientsStringData = [ clientsStringData substringToIndex:[clientsStringData rangeOfString:@"}"].location ];
|
|
|
|
// Remove any white spaces
|
|
NSArray *parts = [clientsStringData componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
|
|
NSArray *filteredArray = [parts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != ''"]];
|
|
clientsStringData = [filteredArray componentsJoinedByString:@" "];
|
|
parts = nil;
|
|
filteredArray = nil;
|
|
|
|
// Remove any quotes
|
|
parts = [clientsStringData componentsSeparatedByCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@"\'"]];
|
|
filteredArray = [parts filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != ''"]];
|
|
clientsStringData = [filteredArray componentsJoinedByString:@""];
|
|
|
|
NSArray *clientsData = [clientsStringData componentsSeparatedByString:@","];
|
|
|
|
NSMenu *clientMenu;
|
|
NSMenuItem *clientMenuItem;
|
|
NSMenuItem *clientItem;
|
|
|
|
NSString *ipconn = [wrt_request_client getKey:_statusStringData key:@"ip_conntrack"];
|
|
|
|
[menuClientsConnections setTitle:[NSString stringWithFormat:@"%@ Connection%@", ipconn, ([ipconn isEqualToString:@"1"] ? @"" : @"s")]];
|
|
|
|
uint16_t clientsCount = [clientsData count] / 4;
|
|
[menuClientsCount setTitle:[NSString stringWithFormat:@"%lu Active Client%@", clientsCount, (clientsCount > 1 ? @"s" : @"")]];
|
|
|
|
// Clear the old client data
|
|
uint16_t clientIndex;
|
|
uint16_t firstItem = [menuClients indexOfItem:menuClientsSeparator];
|
|
if ([menuClients numberOfItems] > firstItem) {
|
|
for (clientIndex = ([menuClients numberOfItems] - 1); clientIndex > (firstItem + 1); clientIndex--) {
|
|
[menuClients removeItemAtIndex:clientIndex];
|
|
}
|
|
}
|
|
|
|
for (clientIndex = 0; clientIndex < [clientsData count]; clientIndex+=4) {
|
|
// Allocate a new menu for the client data
|
|
clientMenu = [[NSMenu alloc] init];
|
|
|
|
// Hostname
|
|
clientMenuItem = [[NSMenuItem alloc] initWithTitle:[clientsData objectAtIndex:clientIndex] action:nil keyEquivalent:@""];
|
|
[clientMenuItem setSubmenu:[self createCopyMenuItem]];
|
|
[clientMenu addItem:clientMenuItem];
|
|
|
|
// IP
|
|
clientMenuItem = [[NSMenuItem alloc] initWithTitle:[clientsData objectAtIndex:(clientIndex+1)] action:nil keyEquivalent:@""];
|
|
[clientMenuItem setSubmenu:[self createCopyMenuItem]];
|
|
[clientMenu addItem:clientMenuItem];
|
|
|
|
// MAC
|
|
clientMenuItem = [[NSMenuItem alloc] initWithTitle:[[clientsData objectAtIndex:(clientIndex+2)] uppercaseString] action:nil keyEquivalent:@""];
|
|
[clientMenuItem setSubmenu:[self createCopyMenuItem]];
|
|
[clientMenu addItem:clientMenuItem];
|
|
|
|
// Connections
|
|
uint16_t conn = strtoull([[clientsData objectAtIndex:(clientIndex+3)] UTF8String], NULL, 0);
|
|
clientMenuItem = [[NSMenuItem alloc] initWithTitle:[NSString stringWithFormat:@"%lu Connection%@", conn, (conn > 1 ? @"s" : @"")] action:nil keyEquivalent:@""];
|
|
[clientMenu addItem:clientMenuItem];
|
|
|
|
clientItem = [[NSMenuItem alloc] initWithTitle:[clientsData objectAtIndex:clientIndex] action:nil keyEquivalent:@""];
|
|
[clientItem setSubmenu:clientMenu];
|
|
|
|
[menuClients addItem:clientItem];
|
|
}
|
|
}
|
|
|
|
- (NSMenu *) createCopyMenuItem
|
|
{
|
|
NSMenu *copyMenu = [[NSMenu alloc] init];
|
|
NSMenuItem *copyMenuItem = [[NSMenuItem alloc] initWithTitle:@"Copy" action:@selector(copyParentMenuTitle:) keyEquivalent:@""];
|
|
[copyMenuItem setEnabled:true];
|
|
[copyMenuItem setTarget:self];
|
|
[copyMenu addItem:copyMenuItem];
|
|
|
|
return [copyMenu retain];
|
|
}
|
|
# pragma mark -
|
|
# pragma mark Utilities:
|
|
|
|
- (IBAction) copyParentMenuTitle:(id)sender
|
|
{
|
|
NSPasteboard *pasteBoard = [NSPasteboard generalPasteboard];
|
|
[pasteBoard declareTypes:[NSArray arrayWithObjects:NSStringPboardType, nil] owner: nil];
|
|
[pasteBoard setString:[[sender parentItem] title] forType:NSStringPboardType];
|
|
}
|
|
- (NSString *) stringFromSize:(uint64_t)theBytes
|
|
{
|
|
return [self stringFromSize:theBytes withUnits:true];
|
|
}
|
|
|
|
- (NSString *) stringFromSize:(uint64_t)theBytes withUnits:(BOOL)withUnits
|
|
{
|
|
NSString *units = @"";
|
|
double floatSize = theBytes;
|
|
|
|
if (withUnits == true) units = @"B";
|
|
|
|
if (theBytes<1023)
|
|
return([NSString stringWithFormat:@"%llu%@", theBytes, units]);
|
|
floatSize = floatSize / 1024;
|
|
if (withUnits == true) units = @"KiB";
|
|
if (floatSize<1023)
|
|
return([NSString stringWithFormat:@"%1.1f%@", floatSize, units]);
|
|
floatSize = floatSize / 1024;
|
|
if (withUnits == true) units = @"MiB";
|
|
if (floatSize<1023)
|
|
return([NSString stringWithFormat:@"%1.2f%@", floatSize, units]);
|
|
floatSize = floatSize / 1024;
|
|
if (withUnits == true) units = @"GiB";
|
|
if (floatSize<1023)
|
|
return([NSString stringWithFormat:@"%1.2f%@", floatSize, units]);
|
|
floatSize = floatSize / 1024;
|
|
if (withUnits == true) units = @"TiB";
|
|
|
|
return([NSString stringWithFormat:@"%1.2f%@", floatSize, units]);
|
|
}
|
|
|
|
- (NSString *) stringFromSpeed:(uint64_t)theBytes
|
|
{
|
|
NSString *suffix;
|
|
|
|
if (useBytes == false) {
|
|
theBytes *= 8;
|
|
}
|
|
|
|
double floatSize = theBytes;
|
|
suffix = (useBytes ? @"B" : @"b");
|
|
|
|
if (theBytes<1023)
|
|
return([NSString stringWithFormat:@"%llu%@", theBytes, suffix]);
|
|
floatSize = floatSize / 1024;
|
|
suffix = (useBytes ? @"KiB" : @"Kb");
|
|
if (floatSize<1023)
|
|
return([NSString stringWithFormat:@"%1.1f%@", floatSize, suffix]);
|
|
floatSize = floatSize / 1024;
|
|
suffix = (useBytes ? @"MiB" : @"Mb");
|
|
if (floatSize<1023)
|
|
return([NSString stringWithFormat:@"%1.2f%@", floatSize, suffix]);
|
|
floatSize = floatSize / 1024;
|
|
suffix = (useBytes ? @"GiB" : @"Gb");
|
|
if (floatSize<1023)
|
|
return([NSString stringWithFormat:@"%1.2f%@", floatSize, suffix]);
|
|
floatSize = floatSize / 1024;
|
|
|
|
suffix = (useBytes ? @"TiB" : @"Tb");
|
|
return([NSString stringWithFormat:@"%1.2f%@", floatSize, suffix]);
|
|
}
|
|
|
|
@end |