Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
ContractGetter.cs
1using System;
3using System.Collections.Specialized;
4using System.Security.Cryptography.X509Certificates;
5using System.Text;
6using System.Threading.Tasks;
7using System.Web;
8using Waher.Content;
14
16{
20 public class ContractGetter : IContentGetter, IDisposable
21 {
22 private static string defaultPurpose = string.Empty;
23
24 private readonly Dictionary<string, TaskCompletionSource<ContractPetitionResponseEventArgs>> contractPetitions = new Dictionary<string, TaskCompletionSource<ContractPetitionResponseEventArgs>>();
25 private readonly object syncObj = new object();
26 private bool handlerAdded = false;
27
32 {
33 }
34
38 public static string DefaultPurpose
39 {
40 get => defaultPurpose;
41 set
42 {
43 if (string.IsNullOrEmpty(value))
44 throw new ArgumentException("Default purpose cannot be empty.", nameof(DefaultPurpose));
45
46 defaultPurpose = value;
47 }
48 }
49
53 public string[] UriSchemes => new string[] { "iotsc" };
54
61 public bool CanGet(Uri Uri, out Grade Grade)
62 {
63 if (string.Compare(Uri.Scheme, "iotsc", true) == 0)
64 {
65 Grade = Grade.Ok;
66 return true;
67 }
68 else
69 {
70 Grade = Grade.NotAtAll;
71 return false;
72 }
73 }
74
78 public void Dispose()
79 {
80 lock (this.syncObj)
81 {
82 if (this.handlerAdded)
83 {
84 Gateway.ContractsClient.PetitionedContractResponseReceived -= this.Client_PetitionedContractResponseReceived;
85 this.handlerAdded = false;
86 }
87 }
88 }
89
98 public Task<ContentResponse> GetAsync(Uri Uri, X509Certificate Certificate,
99 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
100 {
101 return this.GetAsync(Uri, Certificate, RemoteCertificateValidator, InternetContent.DefaultTimeout, Headers);
102 }
103
112 public async Task<ContentResponse> GetAsync(Uri Uri, X509Certificate Certificate,
113 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
114 {
116 if (Client is null)
117 return new ContentResponse(new NotSupportedException("Contracts feature not supported or activated on this system."));
118
119 lock (this.syncObj)
120 {
121 if (!this.handlerAdded)
122 {
123 Client.PetitionedContractResponseReceived += this.Client_PetitionedContractResponseReceived;
124 this.handlerAdded = true;
125 }
126 }
127
128 string ContractId = Uri.AbsolutePath;
129
130 try
131 {
132 Contract Contract = await Client.GetContractAsync(ContractId);
133 return new ContentResponse(string.Empty, Contract, Array.Empty<byte>());
134 }
135 catch (Exception)
136 {
137 TaskCompletionSource<ContractPetitionResponseEventArgs> Result = new TaskCompletionSource<ContractPetitionResponseEventArgs>();
138 string PetitionId = Guid.NewGuid().ToString();
139 string Purpose = null;
140
141 if (!string.IsNullOrEmpty(Uri.Query))
142 {
143 NameValueCollection Parameters = HttpUtility.ParseQueryString(Uri.Query);
144
145 foreach (string Parameter in Parameters.AllKeys)
146 {
147 switch (Parameter.ToLower())
148 {
149 case "p":
150 case "purpose":
151 Purpose = Parameters[Parameter];
152 break;
153 }
154 }
155 }
156
157 if (string.IsNullOrEmpty(Purpose))
158 Purpose = "Processing referenced contract.";
159
160 lock (this.syncObj)
161 {
162 this.contractPetitions[PetitionId] = Result;
163 }
164
165 try
166 {
167 await Client.PetitionContractAsync(ContractId, PetitionId, Purpose);
168
169 Task _ = Task.Delay(TimeoutMs).ContinueWith((T) =>
170 {
171 Result.TrySetException(new TimeoutException("Response to petition not received within allotted time."));
172 return Task.CompletedTask;
173 });
174 }
175 catch (Exception ex)
176 {
177 lock (this.syncObj)
178 {
179 this.contractPetitions.Remove(PetitionId);
180 }
181
182 return new ContentResponse(ex);
183 }
184
185 ContractPetitionResponseEventArgs e = await Result.Task;
186
187 return new ContentResponse(string.Empty, e.RequestedContract, Array.Empty<byte>());
188 }
189 }
190
191 private Task Client_PetitionedContractResponseReceived(object Sender, ContractPetitionResponseEventArgs e)
192 {
193 lock (this.syncObj)
194 {
195 if (this.contractPetitions.TryGetValue(e.PetitionId, out TaskCompletionSource<ContractPetitionResponseEventArgs> Result))
196 Result.TrySetResult(e);
197 }
198
199 return Task.CompletedTask;
200 }
201
210 public Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
211 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
212 {
213 return this.GetTempStreamAsync(Uri, Certificate, RemoteCertificateValidator, InternetContent.DefaultTimeout, Headers);
214 }
215
225 public Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
226 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, TemporaryStream Destination, params KeyValuePair<string, string>[] Headers)
227 {
228 return this.GetTempStreamAsync(Uri, Certificate, RemoteCertificateValidator, InternetContent.DefaultTimeout, Destination, Headers);
229 }
230
240 public Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
241 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
242 {
243 return this.GetTempStreamAsync(Uri, Certificate, RemoteCertificateValidator, TimeoutMs, null, Headers);
244 }
245
256 public async Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
257 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs, TemporaryStream Destination,
258 params KeyValuePair<string, string>[] Headers)
259 {
260 ContentResponse Content = await this.GetAsync(Uri, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
261 if (Content.HasError)
262 return new ContentStreamResponse(Content.Error);
263
265 StringBuilder Xml = new StringBuilder();
266 Contract.Serialize(Xml, true, true, true, true, true, true, true);
267 byte[] Bin = Encoding.UTF8.GetBytes(Xml.ToString());
268 bool DestinationCreated = false;
269
270 if (Destination is null)
271 {
272 Destination = new TemporaryStream();
273 DestinationCreated = true;
274 }
275
276 try
277 {
278 await Destination.WriteAsync(Bin, 0, Bin.Length);
279 }
280 catch (Exception ex)
281 {
282 if (DestinationCreated)
283 Destination.Dispose();
284
285 return new ContentStreamResponse(ex);
286 }
287
288 return new ContentStreamResponse("application/xml; charset=utf-8", Destination);
289 }
290 }
291}
Contains information about a response to a content request.
bool HasError
If an error occurred.
object Decoded
Decoded object.
Exception Error
Error response.
Contains information about a stream response to a content request.
Static class managing encoding and decoding of internet content.
static int DefaultTimeout
Default timeout of internet access methods, in milliseconds.
Static class managing the runtime environment of the IoT Gateway.
Definition: Gateway.cs:147
static ContractsClient ContractsClient
XMPP Contracts Client, if such a compoent is available on the XMPP broker.
Definition: Gateway.cs:5299
Contains the definition of a contract
Definition: Contract.cs:22
void Serialize(StringBuilder Xml, bool IncludeNamespace, bool IncludeIdAttribute, bool IncludeClientSignatures, bool IncludeAttachments, bool IncludeStatus, bool IncludeServerSignature, bool IncludeAttachmentReferences)
Serializes the Contract, in normalized form.
Definition: Contract.cs:1621
Adds support for legal identities, smart contracts and signatures to an XMPP client.
Task PetitionContractAsync(string ContractId, string PetitionId, string Purpose)
Sends a petition to the parts of a smart contract, to access the information in the contract....
Task< Contract > GetContractAsync(string ContractId)
Gets a contract
Abstract base class for contractual parameters
Definition: Parameter.cs:17
Manages a temporary stream. Contents is kept in-memory, if below a memory threshold,...
override void Dispose(bool disposing)
Releases the unmanaged resources used by the System.IO.Stream and optionally releases the managed res...
override async Task WriteAsync(byte[] buffer, int offset, int count, CancellationToken cancellationToken)
Asynchronously writes a sequence of bytes to the current stream, advances the current position within...
Task< ContentResponse > GetAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets a resource, using a Uniform Resource Identifier (or Locator).
bool CanGet(Uri Uri, out Grade Grade)
If the getter is able to get a resource, given its URI.
Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
async Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, TemporaryStream Destination, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
async Task< ContentResponse > GetAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a resource, using a Uniform Resource Identifier (or Locator).
Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
string[] UriSchemes
Supported URI schemes.
Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, TemporaryStream Destination, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
static string DefaultPurpose
Default purpose string.
Basic interface for Internet Content getters. A class implementing this interface and having a defaul...
Definition: ImplTypes.g.cs:58
Grade
Grade enumeration
Definition: Grade.cs:7