Projekt

Obecné

Profil

« Předchozí | Další » 

Revize f281acac

Přidáno uživatelem Jakub Šilhavý před asi 2 roky(ů)

re #9566 Added InfoFetcher.cs, modified some other files (a bit of refactoring)

Zobrazit rozdíly:

ld_client/LDClient/Program.cs
1
using System.Runtime.InteropServices;
2
using System.Security.Principal;
3 1
using LDClient.detection;
4 2
using LDClient.network;
5 3
using LDClient.utils;
......
15 13
    public static ConfigLoader Config { get; } = new();
16 14
    public static ALogger DefaultLogger { get; } = ALogger.Current;
17 15
    private static IApiClient? DefaultApiClient { get; set; }
18
    private static readonly NetworkDetection NetDetect = new(Config.ApiPort, Config.DetectionPeriod);
19
    private static readonly ProcessDetection ProcDetect = new(Config.T32ProcessName, Config.DetectionPeriod);
20 16
    
21
    // Main Method
17
    private static readonly InfoFetcher InfoFetcher = new(
18
        5,
19
        1000,
20
        "output.txt"
21
    );
22
    
22 23
    public static int Main() {
23 24
        var exists = GetProcessesByName(Path.GetFileNameWithoutExtension(GetEntryAssembly()?.Location)).Length > 1;
24 25
        if (exists) {
......
35 36
            Config.CacheFileName
36 37
        );
37 38
        
39
        IProcessDetection processProcessDetection = new ProcessProcessDetection(
40
            Config.T32ProcessName,
41
            Config.DetectionPeriod,
42
            InfoFetcher,
43
            DefaultApiClient
44
        );
45
        
38 46
        DefaultLogger.Debug("Main -> starting the ApiClient");
39 47
        var apiClientThread = new Thread(DefaultApiClient.Run) {
40 48
            IsBackground = true
41 49
        };
42 50
        apiClientThread.Start();
43 51

  
44
        var admin = IsAdministrator();
45
        DefaultLogger.Debug($"Is program executed with admin rights? {admin}");
52
        var processThread = new Thread(processProcessDetection.RunPeriodicDetection) {
53
            IsBackground = true
54
        };
55
        processThread.Start();
46 56

  
47
        var networkTread = new Thread(NetDetect.RunPeriodicDetection);
48
        networkTread.Start();
49
        
50
        if (admin) {
51
            ProcDetect.RegisterProcessListeners();
52
        } else {
53
            var processThread = new Thread(ProcDetect.RunPeriodicDetection);
54
            processThread.Start();
55
            processThread.Join();
57
        while (true) {
58
            Thread.Sleep(10 * 1000);
56 59
        }
57

  
58
        networkTread.Join();
59

  
60
        DefaultLogger.Debug("Main -> stopping the ApiClient");
61
        DefaultApiClient.Stop();
62
        apiClientThread.Join();
63
        DefaultLogger.Debug("Main -> finished");
64
        
65 60
        return 0;
66 61
    }
67

  
68
    private static bool IsAdministrator() {
69
        if (!RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) {
70
            return false;
71
        }
72
        var identity = WindowsIdentity.GetCurrent();
73
        var principal = new WindowsPrincipal(identity);
74
        return principal.IsInRole(WindowsBuiltInRole.Administrator);
75
    }
76 62
}
ld_client/LDClient/appsettings.json
14 14
    "LogVerbosityType": 2,
15 15
    "LogFlowType": 0
16 16
  },
17

  
18 17
  "Network": {
19 18
    "ApiBaseAddress": "http://127.0.0.1",
20 19
    "ApiLDEndPoint": "/lauterbach-debugger-logs/",
......
27 26
    "CacheFileName": "cache"
28 27
  },
29 28
  "DebuggerDetection": {
30
    "T32Address": "localhost",
31
    "T32Port": 20000,
32
    "T32ProcessName": "t32mtc",
29
    "T32ProcessName": "ld_mock",
33 30
    "T32InfoLocation": "C:\\app\\tools\\T32\\results\\ldResult.txt",
34 31
    "DetectionPeriod": 5000
35 32
  }
