2016-11-17 13:06:17 -05:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
2016-11-17 13:37:57 -05:00
|
|
|
|
using System.Diagnostics;
|
2016-11-17 13:06:17 -05:00
|
|
|
|
using System.Linq;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
using System.Windows;
|
2016-11-18 01:23:45 -05:00
|
|
|
|
using System.Windows.Input;
|
2016-11-18 23:29:27 -05:00
|
|
|
|
using System.ServiceProcess;
|
2016-11-19 01:32:23 -05:00
|
|
|
|
using System.Net.NetworkInformation;
|
|
|
|
|
|
2016-11-30 03:18:17 -05:00
|
|
|
|
// internal usings
|
2016-11-17 13:37:57 -05:00
|
|
|
|
using WifiSitter;
|
|
|
|
|
using WifiSitter.Model;
|
2016-11-17 13:06:17 -05:00
|
|
|
|
using WifiSitterGui.Helpers;
|
2016-12-21 02:01:42 -05:00
|
|
|
|
using WifiSitterGui.ViewModel.Events;
|
2016-11-19 01:32:23 -05:00
|
|
|
|
|
2016-11-30 03:18:17 -05:00
|
|
|
|
// 3rd party usings
|
|
|
|
|
using NetMQ;
|
|
|
|
|
using NetMQ.Sockets;
|
2016-12-21 02:01:42 -05:00
|
|
|
|
using Prism.Events;
|
2016-11-17 13:06:17 -05:00
|
|
|
|
|
|
|
|
|
namespace WifiSitterGui.ViewModel
|
|
|
|
|
{
|
|
|
|
|
public class WifiSitterAgentViewModel : MvvmObservable
|
|
|
|
|
{
|
|
|
|
|
#region fields
|
|
|
|
|
|
|
|
|
|
private static MainWindowViewModel _windowVM;
|
|
|
|
|
private RelayCommand _launchWindowCommand;
|
2016-11-18 01:23:45 -05:00
|
|
|
|
private RelayCommand _takeFiveCommand; // Asks service to pause for 5 minutes
|
2016-12-21 02:01:42 -05:00
|
|
|
|
private RelayCommand _reloadWhitelistCommand; // Asks service to reload the nic whitelist
|
2016-11-17 13:06:17 -05:00
|
|
|
|
private static MainWindow _statusGui;
|
2016-11-17 13:37:57 -05:00
|
|
|
|
private static string _serviceChannel;
|
2016-11-18 01:23:45 -05:00
|
|
|
|
private System.Timers.Timer _netstateCheckTimer;
|
2016-11-30 03:18:17 -05:00
|
|
|
|
private static string _myChannel = String.Format("{0}-{1}", Process.GetCurrentProcess().Id, Process.GetCurrentProcess().ProcessName);
|
|
|
|
|
private static DealerSocket _mqClient;
|
2016-11-30 03:43:34 -05:00
|
|
|
|
private static NetMQPoller _poller;
|
2016-12-21 02:01:42 -05:00
|
|
|
|
private IEventAggregator _eventAggregator;
|
2016-11-18 01:23:45 -05:00
|
|
|
|
|
2016-11-17 13:06:17 -05:00
|
|
|
|
#endregion // fields
|
|
|
|
|
|
|
|
|
|
#region constructor
|
|
|
|
|
|
|
|
|
|
public WifiSitterAgentViewModel() {
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-19 01:34:12 -05:00
|
|
|
|
|
2016-12-21 02:01:42 -05:00
|
|
|
|
public WifiSitterAgentViewModel(IEventAggregator eventtAggregator) {
|
|
|
|
|
_eventAggregator = eventtAggregator;
|
|
|
|
|
_eventAggregator?.GetEvent<ReloadWhitelistEvent>().Subscribe(() => { RequestReloadWhitelist(); });
|
|
|
|
|
|
2016-11-17 13:06:17 -05:00
|
|
|
|
_windowVM = WindowVM;
|
2016-11-17 13:37:57 -05:00
|
|
|
|
Intitialize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private void Intitialize() {
|
2016-11-19 01:32:23 -05:00
|
|
|
|
// Get NetState
|
|
|
|
|
RequestNetworkState();
|
|
|
|
|
|
2016-11-18 01:23:45 -05:00
|
|
|
|
// Intermittent network state polling
|
|
|
|
|
_netstateCheckTimer = new System.Timers.Timer();
|
|
|
|
|
_netstateCheckTimer.AutoReset = true;
|
|
|
|
|
_netstateCheckTimer.Interval = 30 * 1000; // 30 seconds
|
|
|
|
|
_netstateCheckTimer.Elapsed += (o, e) => { RequestNetworkState(); };
|
|
|
|
|
_netstateCheckTimer.Start();
|
2016-11-17 13:37:57 -05:00
|
|
|
|
|
2016-11-19 01:32:23 -05:00
|
|
|
|
// Connection state changed event handler setup
|
|
|
|
|
NetworkChange.NetworkAvailabilityChanged += (o, e) => { RequestNetworkState(3 * 1000); };
|
|
|
|
|
NetworkChange.NetworkAddressChanged += (o, e) => { RequestNetworkState(3 * 1000); };
|
|
|
|
|
|
2016-11-18 01:23:45 -05:00
|
|
|
|
Trace.WriteLine(String.Format("WifiSitter service msg channel: {0}", ServiceChannelName));
|
2016-11-17 13:06:17 -05:00
|
|
|
|
}
|
2016-11-30 03:43:34 -05:00
|
|
|
|
|
|
|
|
|
~WifiSitterAgentViewModel() {
|
2016-12-17 18:27:58 -05:00
|
|
|
|
_poller?.StopAsync();
|
2016-11-30 03:43:34 -05:00
|
|
|
|
_poller?.Dispose();
|
|
|
|
|
}
|
2016-12-17 18:27:58 -05:00
|
|
|
|
|
2016-11-17 13:06:17 -05:00
|
|
|
|
#endregion // constructor
|
|
|
|
|
|
|
|
|
|
#region properties
|
2016-11-30 03:43:34 -05:00
|
|
|
|
|
2016-11-17 13:06:17 -05:00
|
|
|
|
public MainWindowViewModel WindowVM {
|
|
|
|
|
get { if (_windowVM == null) {
|
2016-12-21 02:01:42 -05:00
|
|
|
|
_windowVM = new MainWindowViewModel(_eventAggregator);
|
2016-11-17 13:06:17 -05:00
|
|
|
|
}
|
|
|
|
|
return _windowVM;
|
|
|
|
|
}
|
|
|
|
|
private set { _windowVM = value; OnPropertyChanged("WindowVM"); }
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-19 01:34:12 -05:00
|
|
|
|
|
2016-11-17 13:37:57 -05:00
|
|
|
|
internal string ServiceChannelName {
|
|
|
|
|
get {
|
2016-11-21 17:28:17 -05:00
|
|
|
|
var serviceProc = Process.GetProcesses().Where(x => x.ProcessName.ToLower().StartsWith("wifisitter"))
|
|
|
|
|
.Where(x => !x.ProcessName.ToLower().Contains("gui")).ToArray();
|
|
|
|
|
if (serviceProc != null &&
|
|
|
|
|
serviceProc.Length > 0) {
|
|
|
|
|
_serviceChannel = String.Format("{0}-{1}", serviceProc[0].Id, serviceProc[0].ProcessName);
|
2016-11-17 13:37:57 -05:00
|
|
|
|
}
|
2016-11-21 17:28:17 -05:00
|
|
|
|
|
2016-11-17 13:37:57 -05:00
|
|
|
|
return _serviceChannel;
|
|
|
|
|
}
|
|
|
|
|
}
|
2016-11-18 23:29:27 -05:00
|
|
|
|
|
2016-11-17 13:06:17 -05:00
|
|
|
|
#endregion // properties
|
|
|
|
|
|
|
|
|
|
#region methods
|
2016-11-18 01:23:45 -05:00
|
|
|
|
|
2016-11-19 01:32:23 -05:00
|
|
|
|
public void RequestNetworkState(int Delay) {
|
|
|
|
|
Task.Delay(Delay).ContinueWith((task) => { RequestNetworkState(); }, TaskScheduler.FromCurrentSynchronizationContext());
|
|
|
|
|
}
|
2016-11-21 19:16:01 -05:00
|
|
|
|
|
2016-12-17 18:27:58 -05:00
|
|
|
|
|
|
|
|
|
System.Timers.Timer _netstateTimer;
|
2016-11-19 01:32:23 -05:00
|
|
|
|
public void RequestNetworkState () {
|
2016-12-17 18:27:58 -05:00
|
|
|
|
|
|
|
|
|
// Setup timer to throttle requests
|
|
|
|
|
if (_netstateTimer == null) {
|
|
|
|
|
_netstateTimer = new System.Timers.Timer();
|
|
|
|
|
_netstateTimer.Interval = 3000;
|
|
|
|
|
_netstateTimer.AutoReset = false;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_netstateTimer.Enabled) {
|
|
|
|
|
Trace.WriteLine("Requested network state less than 2 seconds ago, skipping.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
_netstateTimer.Start();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-11-18 01:23:45 -05:00
|
|
|
|
if (!String.IsNullOrEmpty(ServiceChannelName)) {
|
|
|
|
|
try {
|
|
|
|
|
Trace.WriteLine("Checking for network state.");
|
2016-11-30 03:18:17 -05:00
|
|
|
|
string request = new WifiSitterIpcMessage("get_netstate", _myChannel).ToJsonString();
|
2016-12-17 18:27:58 -05:00
|
|
|
|
bool success = SendMessageToService(request);
|
|
|
|
|
if (!success) Trace.WriteLine("Failed to send request network state.");
|
2016-11-18 01:23:45 -05:00
|
|
|
|
}
|
|
|
|
|
catch (Exception e) {
|
|
|
|
|
Trace.WriteLine(e.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-12-17 18:27:58 -05:00
|
|
|
|
|
2016-12-21 02:01:42 -05:00
|
|
|
|
public void RequestReloadWhitelist() {
|
|
|
|
|
if (!String.IsNullOrEmpty(ServiceChannelName)) {
|
|
|
|
|
try {
|
|
|
|
|
Trace.WriteLine("Checking for network state.");
|
|
|
|
|
string request = new WifiSitterIpcMessage("reload_whitelist", _myChannel).ToJsonString();
|
|
|
|
|
bool success = SendMessageToService(request);
|
|
|
|
|
if (!success) Trace.WriteLine("Failed to send request reload_whitelist.");
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e) {
|
|
|
|
|
Trace.WriteLine(e.Message);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-12-17 18:27:58 -05:00
|
|
|
|
private bool SendMessageToService(string msg) {
|
|
|
|
|
|
|
|
|
|
// Initialize messaging componenets if needed.
|
|
|
|
|
int port = 37247;
|
|
|
|
|
string connString = String.Format("tcp://127.0.0.1:{0}", port);
|
|
|
|
|
|
|
|
|
|
if (_mqClient == null) {
|
|
|
|
|
_mqClient = new DealerSocket();
|
|
|
|
|
_mqClient.Options.Identity = Encoding.UTF8.GetBytes(_myChannel);
|
|
|
|
|
_mqClient.Connect(connString);
|
|
|
|
|
_mqClient.ReceiveReady += _mqClient_ReceiveReady;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_poller == null) {
|
|
|
|
|
_poller = new NetMQPoller();
|
|
|
|
|
_poller.Add(_mqClient);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!_poller.IsRunning) {
|
|
|
|
|
Trace.WriteLine("Reinitializing poller.");
|
|
|
|
|
_poller = new NetMQPoller();
|
|
|
|
|
_poller.Add(_mqClient);
|
|
|
|
|
_poller.RunAsync();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Send message
|
|
|
|
|
var reqMessage = new NetMQMessage();
|
|
|
|
|
reqMessage.Append(_mqClient.Options.Identity);
|
|
|
|
|
reqMessage.AppendEmptyFrame();
|
|
|
|
|
reqMessage.Append(msg);
|
|
|
|
|
return _mqClient.TrySendMultipartMessage(reqMessage);
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-17 13:06:17 -05:00
|
|
|
|
#endregion // methods
|
|
|
|
|
|
|
|
|
|
#region commands
|
|
|
|
|
|
2016-11-18 01:23:45 -05:00
|
|
|
|
public ICommand LaunchSettingsWindow {
|
2016-11-17 13:06:17 -05:00
|
|
|
|
get {
|
|
|
|
|
if (_launchWindowCommand == null) {
|
|
|
|
|
_launchWindowCommand = new RelayCommand(() => {
|
|
|
|
|
if (_statusGui == null) {
|
|
|
|
|
_statusGui = new MainWindow();
|
|
|
|
|
_statusGui.DataContext = WindowVM;
|
|
|
|
|
_statusGui.Closed += (s, e) => { _statusGui = null; };
|
|
|
|
|
_statusGui.Show();
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
_statusGui.WindowState = WindowState.Normal;
|
|
|
|
|
_statusGui.Activate();
|
|
|
|
|
}
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return _launchWindowCommand;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-18 01:23:45 -05:00
|
|
|
|
|
2016-12-21 02:01:42 -05:00
|
|
|
|
public ICommand SendReloadWhitelistRequest {
|
|
|
|
|
get {
|
|
|
|
|
if (_reloadWhitelistCommand == null) {
|
|
|
|
|
_reloadWhitelistCommand = new RelayCommand(() => {
|
|
|
|
|
var request = new WifiSitterIpcMessage("reload_whitelist", _myChannel).ToJsonString();
|
|
|
|
|
bool success = SendMessageToService(request);
|
|
|
|
|
if (!success) Trace.WriteLine("Failed to send reload_whitelist");
|
|
|
|
|
// TODO need response validation mechanism
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return _reloadWhitelistCommand;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
2016-11-18 01:23:45 -05:00
|
|
|
|
public ICommand SendTakeFiveRequest {
|
|
|
|
|
get {
|
|
|
|
|
if (_takeFiveCommand == null) {
|
|
|
|
|
_takeFiveCommand = new RelayCommand(() => {
|
2016-11-30 03:18:17 -05:00
|
|
|
|
var request = new WifiSitterIpcMessage("take_five", _myChannel).ToJsonString();
|
2016-12-17 18:27:58 -05:00
|
|
|
|
bool success = SendMessageToService(request);
|
2016-11-30 03:18:17 -05:00
|
|
|
|
if (!success) Trace.WriteLine("Failed to send take_five");
|
2016-11-18 01:23:45 -05:00
|
|
|
|
// TODO need response validation mechanism
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
return _takeFiveCommand;
|
|
|
|
|
}
|
2016-11-30 03:43:34 -05:00
|
|
|
|
}
|
2016-11-18 01:23:45 -05:00
|
|
|
|
|
2016-11-17 13:06:17 -05:00
|
|
|
|
#endregion // commands
|
|
|
|
|
|
|
|
|
|
#region events
|
2016-11-17 13:37:57 -05:00
|
|
|
|
|
2016-11-30 03:43:34 -05:00
|
|
|
|
private void _mqClient_ReceiveReady(object sender, NetMQSocketEventArgs e) {
|
2016-11-30 03:55:07 -05:00
|
|
|
|
|
2016-12-17 18:27:58 -05:00
|
|
|
|
Trace.WriteLine(">> Response received.");
|
2016-11-30 03:55:07 -05:00
|
|
|
|
WifiSitterIpcMessage _sr = null;
|
|
|
|
|
|
|
|
|
|
var msg = e.Socket.ReceiveMultipartMessage();
|
|
|
|
|
if (msg.FrameCount >= 2) {
|
|
|
|
|
var msgString = String.Concat(msg.Where(x => x.BufferSize > 0).Select(x => x.ConvertToString()));
|
|
|
|
|
try { _sr = Newtonsoft.Json.JsonConvert.DeserializeObject<WifiSitterIpcMessage>(msgString); }
|
|
|
|
|
catch {
|
|
|
|
|
Trace.WriteLine("Deserialize to WifiSitterIpcMessage failed.");
|
|
|
|
|
// TODO respond with failure
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (_sr != null) {
|
|
|
|
|
switch (_sr.Request) {
|
|
|
|
|
case "give_netstate":
|
2016-12-21 02:01:42 -05:00
|
|
|
|
try {
|
|
|
|
|
_netstateTimer.Stop(); _netstateTimer.Start();
|
|
|
|
|
WindowVM.NetState = Newtonsoft.Json.JsonConvert.DeserializeObject<SimpleNetworkState>(Encoding.UTF8.GetString(_sr.Payload)); }
|
2016-11-30 03:55:07 -05:00
|
|
|
|
catch { WifiSitter.WifiSitter.LogLine("Failed to deserialize netstate, payload."); }
|
|
|
|
|
break;
|
|
|
|
|
case "taking_five":
|
|
|
|
|
Trace.WriteLine(String.Format("Responded 'taking_five' : {0}", Encoding.UTF8.GetString(_sr.Payload)));
|
|
|
|
|
break;
|
|
|
|
|
case "service_status":
|
|
|
|
|
// TODO issue service status update
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
Trace.WriteLine(String.Format("Unknown request type: {0} from {1}", _sr?.Request, _sr?.Requestor));
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
Trace.WriteLine("Server response is null.");
|
2016-11-30 03:43:34 -05:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2016-11-17 13:06:17 -05:00
|
|
|
|
#endregion // events
|
|
|
|
|
}
|
|
|
|
|
}
|