-
Notifications
You must be signed in to change notification settings - Fork 2
/
Program.cs
185 lines (158 loc) · 7.35 KB
/
Program.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
using OpenSource.UPnP;
using System;
using System.Diagnostics;
using System.Threading;
namespace upnpc {
class Program {
/// <summary>
/// Thrown when a condition in running the program occurs that should
/// cause it to terminate unsuccessfully.
/// </summary>
class ProgramExecutionException : Exception {
public ProgramExecutionException(string message) : base(message) { }
}
/// <summary>
/// The service we're going to talk to.
/// </summary>
volatile UPnPService _Service = null;
/// <summary>
/// Options for this Program.
/// </summary>
readonly Options _Options;
/// <summary>
/// Prints the verbose status of the discovery to the Console iff
/// _Options.VerboseDiscovery is true.
/// </summary>
private void PrintDiscoveryStatus(string format, params object[] args) {
if (_Options.VerboseDiscovery)
Console.WriteLine(format, args);
}
/// <summary>
/// Handles a newly discovered or added device.
/// </summary>
/// <param name="smartControlPoint">UPnPSmartControlPoint that discovered this device.</param>
/// <param name="addedDevice">The device added.</param>
protected void HandleDeviceAdded(UPnPSmartControlPoint smartControlPoint, UPnPDevice addedDevice) {
var logPrefix = string.Format("Discovered Device \"{0}\", URN={1}, UDN={2}: ",
addedDevice.FriendlyName, addedDevice.DeviceURN, addedDevice.UniqueDeviceName);
if (!_Options.Matches(addedDevice)) {
PrintDiscoveryStatus(logPrefix + "Device does not match");
return;
} else {
PrintDiscoveryStatus(logPrefix + "Device matches");
}
foreach (UPnPService svc in addedDevice.Services)
HandleServiceAdded(smartControlPoint, svc);
}
/// <summary>
/// Handles a newly discovered or added service.
/// </summary>
/// <param name="smartControlPoint">UPnPSmartControlPoint that discovered this service.</param>
/// <param name="addedService">The service added.</param>
protected void HandleServiceAdded(UPnPSmartControlPoint smartControlPoint, UPnPService addedService) {
var logPrefix = string.Format("Discovered service ID={0}, URN={1}: ",
addedService.ServiceID, addedService.ServiceURN);
if (!_Options.Matches(addedService)) {
PrintDiscoveryStatus(logPrefix + "Does not match filter");
return;
} else {
PrintDiscoveryStatus(logPrefix + "Matches filter");
}
var old = Interlocked.CompareExchange<UPnPService>(ref _Service, addedService, null);
if (old != null && old != addedService)
Console.Error.WriteLine("Ignoring duplicate service {0}, already got {1}",
addedService, old);
}
/// <summary>
/// Dumps all arguments of an UPnPAction to Console.
/// </summary>
/// <param name="action">The UPnPAction whose parameters are to be dumped.</param>
private static void DumpVars(UPnPAction action) {
foreach (UPnPArgument arg in action.ArgumentList) {
Console.WriteLine("var name={0} (direction={1} type={2} value=\"{3}\" isReturnValue={4}",
arg.Name, arg.Direction, arg.RelatedStateVar.GetNetType(), arg.DataValue, arg.IsReturnValue);
}
}
/// <summary>
/// Initializes this Program (i.e. parse Options).
/// </summary>
/// <param name="args">The command-line arguments.</param>
private Program(string[] args) {
_Options = new Options(args);
}
/// <summary>
/// Runs this Program.
/// </summary>
private void Run() {
UPnPSmartControlPoint smartControlPoint = new UPnPSmartControlPoint(HandleDeviceAdded);
smartControlPoint.OnAddedService += HandleServiceAdded;
Stopwatch discoveryTimeoutStopwatch = new Stopwatch();
Stopwatch rescanTimeoutStopwatch = new Stopwatch();
discoveryTimeoutStopwatch.Start();
rescanTimeoutStopwatch.Start();
while (_Service == null && discoveryTimeoutStopwatch.ElapsedMilliseconds < _Options.DisoveryTimeoutMs) {
if (rescanTimeoutStopwatch.ElapsedMilliseconds >= _Options.RediscoveryMs) {
PrintDiscoveryStatus("Rescanning");
smartControlPoint.Rescan();
rescanTimeoutStopwatch.Restart();
}
Thread.Sleep(100);
}
if (_Service == null) {
throw new ProgramExecutionException("Service not found");
}
UPnPAction action = _Service.GetAction(_Options.Action);
if (action == null)
throw new ProgramExecutionException("Action \"" + _Options.Action + "\" not found.");
if (_Options.DumpVars) {
DumpVars(action);
return;
}
foreach (var setVar in _Options.SetVars) {
string name = setVar.Key;
string value = setVar.Value;
UPnPArgument arg = action.GetArg(name);
if (arg == null)
throw new ProgramExecutionException("Variable \"" + name + "\" not found.");
arg.DataValue = Convert.ChangeType(value, arg.RelatedStateVar.GetNetType());
}
_Service.InvokeSync(action.Name, action.ArgumentList);
foreach (var name in _Options.GetVars) {
UPnPArgument arg = action.GetArg(name);
if (arg == null)
throw new ProgramExecutionException("Variable \"" + name + "\" not found.");
Console.WriteLine(arg.DataValue);
}
foreach (var expectVar in _Options.ExpectVars) {
string name = expectVar.Key, value = expectVar.Value;
UPnPArgument arg = action.GetArg(name);
if (arg == null)
throw new ProgramExecutionException("Variable \"" + name + "\" not found.");
if (!value.Equals(arg.DataValue))
throw new ProgramExecutionException(String.Format(
"Variable \"{0}\" expected to be \"{1}\", but is actually \"{2}\".",
name, value, arg.DataValue));
}
}
/// <summary>
/// Constructs and runs a new Program.
/// </summary>
/// <param name="args">The command-line arguments.</param>
/// <returns>0 on success, 1 on error.</returns>
static int Main(string[] args) {
int rc = 1;
try {
new Program(args).Run();
rc = 0;
} catch (Options.UsageException ue) {
Console.Error.WriteLine("Error: {0}\nUsage: {1}",
ue.Message, Options.Help());
} catch (ProgramExecutionException pee) {
Console.Error.WriteLine("Error during execution: {0}", pee.Message);
} catch (Exception e) {
Console.Error.WriteLine(e.ToString());
}
return rc;
}
}
}