ld_client/LDClient/detection/IDetection.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6

  
7
namespace LDClient.detection {
8
    internal interface IDetection {
9

  
10
        public void DetectAsync();
11

  
12
        public void RunPeriodicDetection();
13
        public void StopPeriodicDetection();
14
    }
15
}
ld_client/LDClient/detection/IProcessDetection.cs
1
namespace LDClient.detection {
2
    
3
    internal interface IProcessDetection {
4
        
5
        public void RunPeriodicDetection();
6
    }
7
}
ld_client/LDClient/detection/InfoFetcher.cs
1
using System.Diagnostics;
2
using LDClient.utils;
3

  
4
namespace LDClient.detection {
5

  
6
    public class InfoFetcher {
7

  
8
        private const string F32RemExecutable = "/home/silhavyj/School/KIV-ASWI/aswi2022bug-thugs/ld_client/Mock/t32rem/build/t32rem_mock";
9
        private const string F32RemArguments = "localhost port=20000 VERSION.HARDWARE";
10
        private const string UndefinedSerialNumber = "number";
11

  
12
        private readonly int _maxAttempts;
13
        private readonly int _waitPeriodMs;
14
        private readonly string _infoFilePath;
15

  
16
        public string HeadSerialNumber { get; private set; } = UndefinedSerialNumber;
17
        public string BodySerialNumber { get; private set; } = UndefinedSerialNumber;
18

  
19
        public InfoFetcher(int maxAttempts, int waitPeriodMs, string infoFilePath) {
20
            _maxAttempts = maxAttempts;
21
            _waitPeriodMs = waitPeriodMs;
22
            _infoFilePath = infoFilePath;
23
        }
24

  
25
        public async Task<bool> FetchDataAsync() {
26
            Program.DefaultLogger.Info("Fetching data from the debugger.");
27
            var success = await SendRetrieveInfoCommandAsync(F32RemExecutable, F32RemArguments);
28
            if (!success) {
29
                Program.DefaultLogger.Error("Failed to fetch data from the debugger.");
30
                return false;
31
            }
32
            for (var i = 0; i < _maxAttempts; i++) {
33
                Program.DefaultLogger.Info($"{i}. attempt to parse the info file.");
34
                if (RetrieveDebuggerInfo(_infoFilePath)) {
35
                    Program.DefaultLogger.Info($"Info file has been parsed successfully.");
36
                    return true;
37
                }
38
                await Task.Delay(_waitPeriodMs);
39
            }
40
            Program.DefaultLogger.Error("Failed to parse the into file. It may have not been created.");
41
            return false;
42
        }
43

  
44
        private bool RetrieveDebuggerInfo(string filePath) {
45
            try {
46
                var fileContent = IoUtils.ReadFile(filePath);
47
                var (headSerialNumber, bodySerialNumber) = DebuggerInfoParser.Parse(fileContent);
48
                HeadSerialNumber = headSerialNumber;
49
                BodySerialNumber = bodySerialNumber;
50
                File.Delete(filePath);
51
            } catch (Exception exception) {
52
                Program.DefaultLogger.Error($"Failed to retrieve debugger info. File {filePath} may not exist or it does not have the right format. {exception.Message}");
53
                return false;
54
            }
55
            return true;
56
        }
57

  
58
        private static async Task<bool> SendRetrieveInfoCommandAsync(string executableFile, string arguments) {
59
            var t32RemProcess = new Process();
60
            t32RemProcess.StartInfo.FileName = executableFile;
61
            t32RemProcess.StartInfo.Arguments = arguments;
62
            try {
63
                t32RemProcess.Start();
64
                await t32RemProcess.WaitForExitAsync();
65
            } catch (Exception exception) {
66
                Program.DefaultLogger.Error($"Failed to run {executableFile}. {exception.Message}");
67
                return false;
68
            }
69
            return true;
70
        }
71
    }
72
}
ld_client/LDClient/detection/NetworkDetection.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6

  
7
namespace LDClient.detection {
8
    public class NetworkDetection : IDetection {
9

  
10
        private readonly uint _port;
11

  
12
        private bool _isRunning;
13
        
14
        private readonly uint _detectionPeriod;
15

  
16
        public NetworkDetection(uint port, uint detectionPeriod) {
17
            this._port = port;
18
            this._detectionPeriod = detectionPeriod;
19
        }
20

  
21
        public void DetectAsync() {
22

  
23
            var listeners = System.Net.NetworkInformation.IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners();
24

  
25
            Program.DefaultLogger.Debug($"NetworkDetection -> Checking all currently listening.");
26
            foreach (var listener in listeners) {
27
                //Program.DefaultLogger.Debug($"{listener.Address}:{listener.Port}");
28
                if (listener.Port == _port) {
29
                    Program.DefaultLogger.Info($"Found some process listening on {listener.Address}:{_port}");
30
                }
31
            }
32

  
33
        }
34

  
35

  
36
        public void RunPeriodicDetection() {
37
            Program.DefaultLogger.Info("Network periodic detector has started");
38
            _isRunning = true;
39
            while (_isRunning) {
40
                DetectAsync();
41
                Thread.Sleep((int)_detectionPeriod);
42
            }
43
        }
44

  
45
        public void StopPeriodicDetection() {
46
            _isRunning = false;
47
        }
48
    }
49
}
ld_client/LDClient/detection/ProcessDetection.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Diagnostics;
4
using System;
5
using System.Management;
6

  
7
namespace LDClient.detection {
8
    public class ProcessDetection : IDetection {
9

  
10
        private const string ProcessStartQuery = "SELECT * FROM Win32_ProcessStartTrace";
11
        private const string ProcessStopQuery = "SELECT * FROM Win32_ProcessStopTrace";
12

  
13
        private ManagementEventWatcher _stopWatch;
14

  
15
        private bool _isRunning;
16

  
17
        private readonly string _processName;
18
        private readonly uint _detectionPeriod;
19
        private bool _processActive;
20
        public ProcessDetection(string processName, uint detectionPeriod) {
21
            this._processName = processName;
22
            this._detectionPeriod = detectionPeriod;
23
        }
24

  
25

  
26
        public void DetectAsync() {
27
            var processes = Process.GetProcessesByName(_processName);
28
            Program.DefaultLogger.Info($"Found {processes.Length} processes with name: {_processName}");
29
            var processFound = false;
30
            foreach (var process in processes) {
31
                if (process.ProcessName.Equals(_processName)) {
32
                    if (!_processActive) {
33
                        Program.DefaultLogger.Info($"Process started: {_processName}");
34
                    }
35
                    _processActive = true;
36
                    processFound = true;
37
                    break;
38
                }
39
                Console.WriteLine(process);
40
            }
41

  
42
            if (!processFound) {
43
                if (_processActive) {
44
                    Program.DefaultLogger.Info($"Process stopped: {_processName}");
45
                }
46
                _processActive = false;
47
            }
48
        }
49

  
50

  
51
        public void RunPeriodicDetection() {
52

  
53
            Program.DefaultLogger.Info("Process periodic detector has started");
54
            _isRunning = true;
55
            while (_isRunning) {
56
                DetectAsync();
57
                Thread.Sleep((int)_detectionPeriod);
58
            }
59
        }
60

  
61
        public void StopPeriodicDetection() {
62
            _isRunning = false;
63
        }
64

  
65

  
66
        public void RegisterProcessListeners() {
67
            ManagementEventWatcher startWatch = new ManagementEventWatcher(
68
                new WqlEventQuery(ProcessStartQuery));
69
            startWatch.EventArrived += startWatch_EventArrived;
70
            startWatch.Start();
71

  
72
            _stopWatch = new ManagementEventWatcher(
73
                new WqlEventQuery(ProcessStopQuery));
74
            _stopWatch.EventArrived += stopWatch_EventArrived;
75
            _stopWatch.Start();
76
        }
77

  
78
        void stopWatch_EventArrived(object sender, EventArrivedEventArgs e) {
79
            var processName = e.NewEvent.Properties["ProcessName"].Value.ToString();
80
            if (processName.Equals(_processName + ".exe")) {
81
                Program.DefaultLogger.Info($"Process stopped: {processName}");
82
            }
83
        }
84

  
85
        void startWatch_EventArrived(object sender, EventArrivedEventArgs e) {
86
            var processName = e.NewEvent.Properties["ProcessName"].Value.ToString();
87
            if (processName.Equals(_processName + ".exe")) {
88
                Program.DefaultLogger.Info($"Process started: {processName}");
89
            }
90
        }
91
    }
92
}
ld_client/LDClient/detection/ProcessProcessDetection.cs
1
using System.Diagnostics;
2
using LDClient.network;
3
using LDClient.network.data;
4

  
5
namespace LDClient.detection {
6
   
7
	 public class ProcessProcessDetection : IProcessDetection {
8
        
9
        private const string DatetimeFormat = "yyyy-MM-dd hh:mm:ss";
10
        
11
        private readonly string _processName;
12
        private readonly uint _detectionPeriodMs;
13
        private bool _processIsActive;
14
        private bool _failedToRetrieveData;
15
        private Payload? _lastlyConnected;
16

  
17
        private readonly InfoFetcher _infoFetcher;
18
        private readonly IApiClient _apiClient;
19

  
20
        public ProcessProcessDetection(string processName, uint detectionPeriodMs, InfoFetcher infoFetcher, IApiClient apiClient) {
21
            _processName = processName;
22
            _detectionPeriodMs = detectionPeriodMs;
23
            _infoFetcher = infoFetcher;
24
            _apiClient = apiClient;
25
            _failedToRetrieveData = false;
26
        }
27

  
28
        private async Task<bool> RetrieveDataFromDebugger() {
29
            var success = await _infoFetcher.FetchDataAsync();
30
            if (success) {
31
                _lastlyConnected = await SendDataToServerAsync(_infoFetcher.HeadSerialNumber, _infoFetcher.BodySerialNumber, DatetimeFormat);
32
            }
33
            return success;
34
        }
35

  
36
        private async Task DebuggerDisconnected() {
37
            if (_lastlyConnected is not null) {
38
                _lastlyConnected.Status = ConnectionStatus.Disconnected;
39
                _lastlyConnected.TimeStamp = DateTime.Now.ToString(DatetimeFormat);
40
                await _apiClient.SendPayloadAsync(_lastlyConnected);
41
                _lastlyConnected = null;
42
            }
43
        }
44

  
45
        private async Task DetectProcessAsync() {
46
            var processExists = Process.GetProcessesByName(_processName).Length > 0;
47

  
48
            if (processExists && !_processIsActive) {
49
                Program.DefaultLogger.Info($"Process started: {_processName}");
50
                if (!_failedToRetrieveData) {
51
                    _failedToRetrieveData = !await RetrieveDataFromDebugger();
52
                }
53
            } else if (!processExists && _processIsActive) {
54
                Program.DefaultLogger.Info($"Process stopped: {_processName}");
55
                _failedToRetrieveData = false;
56
                await DebuggerDisconnected();
57
            }
58
            _processIsActive = processExists;
59
        }
60
        
61
        private async Task<Payload> SendDataToServerAsync(string headSerialNumber, string bodySerialNumber, string datetimeFormat) {
62
            Payload payload = new() {
63
                UserName = Environment.UserName,
64
                HostName = Environment.MachineName,
65
                TimeStamp = DateTime.Now.ToString(datetimeFormat),
66
                HeadDevice = new DebuggerInfo {
67
                    SerialNumber = headSerialNumber
68
                },
69
                BodyDevice = new DebuggerInfo {
70
                    SerialNumber = bodySerialNumber
71
                },
72
                Status = ConnectionStatus.Connected
73
            };
74
            await _apiClient.SendPayloadAsync(payload);
75
            return payload;
76
        }
77
        
78
        public async void RunPeriodicDetection() {
79
            Program.DefaultLogger.Info("Process periodic detector has started");
80
            while (true) {
81
                await DetectProcessAsync();
82
                Thread.Sleep((int)_detectionPeriodMs);
83
            }
84
            // ReSharper disable once FunctionNeverReturns
85
        }
86
    }
87
}
ld_client/LDClient/network/ApiClient.cs
7 7
using LDClient.network.data;
8 8

  
9 9
namespace LDClient.network {
10
    
10 11
    public class ApiClient : IApiClient {
11 12
        
12
        public static readonly Payload ExampleInfo = new() {
13
            UserName = "honikCz",
14
            HostName = "Bramborak",
15
            TimeStamp = DateTime.Parse("2022-03-21 18:05:00.168895"),
16
            HeadDevice = new DebuggerInfo {
17
                SerialNumber = "C12345678912"
18
            },
19
            BodyDevice = new DebuggerInfo {
20
                SerialNumber = "C98765432198"
21
            },
22
            Status = ConnectionStatus.Connected
23
        };
24

  
25
        private bool _running;
26

  
27

  
28 13
        private readonly string _uri;
29 14
        private readonly HttpClient _client;
30 15
        private readonly IPersistentQueue _cache;
......
32 17
        private readonly uint _maxEntries;
33 18
        private readonly uint _maxRetries;
34 19
        
35

  
36

  
37 20
        public ApiClient(string url, uint port, string path, uint retryPeriod, uint maxEntries, uint maxRetries,
38 21
            string cacheFilename) {
39 22
            _uri = $"{url}:{port}{path}";
......
43 26

  
44 27
            _client = new HttpClient();
45 28
            _cache = new PersistentQueue(cacheFilename);
46

  
47 29
        }
48 30

  
49 31
        public async Task SendPayloadAsync(Payload payload) {
......
55 37
                    Converters = {
56 38
                        new JsonStringEnumConverter( JsonNamingPolicy.CamelCase)
57 39
                    }
58

  
59 40
                });
60 41
                stopWatch.Stop();
61 42
                CreateRequestLog(payload, response, stopWatch.ElapsedMilliseconds);
......
80 61
                                 $"Response: {responseToLog}");
