Projekt

Obecné

Profil

« Předchozí | Další » 

Revize e6a01bd8

Přidáno uživatelem Pultak před více než 2 roky(ů)

re #9712 Added documentation of the newly implemented methods + refactoring

Zobrazit rozdíly:

ld_client/LDClient/detection/AInfoFetcher.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
6
using LDClient.utils;
1
using LDClient.utils;
7 2

  
8 3
namespace LDClient.detection; 
9 4

  
ld_client/LDClient/detection/DebuggerInfoParser.cs
1 1
using System.Text.RegularExpressions;
2 2

  
3
namespace LDClient.detection {
3
namespace LDClient.detection; 
4

  
5
/// <summary>
6
/// This class parses the .txt file generated from the debugger.
7
/// Its primary interest is to find two serial numbers (head + body). 
8
/// </summary>
9
public static class DebuggerInfoParser {
4 10

  
5 11
    /// <summary>
6
    /// This class parses the .txt file generated from the debugger.
7
    /// Its primary interest is to find two serial numbers (head + body). 
12
    /// Number of serial numbers expected to be in the .txt file (number of matches - regex).
8 13
    /// </summary>
9
    public static class DebuggerInfoParser {
10

  
11
        /// <summary>
12
        /// Number of serial numbers expected to be in the .txt file (number of matches - regex).
13
        /// </summary>
14
        private const int ExpectedNumberOfMatches = 2;
14
    private const int ExpectedNumberOfMatches = 2;
15 15
        
16
        /// <summary>
17
        /// Regular expression used to find the serial numbers.
18
        /// </summary>
19
        private static readonly Regex SerialNumberRegex = new("(?<=Serial Number: )(.*)");
16
    /// <summary>
17
    /// Regular expression used to find the serial numbers.
18
    /// </summary>
19
    private static readonly Regex SerialNumberRegex = new("(?<=Serial Number: )(.*)");
20 20
        
21
        /// <summary>
22
        /// Takes the content of a .txt file and tries to find the two serial numbers (head and body).
23
        /// If it succeed, it will return the two numbers.
24
        /// </summary>
25
        /// <param name="dataTxt">the content of a .txt file (generated from the debugger)</param>
26
        /// <returns>two serial numbers (head and body) of the debugger</returns>
27
        /// <exception cref="ArgumentException">throws an exception if it fails to find the serial numbers</exception>
28
        public static (string headSerialNumber, string bodySerialNumber) Parse(string dataTxt) {
29
            // Find all matches in the content of the file that satisfy the regular expression.
30
            var matches = SerialNumberRegex.Matches(dataTxt);
21
    /// <summary>
22
    /// Takes the content of a .txt file and tries to find the two serial numbers (head and body).
23
    /// If it succeed, it will return the two numbers.
24
    /// </summary>
25
    /// <param name="dataTxt">the content of a .txt file (generated from the debugger)</param>
26
    /// <returns>two serial numbers (head and body) of the debugger</returns>
27
    /// <exception cref="ArgumentException">throws an exception if it fails to find the serial numbers</exception>
28
    public static (string headSerialNumber, string bodySerialNumber) Parse(string dataTxt) {
29
        // Find all matches in the content of the file that satisfy the regular expression.
30
        var matches = SerialNumberRegex.Matches(dataTxt);
31 31

  
32
            // Make sure an exact number of matches has been found.
33
            if (matches.Count != ExpectedNumberOfMatches) {
34
                throw new ArgumentException($"Expected {ExpectedNumberOfMatches} matches to be found in the text (actually found: {matches.Count})");
35
            }
36
            
37
            // Return the two serial numbers (head and body).
38
            return (matches[1].ToString().Trim(), matches[0].ToString().Trim());
32
        // Make sure an exact number of matches has been found.
33
        if (matches.Count != ExpectedNumberOfMatches) {
34
            throw new ArgumentException($"Expected {ExpectedNumberOfMatches} matches to be found in the text (actually found: {matches.Count})");
39 35
        }
36
            
37
        // Return the two serial numbers (head and body).
38
        return (matches[1].ToString().Trim(), matches[0].ToString().Trim());
40 39
    }
41 40
}
ld_client/LDClient/detection/IInfoFetcher.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
1
namespace LDClient.detection; 
2

  
3
/// <summary>
4
/// This interface defines the functionality of an info fetcher which
5
/// takes care of sending commands to the debugger. 
6
/// </summary>
7
public interface IInfoFetcher {
6 8

  
7
namespace LDClient.detection {
8
    
9 9
    /// <summary>
10
    /// This interface defines the functionality of an info fetcher which
11
    /// takes care of sending commands to the debugger. 
10
    /// Returns the head serial number of the debugger.
12 11
    /// </summary>
13
    public interface IInfoFetcher {
14

  
15
        /// <summary>
16
        /// Returns the head serial number of the debugger.
17
        /// </summary>
18
        public string HeadSerialNumber { get; set; }
12
    public string HeadSerialNumber { get; set; }
19 13
        
20
        /// <summary>
21
        /// Returns the body serial number of the debugger.
22
        /// </summary>
23
        public string BodySerialNumber { get; set; }
14
    /// <summary>
15
    /// Returns the body serial number of the debugger.
16
    /// </summary>
17
    public string BodySerialNumber { get; set; }
24 18

  
25
        /// <summary>
26
        /// Fetches data from the debugger. It sends the commands defined
27
        /// in the appsettings.json file to the debugger and tries to
28
        /// parse the .txt (contains the serial numbers).
29
        /// </summary>
30
        /// <returns>True, if data was fetched successfully. False otherwise.</returns>
31
        public Task<bool> FetchDataAsync();
32
    }
33
}
19
    /// <summary>
20
    /// Fetches data from the debugger. It sends the commands defined
21
    /// in the appsettings.json file to the debugger and tries to
22
    /// parse the .txt (contains the serial numbers).
23
    /// </summary>
24
    /// <returns>True, if data was fetched successfully. False otherwise.</returns>
25
    public Task<bool> FetchDataAsync();
26
}
ld_client/LDClient/detection/IProcessDetection.cs
1
namespace LDClient.detection {
2
    
1
namespace LDClient.detection; 
2

  
3
/// <summary>
4
/// This interface defines the functionality of a process detector.
5
/// A process detector is used to determine whether a user is currently
6
/// using a debugger or not.
7
/// </summary>
8
internal interface IProcessDetection {
9
        
3 10
    /// <summary>
4
    /// This interface defines the functionality of a process detector.
5
    /// A process detector is used to determine whether a user is currently
6
    /// using a debugger or not.
11
    /// Periodically runs process detection. This method is instantiated
12
    /// as a thread from the main class (Program.cs).
7 13
    /// </summary>
8
    internal interface IProcessDetection {
9
        
10
        /// <summary>
11
        /// Periodically runs process detection. This method is instantiated
12
        /// as a thread from the main class (Program.cs).
13
        /// </summary>
14
        public void RunPeriodicDetection();
15
    }
14
    public void RunPeriodicDetection();
16 15
}
ld_client/LDClient/detection/IProcessUtils.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
1
namespace LDClient.detection; 
6 2

  
7
namespace LDClient.detection {
8
    
3
/// <summary>
4
/// This interface defines the functionality of all methods that
5
/// are used to work with processes (within this project).
6
/// </summary>
7
public interface IProcessUtils {
8
        
9 9
    /// <summary>
10
    /// This interface defines the functionality of all methods that
11
    /// are used to work with processes (within this project).
10
    /// Checks if a process is running or not.
12 11
    /// </summary>
13
    public interface IProcessUtils {
14
        
15
        /// <summary>
16
        /// Checks if a process is running or not.
17
        /// </summary>
18
        /// <param name="name">Name of the process</param>
19
        /// <returns>True, if the process is running. False otherwise.</returns>
20
        public bool IsProcessRunning(string name);
12
    /// <param name="name">Name of the process</param>
13
    /// <returns>True, if the process is running. False otherwise.</returns>
14
    public bool IsProcessRunning(string name);
21 15

  
22
        /// <summary>
23
        /// Executes a new process (t32rem.exe) with arguments which are passed in
24
        /// as a parameter of the method.
25
        /// </summary>
26
        /// <param name="fileName">Path to the .exe file</param>
27
        /// <param name="argument">Arguments passed into the .exe file</param>
28
        /// <param name="timeout">Timeout used when waiting for the process to terminate</param>
29
        /// <param name="desiredExitCode">Status code indicating a successful termination of the process.</param>
30
        /// <returns>True, if the command was executed successfully. False otherwise.</returns>
31
        public bool ExecuteNewProcess(string fileName, string argument, int timeout, int desiredExitCode);
32
    }
33
}
16
    /// <summary>
17
    /// Executes a new process (t32rem.exe) with arguments which are passed in
18
    /// as a parameter of the method.
19
    /// </summary>
20
    /// <param name="fileName">Path to the .exe file</param>
21
    /// <param name="argument">Arguments passed into the .exe file</param>
22
    /// <param name="timeout">Timeout used when waiting for the process to terminate</param>
23
    /// <param name="desiredExitCode">Status code indicating a successful termination of the process.</param>
24
    /// <returns>True, if the command was executed successfully. False otherwise.</returns>
25
    public bool ExecuteNewProcess(string fileName, string argument, int timeout, int desiredExitCode);
26
}
ld_client/LDClient/detection/IT32Utils.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Text;
5
using System.Threading.Tasks;
1
namespace LDClient.detection;
6 2

  
7
namespace LDClient.detection {
8
    public interface IT32Utils {
9 3

  
10
        public bool InitConnection();
11
        public bool ExecuteCommands();
12
        public bool CloseConnection();
4
/// <summary>
5
/// This interface defines the main functionality of an trace32 API
6
/// which is mainly used to send commands to the debugger. 
7
/// </summary>
8
public interface IT32Utils {
9
    
10
    /// <summary>
11
    /// This method initialized the connection with the trace32 application API.
12
    /// It setups the standard connection configuration a tries to connect to the API
13
    /// </summary>
14
    /// <returns>true on success</returns>
15
    public bool InitConnection();
13 16

  
14
    }
15
}
17
    /// <summary>
18
    /// Method executes all passed commands though the trace32 API
19
    /// </summary>
20
    /// <returns>true on success</returns>
21
    public bool ExecuteCommands();
22

  
23
    /// <summary>
24
    /// This method closes the connection with the trace32 application api
25
    /// </summary>
26
    /// <returns>true on success</returns>
27
    public bool CloseConnection();
28

  
29
}
ld_client/LDClient/detection/ProcessDetection.cs
1
using System.Diagnostics;
2
using LDClient.network;
1
using LDClient.network;
3 2
using LDClient.network.data;
4 3

  
5
namespace LDClient.detection {
4
namespace LDClient.detection; 
5

  
6
/// <summary>
7
/// This class takes care of process detection. When t32mtc (process)
8
/// is detected, it means that the debugger is currently being used.
9
/// The class keeps track of the current state of a debugger.
10
/// </summary>
11
public sealed class ProcessDetection : IProcessDetection {
6 12

  
7 13
    /// <summary>
8
    /// This class takes care of process detection. When t32mtc (process)
9
    /// is detected, it means that the debugger is currently being used.
10
    /// The class keeps track of the current state of a debugger.
14
    /// Datetime format used when sending payloads to the server.
11 15
    /// </summary>
12
    public sealed class ProcessDetection : IProcessDetection {
13

  
14
        /// <summary>
15
        /// Datetime format used when sending payloads to the server.
16
        /// </summary>
17
        private const string DatetimeFormat = "yyyy-MM-dd hh:mm:ss";
16
    private const string DatetimeFormat = "yyyy-MM-dd hh:mm:ss";
18 17

  
19
        /// <summary>
20
        /// Name of the process the application detects.
21
        /// </summary>
22
        private readonly string _processName;
18
    /// <summary>
19
    /// Name of the process the application detects.
20
    /// </summary>
21
    private readonly string _processName;
23 22
        
24
        /// <summary>
25
        /// How often the application check the current status of the process (cunning / not running).
26
        /// </summary>
27
        private readonly uint _detectionPeriodMs;
23
    /// <summary>
24
    /// How often the application check the current status of the process (cunning / not running).
25
    /// </summary>
26
    private readonly uint _detectionPeriodMs;
28 27
        
29
        /// <summary>
30
        /// Instance of InfoFetcher used to fetch information from the debugger
31
        /// (when the process is detected).
32
        /// </summary>
33
        private readonly IInfoFetcher _infoFetcher;
28
    /// <summary>
29
    /// Instance of InfoFetcher used to fetch information from the debugger
30
    /// (when the process is detected).
31
    /// </summary>
32
    private readonly IInfoFetcher _infoFetcher;
34 33
        
35
        /// <summary>
36
        /// Instance of API clients used for sending data off to the server.
37
        /// </summary>
38
        private readonly IApiClient _apiClient;
34
    /// <summary>
35
    /// Instance of API clients used for sending data off to the server.
36
    /// </summary>
37
    private readonly IApiClient _apiClient;
39 38
        
40
        /// <summary>
41
        /// Instance of ProcessUtils which encapsulates common functionality
42
        /// when it comes to dealing with processes (limited by the needs of this application).
43
        /// </summary>
44
        private readonly IProcessUtils _processUtils;
39
    /// <summary>
40
    /// Instance of ProcessUtils which encapsulates common functionality
41
    /// when it comes to dealing with processes (limited by the needs of this application).
42
    /// </summary>
43
    private readonly IProcessUtils _processUtils;
45 44

  
46
        /// <summary>
47
        /// Flag indicating whether the process is currently running or not.
48
        /// </summary>
49
        private bool _processIsActive;
45
    /// <summary>
46
    /// Flag indicating whether the process is currently running or not.
47
    /// </summary>
48
    private bool _processIsActive;
50 49
        
51
        /// <summary>
52
        /// Flag if the application failed to retrieve data when the process was detected.
53
        /// </summary>
54
        private bool _failedToRetrieveData;
50
    /// <summary>
51
    /// Flag if the application failed to retrieve data when the process was detected.
52
    /// </summary>
53
    private bool _failedToRetrieveData;
55 54
        
56
        /// <summary>
57
        /// Last payload that was sent to the server.
58
        /// </summary>
59
        private Payload? _lastConnectedPayload;
55
    /// <summary>
56
    /// Last payload that was sent to the server.
57
    /// </summary>
58
    private Payload? _lastConnectedPayload;
60 59

  
61
        /// <summary>
62
        /// Flag used to stop the thread (process detection).
63
        /// </summary>
64
        public bool DetectionRunning = false;
60
    /// <summary>
61
    /// Flag used to stop the thread (process detection).
62
    /// </summary>
63
    public bool DetectionRunning = false;
65 64
        
66
        /// <summary>
67
        /// Creates an instance of this class.
68
        /// </summary>
69
        /// <param name="processName">Name of the process the application detects</param>
70
        /// <param name="detectionPeriodMs">How often the application check the current status of the process (cunning / not running)</param>
71
        /// <param name="infoFetcher">Instance of InfoFetcher used to fetch information from the debugger</param>
72
        /// <param name="apiClient">Instance of API clients used for sending data off to the server</param>
73
        /// <param name="processUtils">Instance of ProcessUtils which encapsulates common functionality when it comes to dealing with processes (limited by the needs of this application)</param>
74
        public ProcessDetection(string processName, uint detectionPeriodMs, IInfoFetcher infoFetcher,
75
            IApiClient apiClient, IProcessUtils processUtils) {
76
            _processName = processName;
77
            _detectionPeriodMs = detectionPeriodMs;
78
            _infoFetcher = infoFetcher;
79
            _apiClient = apiClient;
80
            _failedToRetrieveData = false;
81
            _processUtils = processUtils;
82
        }
65
    /// <summary>
66
    /// Creates an instance of this class.
67
    /// </summary>
68
    /// <param name="processName">Name of the process the application detects</param>
69
    /// <param name="detectionPeriodMs">How often the application check the current status of the process (cunning / not running)</param>
70
    /// <param name="infoFetcher">Instance of InfoFetcher used to fetch information from the debugger</param>
71
    /// <param name="apiClient">Instance of API clients used for sending data off to the server</param>
72
    /// <param name="processUtils">Instance of ProcessUtils which encapsulates common functionality when it comes to dealing with processes (limited by the needs of this application)</param>
73
    public ProcessDetection(string processName, uint detectionPeriodMs, IInfoFetcher infoFetcher,
74
        IApiClient apiClient, IProcessUtils processUtils) {
75
        _processName = processName;
76
        _detectionPeriodMs = detectionPeriodMs;
77
        _infoFetcher = infoFetcher;
78
        _apiClient = apiClient;
79
        _failedToRetrieveData = false;
80
        _processUtils = processUtils;
81
    }
83 82

  
84
        /// <summary>
85
        /// Retrieves data from the debugger.
86
        /// </summary>
87
        /// <returns>True, if the data was fetched successfully. False, otherwise.</returns>
88
        private async Task<bool> RetrieveDataFromDebugger() {
89
            // Try to fetch data from the debugger.
90
            var success = await _infoFetcher.FetchDataAsync();
83
    /// <summary>
84
    /// Retrieves data from the debugger.
85
    /// </summary>
86
    /// <returns>True, if the data was fetched successfully. False, otherwise.</returns>
87
    private async Task<bool> RetrieveDataFromDebugger() {
88
        // Try to fetch data from the debugger.
89
        var success = await _infoFetcher.FetchDataAsync();
91 90
            
92
            // If the data was fetched successfully, send a payload off to the server.
93
            if (success) {
94
                _lastConnectedPayload = await SendDataToServerAsync(_infoFetcher.HeadSerialNumber,
95
                    _infoFetcher.BodySerialNumber, DatetimeFormat);
96
            }
97
            return success;
91
        // If the data was fetched successfully, send a payload off to the server.
92
        if (success) {
93
            _lastConnectedPayload = await SendDataToServerAsync(_infoFetcher.HeadSerialNumber,
94
                _infoFetcher.BodySerialNumber, DatetimeFormat);
98 95
        }
96
        return success;
97
    }
99 98

  
100
        /// <summary>
101
        /// Sends a payload to the server when a debugger gets disconnected.
102
        /// </summary>
103
        private async Task DebuggerDisconnected() {
104
            // Make sure the debugger was connected in the first place.
105
            if (_lastConnectedPayload is not null) {
106
                // Update the status and timestamp of the last payload
107
                // (the serial numbers remain the same).
108
                _lastConnectedPayload.Status = ConnectionStatus.Disconnected;
109
                _lastConnectedPayload.TimeStamp = DateTime.Now.ToString(DatetimeFormat);
99
    /// <summary>
100
    /// Sends a payload to the server when a debugger gets disconnected.
101
    /// </summary>
102
    private async Task DebuggerDisconnected() {
103
        // Make sure the debugger was connected in the first place.
104
        if (_lastConnectedPayload is not null) {
105
            // Update the status and timestamp of the last payload
106
            // (the serial numbers remain the same).
107
            _lastConnectedPayload.Status = ConnectionStatus.Disconnected;
108
            _lastConnectedPayload.TimeStamp = DateTime.Now.ToString(DatetimeFormat);
110 109
                
111
                // Send the data to the server.
112
                await _apiClient.SendPayloadAsync(_lastConnectedPayload);
110
            // Send the data to the server.
111
            await _apiClient.SendPayloadAsync(_lastConnectedPayload);
113 112
                
114
                // Clear the last payload.
115
                _lastConnectedPayload = null;
116
            }
113
            // Clear the last payload.
114
            _lastConnectedPayload = null;
117 115
        }
116
    }
118 117

  
119
        /// <summary>
120
        /// Checks if the t32mtc process is running or not. 
121
        /// </summary>
122
        private async Task DetectProcessAsync() {
123
            // Check if the process is running.
124
            var processExists = _processUtils.IsProcessRunning(_processName);
118
    /// <summary>
119
    /// Checks if the t32mtc process is running or not. 
120
    /// </summary>
121
    private async Task DetectProcessAsync() {
122
        // Check if the process is running.
123
        var processExists = _processUtils.IsProcessRunning(_processName);
125 124

  
126
            // Check if the process was not running but now it is (flip flop ON). 
127
            if (processExists && !_processIsActive) {
128
                Program.DefaultLogger.Info($"Process started: {_processName}");
129
                if (!_failedToRetrieveData) {
130
                    _failedToRetrieveData = !await RetrieveDataFromDebugger();
131
                }
132
            }
133
            // Check if the process was running but now it is not (fli flop OFF).
134
            else if (!processExists && _processIsActive) {
135
                Program.DefaultLogger.Info($"Process stopped: {_processName}");
136
                _failedToRetrieveData = false;
137
                await DebuggerDisconnected();
125
        // Check if the process was not running but now it is (flip flop ON). 
126
        if (processExists && !_processIsActive) {
127
            Program.DefaultLogger.Info($"Process started: {_processName}");
128
            if (!_failedToRetrieveData) {
129
                _failedToRetrieveData = !await RetrieveDataFromDebugger();
138 130
            }
139

  
140
            // Keep track of the current state of the debugger.
141
            _processIsActive = processExists;
131
        }
132
        // Check if the process was running but now it is not (fli flop OFF).
133
        else if (!processExists && _processIsActive) {
134
            Program.DefaultLogger.Info($"Process stopped: {_processName}");
135
            _failedToRetrieveData = false;
136
            await DebuggerDisconnected();
142 137
        }
143 138

  
144
        /// <summary>
145
        /// Creates a payload and sends it to the server.
146
        /// </summary>
147
        /// <param name="headSerialNumber">serial number of the head of the debugger</param>
148
        /// <param name="bodySerialNumber">serial number of the body of the debugger</param>
149
        /// <param name="datetimeFormat">datetime format (timestamp)</param>
150
        /// <returns>the newly-created payload</returns>
151
        private async Task<Payload> SendDataToServerAsync(string headSerialNumber, string bodySerialNumber, string datetimeFormat) {
152
            // Create a new payload. 
153
            Payload payload = new() {
154
                UserName = Environment.UserName,
155
                HostName = Environment.MachineName,
156
                TimeStamp = DateTime.Now.ToString(datetimeFormat),
157
                HeadDevice = new DebuggerInfo {
158
                    SerialNumber = headSerialNumber
159
                },
160
                BodyDevice = new DebuggerInfo {
161
                    SerialNumber = bodySerialNumber
162
                },
163
                Status = ConnectionStatus.Connected
164
            };
139
        // Keep track of the current state of the debugger.
140
        _processIsActive = processExists;
141
    }
142

  
143
    /// <summary>
144
    /// Creates a payload and sends it to the server.
145
    /// </summary>
146
    /// <param name="headSerialNumber">serial number of the head of the debugger</param>
147
    /// <param name="bodySerialNumber">serial number of the body of the debugger</param>
148
    /// <param name="datetimeFormat">datetime format (timestamp)</param>
149
    /// <returns>the newly-created payload</returns>
150
    private async Task<Payload> SendDataToServerAsync(string headSerialNumber, string bodySerialNumber, string datetimeFormat) {
151
        // Create a new payload. 
152
        Payload payload = new() {
153
            UserName = Environment.UserName,
154
            HostName = Environment.MachineName,
155
            TimeStamp = DateTime.Now.ToString(datetimeFormat),
156
            HeadDevice = new DebuggerInfo {
157
                SerialNumber = headSerialNumber
158
            },
159
            BodyDevice = new DebuggerInfo {
160
                SerialNumber = bodySerialNumber
161
            },
162
            Status = ConnectionStatus.Connected
163
        };
165 164
            
166
            // Send it to the server and return it.
167
            await _apiClient.SendPayloadAsync(payload);
168
            return payload;
169
        }
165
        // Send it to the server and return it.
166
        await _apiClient.SendPayloadAsync(payload);
167
        return payload;
168
    }
170 169

  
171
        /// <summary>
172
        /// Periodically runs process detection. This method is instantiated
173
        /// as a thread from the main class (Program.cs).
174
        /// </summary>
175
        public async void RunPeriodicDetection() {
176
            Program.DefaultLogger.Info("Process periodic detector has started");
177
            DetectionRunning = true;
170
    /// <summary>
171
    /// Periodically runs process detection. This method is instantiated
172
    /// as a thread from the main class (Program.cs).
173
    /// </summary>
174
    public async void RunPeriodicDetection() {
175
        Program.DefaultLogger.Info("Process periodic detector has started");
176
        DetectionRunning = true;
178 177
            
179
            while (DetectionRunning) {
180
                await DetectProcessAsync();
181
                Thread.Sleep((int) _detectionPeriodMs);
182
            }
178
        while (DetectionRunning) {
179
            await DetectProcessAsync();
180
            Thread.Sleep((int) _detectionPeriodMs);
183 181
        }
184 182
    }
185
}
183
}
ld_client/LDClient/detection/ProcessUtils.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Diagnostics;
4
using System.Linq;
5
using System.Text;
6
using System.Threading.Tasks;
1
using System.Diagnostics;
2

  
3
namespace LDClient.detection; 
4

  
5
/// <summary>
6
/// This class implements the IProcessUtils interface.
7
/// It implements methods that are used when dealing with processes.
8
/// </summary>
9
public class ProcessUtils : IProcessUtils {
7 10

  
8
namespace LDClient.detection {
9
    
10 11
    /// <summary>
11
    /// This class implements the IProcessUtils interface.
12
    /// It implements methods that are used when dealing with processes.
12
    /// Checks if a process is running or not.
13 13
    /// </summary>
14
    public class ProcessUtils : IProcessUtils {
15

  
16
        /// <summary>
17
        /// Checks if a process is running or not.
18
        /// </summary>
19
        /// <param name="name">Name of the process</param>
20
        /// <returns>True, if the process is running. False otherwise.</returns>
21
        public bool IsProcessRunning(string name) {
22
            return Process.GetProcessesByName(name).Length > 0;
23
        }
14
    /// <param name="name">Name of the process</param>
15
    /// <returns>True, if the process is running. False otherwise.</returns>
16
    public bool IsProcessRunning(string name) {
17
        return Process.GetProcessesByName(name).Length > 0;
18
    }
24 19
        
25
        /// <summary>
26
        /// Executes a new process (t32rem.exe) with arguments which are passed in
27
        /// as a parameter of the method.
28
        /// </summary>
29
        /// <param name="fileName">Path to the .exe file</param>
30
        /// <param name="argument">Arguments passed into the .exe file</param>
31
        /// <param name="timeout">Timeout used when waiting for the process to terminate</param>
32
        /// <param name="desiredExitCode">Status code indicating a successful termination of the process.</param>
33
        /// <returns>True, if the command was executed successfully. False otherwise.</returns>
34
        public bool ExecuteNewProcess(string fileName, string argument, int timeout, int desiredExitCode) {
35
            // Create a new process.
36
            var t32RemProcess = new Process();
37
            t32RemProcess.StartInfo.FileName = fileName;
38
            t32RemProcess.StartInfo.Arguments = argument;
20
    /// <summary>
21
    /// Executes a new process (t32rem.exe) with arguments which are passed in
22
    /// as a parameter of the method.
23
    /// </summary>
24
    /// <param name="fileName">Path to the .exe file</param>
25
    /// <param name="argument">Arguments passed into the .exe file</param>
26
    /// <param name="timeout">Timeout used when waiting for the process to terminate</param>
27
    /// <param name="desiredExitCode">Status code indicating a successful termination of the process.</param>
28
    /// <returns>True, if the command was executed successfully. False otherwise.</returns>
29
    public bool ExecuteNewProcess(string fileName, string argument, int timeout, int desiredExitCode) {
30
        // Create a new process.
31
        var t32RemProcess = new Process();
32
        t32RemProcess.StartInfo.FileName = fileName;
33
        t32RemProcess.StartInfo.Arguments = argument;
39 34
            
40
            try {
41
                // Execute the process and wait until it terminates or until the timeout is up.
42
                t32RemProcess.Start();
43
                if (!t32RemProcess.WaitForExit(timeout)) {
44
                    Program.DefaultLogger.Error($"Execution has not terminated within a predefined timeout of {timeout} ms");
45
                    return false;
46
                }
35
        try {
36
            // Execute the process and wait until it terminates or until the timeout is up.
37
            t32RemProcess.Start();
38
            if (!t32RemProcess.WaitForExit(timeout)) {
39
                Program.DefaultLogger.Error($"Execution has not terminated within a predefined timeout of {timeout} ms");
40
                return false;
41
            }
47 42
                
48
                // Check if the process terminated successfully.
49
                if (t32RemProcess.ExitCode != desiredExitCode) {
50
                    Program.DefaultLogger.Error($"Execution terminated with an error code of {t32RemProcess.ExitCode}");
51
                    return false;
52
                }
53
            } catch (Exception exception) {
54
                Program.DefaultLogger.Error($"Failed to run {fileName} {argument}. {exception.Message}");
43
            // Check if the process terminated successfully.
44
            if (t32RemProcess.ExitCode != desiredExitCode) {
45
                Program.DefaultLogger.Error($"Execution terminated with an error code of {t32RemProcess.ExitCode}");
55 46
                return false;
56 47
            }
57
            return true;
48
        } catch (Exception exception) {
49
            Program.DefaultLogger.Error($"Failed to run {fileName} {argument}. {exception.Message}");
50
            return false;
58 51
        }
52
        return true;
59 53
    }
60
}
54
}
ld_client/LDClient/detection/T32ApiFetcher.cs
1
using System;
2
using System.Collections.Generic;
3
using System.Linq;
4
using System.Runtime.InteropServices;
5
using System.Text;
6
using System.Threading.Tasks;
1
using System.Runtime.InteropServices;
7 2

  
8
namespace LDClient.detection {
3
namespace LDClient.detection; 
9 4

  
10
    public class T32ApiFetcher : AInfoFetcher, IT32Utils {
5
public class T32ApiFetcher : AInfoFetcher, IT32Utils {
11 6
#if _WINDOWS
12
        private const string T32DllLibrary = "./lib/t32api64.dll";
7
    /// <summary>
8
    /// Path to the Trace32 API library
9
    /// </summary>
10
    private const string T32DllLibrary = "./lib/t32api64.dll";
13 11
#else
14 12
        private const string T32DllLibrary = "./lib/t32api64.so";
15 13
#endif
14
    /// <summary>
15
    /// Address of the listening t32 application
16
    /// </summary>
17
    private readonly string _t32Address;
18

  
19
    /// <summary>
20
    ///  Port of the listening t32 application
21
    /// </summary>
22
    private readonly string _t32Port;
23

  
24
    /// <summary>
25
    /// Size of the packets send/received from t32 application
26
    /// </summary>
27
    private readonly string _t32PacketLength;
28

  
29
    /// <summary>
30
    /// List of commands to be executed by though the t32 api
31
    /// </summary>
32
    private readonly string[] _commands;
33

  
34
    /// <summary>
35
    /// 
36
    /// </summary>
37
    /// <param name="maxAttempts">Maximum number of attempts to locate and parse the .txt file</param>
38
    /// <param name="waitPeriodMs">Period (how often) the application tries to locate and parse the .txt file</param>
39
    /// <param name="infoFilePath">Path to the .txt file which is generated from the debugger</param>
40
    /// <param name="t32Address">Address of the listening t32 application</param>
41
    /// <param name="t32Port">Port of the listening t32 application</param>
42
    /// <param name="t32PacketLength"> Size of the packets send/received from t32 application </param>
43
    /// <param name="commands"> List of commands to be executed by though the t32 api</param>
44
    public T32ApiFetcher(uint maxAttempts, uint waitPeriodMs, string infoFilePath, string t32Address, 
45
        string t32Port, string t32PacketLength, string[] commands) : base(maxAttempts, waitPeriodMs, infoFilePath) {
46
        this._t32Address = t32Address;
47
        this._t32Port = t32Port;
48
        this._t32PacketLength = t32PacketLength;
49
        this._commands = commands;
50
    }
16 51

  
17
        private readonly string _t32Address;
18
        private readonly string _t32Port;
19
        private readonly string _t32PacketLength;
20
        private readonly string[] _commands;
21

  
22
        public T32ApiFetcher(uint maxAttempts, uint waitPeriodMs, string infoFilePath, string t32Address, 
23
            string t32Port, string t32PacketLength, string[] commands) : base(maxAttempts, waitPeriodMs, infoFilePath) {
24
            this._t32Address = t32Address;
25
            this._t32Port = t32Port;
26
            this._t32PacketLength = t32PacketLength;
27
            this._commands = commands;
28
        }
29

  
30

  
31
        [DllImport(T32DllLibrary, CharSet = CharSet.Ansi)]
32
        private static extern int T32_Config(string s1, string s2);
33

  
34
        [DllImport(T32DllLibrary, CharSet = CharSet.Ansi)]
35
        private static extern int T32_Init();
36 52

  
37
        [DllImport(T32DllLibrary, CharSet = CharSet.Ansi)]
38
        private static extern int T32_Attach(int dev);
53
    /// <summary>
54
    /// To see full documentation of following T32 API methods please check the https://www2.lauterbach.com/pdf/api_remote_c.pdf
55
    /// </summary>
56
    /// <param name="s1"></param>
57
    /// <param name="s2"></param>
58
    /// <returns>return code</returns>
59
    [DllImport(T32DllLibrary, CharSet = CharSet.Ansi)]
60
    private static extern int T32_Config(string s1, string s2);
61

  
62
    /// <summary>
63
    /// To see full documentation of following T32 API methods please check the https://www2.lauterbach.com/pdf/api_remote_c.pdf
64
    /// </summary>
65
    /// <returns>Return code</returns>
66
    [DllImport(T32DllLibrary, CharSet = CharSet.Ansi)]
67
    private static extern int T32_Init();
68

  
69
    /// <summary>
70
    /// To see full documentation of following T32 API methods please check the https://www2.lauterbach.com/pdf/api_remote_c.pdf
71
    /// </summary>
72
    /// <param name="dev"></param>
73
    /// <returns>Return code</returns>
74
    [DllImport(T32DllLibrary, CharSet = CharSet.Ansi)]
75
    private static extern int T32_Attach(int dev);
76

  
77
    /// <summary>
78
    /// To see full documentation of following T32 API methods please check the https://www2.lauterbach.com/pdf/api_remote_c.pdf
79
    /// </summary>
80
    /// <param name="command"></param>
81
    /// <returns>Return code</returns>
82
    [DllImport(T32DllLibrary, CharSet = CharSet.Ansi)]
83
    private static extern int T32_Cmd(string command);
84

  
85
    /// <summary>
86
    /// To see full documentation of following T32 API methods please check the https://www2.lauterbach.com/pdf/api_remote_c.pdf
87
    /// </summary>
88
    /// <returns>Return code</returns>
89
    [DllImport(T32DllLibrary, CharSet = CharSet.Ansi)]
90
    private static extern int T32_Exit();
91

  
92

  
93
    /// <summary>
94
    /// This method initialized the connection with the trace32 application API.
95
    /// It setups the standard connection configuration a tries to connect to the API
96
    /// </summary>
97
    /// <returns>true on success</returns>
98
    public bool InitConnection() {
99
        Program.DefaultLogger.Debug("Trace32 connection initialization");
100
        var config1 = T32_Config("NODE=", _t32Address);
101
        var config2 = T32_Config("PORT=", _t32Port);
102
        var config3 = T32_Config("PACKLEN=", _t32PacketLength);
103

  
104
        if (config1 != 0 || config2 != 0 || config3 != 0) {
105
            Program.DefaultLogger.Error("Trace32 API connection configuration failed.");
106
            return false;
107
        }
108
        var init = T32_Init();
109
        if (init != 0) {
110
            Program.DefaultLogger.Error("Trace32 API connection init failed.");
111
            return false;
112
        }
39 113

  
40
        [DllImport(T32DllLibrary, CharSet = CharSet.Ansi)]
41
        private static extern int T32_Cmd(string command);
114
        var attach = T32_Attach(1);
115
        if (attach != 0) {
116
            Program.DefaultLogger.Error("Trace32 API connection attach failed.");
117
        }
42 118

  
43
        [DllImport(T32DllLibrary, CharSet = CharSet.Ansi)]
44
        private static extern int T32_Exit();
45
        
46
        public bool InitConnection() {
47
            Program.DefaultLogger.Debug("Trace32 connection initialization");
48
            var config1 = T32_Config("NODE=", _t32Address);
49
            var config2 = T32_Config("PORT=", _t32Port);
50
            var config3 = T32_Config("PACKLEN=", _t32PacketLength);
119
        Program.DefaultLogger.Info("Trace32 connection established");
120
        return true;
121
    }
51 122

  
52
            if (config1 != 0 || config2 != 0 || config3 != 0) {
53
                Program.DefaultLogger.Error("Trace32 API connection configuration failed.");
54
                return false;
55
            }
56
            var init = T32_Init();
57
            if (init != 0) {
58
                Program.DefaultLogger.Error("Trace32 API connection init failed.");
123
    /// <summary>
124
    /// Method executes all passed commands though the trace32 API
125
    /// </summary>
126
    /// <returns>true on success</returns>
127
    public bool ExecuteCommands() {
128
        Program.DefaultLogger.Info("Trace32 API commands execution.");
129
        foreach (var command in _commands) {
130
            Program.DefaultLogger.Debug($"Executing Trace32 command '{command}'.");
131
            var ret = T32_Cmd(command);
132
            if (ret != 0) {
133
                Program.DefaultLogger.Error($"Execution of command '{command}' failed. Return code {ret}.");
59 134
                return false;
60 135
            }
61

  
62
            var attach = T32_Attach(1);
63
            if (attach != 0) {
64
                Program.DefaultLogger.Error("Trace32 API connection attach failed.");
65
            }
66

  
67
            Program.DefaultLogger.Info("Trace32 connection established");
68
            return true;
69
        }
70

  
71
        public bool ExecuteCommands() {
72
            Program.DefaultLogger.Info("Trace32 API commands execution.");
73
            foreach (var command in _commands) {
74
                Program.DefaultLogger.Debug($"Executing Trace32 command '{command}'.");
75
                var ret = T32_Cmd(command);
76
                if (ret != 0) {
77
                    Program.DefaultLogger.Error($"Execution of command '{command}' failed. Return code {ret}.");
78
                    return false;
79
                }
80
            }
81
            Program.DefaultLogger.Info("All Trace32 commands executed successfully.");
82
            return true;
83
        }
84

  
85
        public bool CloseConnection() {
86
            Program.DefaultLogger.Debug("Trace32 connection exit");
87
            return T32_Exit() == 0;
88 136
        }
137
        Program.DefaultLogger.Info("All Trace32 commands executed successfully.");
138
        return true;
139
    }
89 140

  
90
        protected override bool FetchData() {
91
            var connected = false;
92
            for (var i = 0; i < _maxAttempts; i++) {
93
                connected = InitConnection();
94
                if (connected) {
95
                    break;
96
                }
97
                Thread.Sleep((int)_waitPeriodMs);
141
    /// <summary>
142
    /// This method closes the connection with the trace32 application api
143
    /// </summary>
144
    /// <returns>true on success</returns>
145
    public bool CloseConnection() {
146
        Program.DefaultLogger.Debug("Trace32 connection exit");
147
        return T32_Exit() == 0;
148
    }
98 149

  
150
    /// <summary>
151
    /// Method tries to fetch the data from the trace32 application.
152
    /// Upon connection fail it tries again for specified number of times
153
    /// </summary>
154
    /// <returns>true on success</returns>
155
    protected override bool FetchData() {
156
        var connected = false;
157
        for (var i = 0; i < _maxAttempts; i++) {
158
            connected = InitConnection();
159
            if (connected) {
160
                break;
99 161
            }
100
            return connected && ExecuteCommands() && CloseConnection();
162
            Thread.Sleep((int)_waitPeriodMs);
163

  
101 164
        }
165
        return connected && ExecuteCommands() && CloseConnection();
102 166
    }
103
}
167
}
ld_client/LDClient/detection/T32RemFetcher.cs
1
using System.Diagnostics;
2
using LDClient.utils;
3
using LDClient.utils.loggers;
1
namespace LDClient.detection; 
4 2

  
5
namespace LDClient.detection {
3
public class T32RemFetcher : AInfoFetcher{
6 4

  
7
    public class T32RemFetcher : AInfoFetcher{
5
    /// <summary>
6
    /// Path to the t32rem.exe file which is used to send commands to the debugger.
7
    /// </summary>
8
    private readonly string _f32RemExecutable;
8 9

  
9
        /// <summary>
10
        /// Path to the t32rem.exe file which is used to send commands to the debugger.
11
        /// </summary>
12
        private readonly string _f32RemExecutable;
10
    /// <summary>
11
    /// Arguments (commands) sent to the debugger in order to generate a .txt file
12
    /// containing all the desired information.
13
    /// </summary>
14
    private readonly string[] _f32RemArguments;
13 15

  
14
        /// <summary>
15
        /// Arguments (commands) sent to the debugger in order to generate a .txt file
16
        /// containing all the desired information.
17
        /// </summary>
18
        private readonly string[] _f32RemArguments;
16
    /// <summary>
17
    /// Status code indicating a successful termination of t32rem.exe
18
    /// </summary>
19
    private readonly int _f32SuccessExitCode;
19 20

  
20
        /// <summary>
21
        /// Status code indicating a successful termination of t32rem.exe
22
        /// </summary>
23
        private readonly int _f32SuccessExitCode;
24 21

  
22
    /// <summary>
23
    /// Timeout used when waiting for the t32rem.exe to finish.
24
    /// </summary>
25
    private readonly int _f32WaitTimeoutMs;
25 26

  
26
        /// <summary>
27
        /// Timeout used when waiting for the t32rem.exe to finish.
28
        /// </summary>
29
        private readonly int _f32WaitTimeoutMs;
27
    /// <summary>
28
    /// Instance of ProcessUtils which encapsulates common functionality
29
    /// when it comes to dealing with processes (limited by the needs of this application).
30
    /// </summary>
31
    public IProcessUtils ProcessUtils;
30 32

  
31
        /// <summary>
32
        /// Instance of ProcessUtils which encapsulates common functionality
33
        /// when it comes to dealing with processes (limited by the needs of this application).
34
        /// </summary>
35
        public IProcessUtils ProcessUtils;
33
    /// <summary>
34
    /// Creates an instance of this class.
35
    /// </summary>
36
    /// <param name="maxAttempts">Maximum number of attempts to locate and parse the .txt file</param>
37
    /// <param name="waitPeriodMs">Period (how often) the application tries to locate and parse the .txt file</param>
38
    /// <param name="infoFilePath">Path to the .txt file which is generated from the debugger</param>
39
    /// <param name="f32RemExecutable">Path to the t32rem.exe file which is used to send commands to the debugger</param>
40
    /// <param name="f32RemArguments">Arguments (commands) sent to the debugger in order to generate a .txt file containing all the desired information.</param>
41
    /// <param name="f32SuccessExitCode">Status code indicating a successful termination of t32rem.exe</param>
42
    /// <param name="f32WaitTimeoutMs">Timeout used when waiting for the t32rem.exe to finish</param>
43
    public T32RemFetcher(uint maxAttempts, uint waitPeriodMs, string infoFilePath, string f32RemExecutable,
44
        string[] f32RemArguments, int f32SuccessExitCode, int f32WaitTimeoutMs) : base(maxAttempts, waitPeriodMs, infoFilePath) {
45
        _f32RemExecutable = f32RemExecutable;
46
        _f32RemArguments = f32RemArguments;
47
        _f32SuccessExitCode = f32SuccessExitCode;
48
        _f32WaitTimeoutMs = f32WaitTimeoutMs;
49
        ProcessUtils = new ProcessUtils();
36 50

  
37
        /// <summary>
38
        /// Creates an instance of this class.
39
        /// </summary>
40
        /// <param name="maxAttempts">Maximum number of attempts to locate and parse the .txt file</param>
41
        /// <param name="waitPeriodMs">Period (how often) the application tries to locate and parse the .txt file</param>
42
        /// <param name="infoFilePath">Path to the .txt file which is generated from the debugger</param>
43
        /// <param name="f32RemExecutable">Path to the t32rem.exe file which is used to send commands to the debugger</param>
44
        /// <param name="f32RemArguments">Arguments (commands) sent to the debugger in order to generate a .txt file containing all the desired information.</param>
45
        /// <param name="f32SuccessExitCode">Status code indicating a successful termination of t32rem.exe</param>
46
        /// <param name="f32WaitTimeoutMs">Timeout used when waiting for the t32rem.exe to finish</param>
47

  
48
        public T32RemFetcher(uint maxAttempts, uint waitPeriodMs, string infoFilePath, string f32RemExecutable,
49
            string[] f32RemArguments, int f32SuccessExitCode, int f32WaitTimeoutMs) : base(maxAttempts, waitPeriodMs, infoFilePath) {
50
            _f32RemExecutable = f32RemExecutable;
51
            _f32RemArguments = f32RemArguments;
52
            _f32SuccessExitCode = f32SuccessExitCode;
53
            _f32WaitTimeoutMs = f32WaitTimeoutMs;
54
            ProcessUtils = new ProcessUtils();
51
    }
55 52

  
53
    /// <summary>
54
    /// Method tries to fetch the data from the trace32 application
55
    /// via defined executable 
56
    /// </summary>
57
    /// <returns>true upon success</returns>
58
    protected override bool FetchData() {
59
        if (_f32RemArguments == null) {
60
            Program.DefaultLogger.Error($"Failed to run {_f32RemExecutable} - no parameters were given");
61
            return false;
56 62
        }
57

  
58
        protected override bool FetchData() {
59
            if (_f32RemArguments == null) {
60
                Program.DefaultLogger.Error($"Failed to run {_f32RemExecutable} - no parameters were given");
63
        // Execute one all arguments (commands) one by one.
64
        foreach (var argument in _f32RemArguments) {
65
            if (!ProcessUtils.ExecuteNewProcess(_f32RemExecutable, argument, _f32WaitTimeoutMs, _f32SuccessExitCode)) {
61 66
                return false;
62 67
            }
63
            // Execute one all arguments (commands) one by one.
64
            foreach (var argument in _f32RemArguments) {
65
                if (!ProcessUtils.ExecuteNewProcess(_f32RemExecutable, argument, _f32WaitTimeoutMs, _f32SuccessExitCode)) {
66
                    return false;
67
                }
68
            }
69
            return true;
70 68
        }
69
        return true;
71 70
    }
72 71
}
ld_client/LDClient/utils/ConfigLoader.cs
39 39
        private const string DdSection = "DebuggerDetection";
40 40

  
41 41

  
42
        public string[] T32ApiCommands { get; private set; } = null!;
43
        public string T32ApiAddress { get; private set; } = null!;
44
        public string T32ApiPort { get; private set; } = null!;
45
        public string T32ApiPacketLen { get; private set; } = null!;
46

  
47 42
        #region Logger
48 43

  
49 44
        /// <summary>
......
169 164
        /// </summary>
170 165
        public int T32RemWaitTimeoutMs { get; private set; }
171 166

  
167

  
168
        /// <summary>
169
        /// List of commands to be executed by though the t32 api
170
        /// </summary>
171
        public string[] T32ApiCommands { get; private set; } = null!;
172

  
173
        /// <summary>
174
        /// Address of the listening t32 application
175
        /// </summary>
176
        public string T32ApiAddress { get; private set; } = null!;
177

  
178
        /// <summary>
179
        /// Port of the listening t32 application
180
        /// </summary>
181
        public string T32ApiPort { get; private set; } = null!;
182

  
183
        /// <summary>
184
        /// Size of the packets send/received from t32 application
185
        /// </summary>
186
        public string T32ApiPacketLen { get; private set; } = null!;
187

  
172 188
        #endregion
173 189

  
174 190
        /// <summary>

Také k dispozici: Unified diff