81 62
        }
82 63
        
83

  
84 64
        private async Task ResendPayloadsAsync() {
85 65
            var numberOfPayloadsToResend = Math.Min(_maxRetries, _cache.EstimatedCountOfItemsInQueue);
86 66
            var payloads = new List<Payload>();
......
106 86
                await Task.WhenAll(tasks);
107 87
            }
108 88
        }
109

  
110

  
89
        
111 90
        private void CachePayload(Payload payload) {
112 91
            Program.DefaultLogger.Info($"Storing {payload} into the cache.");
113 92
            var numberOfCachedPayloads = _cache.EstimatedCountOfItemsInQueue;
......
122 101

  
123 102
        public async void Run() {
124 103
            Program.DefaultLogger.Info("Api Client thread has started");
125
            _running = true;
126
            while (_running) {
104
            while (true) {
127 105
                await ResendPayloadsAsync();
128
                Thread.Sleep((int)_retryPeriod);
106
                Thread.Sleep((int) _retryPeriod);
129 107
            }
130
        }
131

  
132
        public void Stop() {
133
            _running = false;
108
            // ReSharper disable once FunctionNeverReturns
134 109
        }
135 110
    }
136 111
}
ld_client/LDClient/network/IApiClient.cs
1 1
using LDClient.network.data;
2 2

  
3 3
namespace LDClient.network {
4
    
4 5
    public interface IApiClient {
6
        
5 7
        public Task SendPayloadAsync(Payload payload);
6 8
        public void Run();
7
        public void Stop();
8 9
    }
9 10
}
ld_client/LDClient/network/data/Payload.cs
8 8
    public class Payload {
9 9

  
10 10
        [JsonPropertyName("username")]
11
        public string UserName { get; set; }
11
        public string? UserName { get; set; }
12 12

  
13 13
        [JsonPropertyName("hostname")]
14
        public string HostName { get; set; }
14
        public string? HostName { get; set; }
15 15

  
16 16
        [JsonPropertyName("timestamp")]
17 17
        //[Newtonsoft.Json.JsonConverter(typeof(DateFormatConverter), "yyyy-MM-dd HH:mm:ss.ffffff")]
18
        public DateTime TimeStamp { get; set; }
18
        public string? TimeStamp { get; set; }
19 19

  
20 20
        [JsonPropertyName("head_device")]
21
        public DebuggerInfo HeadDevice { get; set; }
21
        public DebuggerInfo? HeadDevice { get; set; }
22 22

  
23 23

  
24 24
        [JsonPropertyName("body_device")]
25
        public DebuggerInfo  BodyDevice { get; set; }
25
        public DebuggerInfo?  BodyDevice { get; set; }
26 26
        
27 27
        [JsonPropertyName("status")]
28 28
        //[Newtonsoft.Json.JsonConverter(typeof(StringEnumConverter))]
ld_client/LDClient/utils/ConfigLoader.cs
2 2
using Microsoft.Extensions.Configuration;
3 3

  
4 4
namespace LDClient.utils {
5
    
5 6
    internal class ConfigLoader {
7
        
6 8
        private const string LoggingSection = "Logging";
7 9
        private const string NetworkSection = "Network";
8 10
        private const string CacheSection = "Cache";
9
        private const string DDSection = "DebuggerDetection";
11
        private const string DdSection = "DebuggerDetection";
10 12

  
11 13
        #region Logger
12
        public int LogChunkSize { get; set; }
13
        public int LogChunkMaxCount { get; set; }
14
        public int LogArchiveMaxCount { get; set; }
15

  
16
        public int LogCleanupPeriod { get; set; }
17

  
18
        public LogVerbosity LogVerbosityType { get; set; } = LogVerbosity.Full;
19

  
20
        public LogFlow LogFlowType { get; set; } = LogFlow.Console;
14
        
15
        public int LogChunkSize { get; private set; }
16
        public int LogChunkMaxCount { get; private set; }
17
        public int LogArchiveMaxCount { get; private set; }
18

  
19
        public int LogCleanupPeriod { get; private set; }
20
        public LogVerbosity LogVerbosityType { get; private set; } = LogVerbosity.Full;
21
        public LogFlow LogFlowType { get; private set; } = LogFlow.Console;
22
        
21 23
        #endregion
22 24

  
23 25
        #region Api
24
        public string ApiBaseAddress { get; set; }
25
        public string ApiUsbEndPoint { get; set; }
26
        public uint ApiPort { get; set; }
26
        
27
        public string ApiBaseAddress { get; private set; }
28
        public string ApiUsbEndPoint { get; private set; }
29
        public uint ApiPort { get; private set; }
27 30

  
28 31
        #endregion
29 32

  
30 33
        #region Cache
31
        public string CacheFileName { get; set; }
32
        public uint MaxRetries { get; set; }
33
        public uint MaxEntries { get; set; }
34
        public uint RetryPeriod { get; set; }
34
        
35
        public string CacheFileName { get; private set; }
36
        public uint MaxRetries { get; private set; }
37
        public uint MaxEntries { get; private set; }
38
        public uint RetryPeriod { get; private set; }
39
        
35 40
        #endregion
36 41

  
37 42
        #region Detection
38
        public string T32Address { get; set; }
39
        public int T32Port { get; set; }
40
        public string T32ProcessName { get; set; }
41
        public uint DetectionPeriod { get; set; }
42
        public string T32InfoLocation { get; set; }
43
        public string T32ProcessName { get; private set; }
44
        public uint DetectionPeriod { get; private set; }
45
        public string T32InfoLocation { get; private set; }
43 46
        #endregion
44 47

  
45 48
        public ConfigLoader() {
......
49 52
            ReadAllSettings(configuration);
50 53
        }
51 54

  
52
        private void ReadAllSettings(IConfigurationRoot configuration) {
55
        private void ReadAllSettings(IConfiguration configuration) {
53 56

  
54 57
            try {
55 58
                var logging = configuration.GetSection(LoggingSection);
......
74 77
                CacheFileName = cache["CacheFileName"];
75 78

  
76 79

  
77
                var debugger = configuration.GetSection(DDSection);
78
                T32Address = debugger["T32Address"];
79
                T32Port = int.Parse(debugger["T32Port"]);
80
                var debugger = configuration.GetSection(DdSection);
80 81
                T32ProcessName = debugger["T32ProcessName"];
81 82
                T32InfoLocation = debugger["T32InfoLocation"];
82 83
                DetectionPeriod = uint.Parse(debugger["DetectionPeriod"]);

Také k dispozici: Unified diff