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;
2using System.Collections.Generic;
3using System.Collections.Specialized;
4using System.Runtime.ExceptionServices;
5using System.Security.Cryptography.X509Certificates;
6using System.Text;
7using System.Threading.Tasks;
8using System.Web;
9using Waher.Content;
15
17{
21 public class ContractGetter : IContentGetter, IDisposable
22 {
23 private static string defaultPurpose = string.Empty;
24 private static int defaultTimeoutMilliseconds = 60000;
25
26 private readonly Dictionary<string, TaskCompletionSource<ContractPetitionResponseEventArgs>> contractPetitions = new Dictionary<string, TaskCompletionSource<ContractPetitionResponseEventArgs>>();
27 private readonly object syncObj = new object();
28 private bool handlerAdded = false;
29
34 {
35 }
36
40 public static string DefaultPurpose
41 {
42 get => defaultPurpose;
43 set
44 {
45 if (string.IsNullOrEmpty(value))
46 throw new ArgumentException("Default purpose cannot be empty.", nameof(DefaultPurpose));
47
48 defaultPurpose = value;
49 }
50 }
51
56 {
57 get => defaultTimeoutMilliseconds;
58 set
59 {
60 if (value <= 0)
61 throw new ArgumentException("Default timeout must be positivt.", nameof(DefaultTimeoutMilliseconds));
62
63 defaultTimeoutMilliseconds = value;
64 }
65 }
66
70 public string[] UriSchemes => new string[] { "iotsc" };
71
78 public bool CanGet(Uri Uri, out Grade Grade)
79 {
80 if (string.Compare(Uri.Scheme, "iotsc", true) == 0)
81 {
82 Grade = Grade.Ok;
83 return true;
84 }
85 else
86 {
87 Grade = Grade.NotAtAll;
88 return false;
89 }
90 }
91
95 public void Dispose()
96 {
97 lock (this.syncObj)
98 {
99 if (this.handlerAdded)
100 {
101 Gateway.ContractsClient.PetitionedContractResponseReceived -= this.Client_PetitionedContractResponseReceived;
102 this.handlerAdded = false;
103 }
104 }
105 }
106
115 public Task<object> GetAsync(Uri Uri, X509Certificate Certificate,
116 RemoteCertificateEventHandler RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
117 {
118 return this.GetAsync(Uri, Certificate, RemoteCertificateValidator, defaultTimeoutMilliseconds, Headers);
119 }
120
129 public async Task<object> GetAsync(Uri Uri, X509Certificate Certificate,
130 RemoteCertificateEventHandler RemoteCertificateValidator, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
131 {
132 ContractsClient Client = Gateway.ContractsClient
133 ?? throw new NotSupportedException("Contracts feature not supported or activated on this system.");
134
135 lock (this.syncObj)
136 {
137 if (!this.handlerAdded)
138 {
139 Client.PetitionedContractResponseReceived += this.Client_PetitionedContractResponseReceived;
140 this.handlerAdded = true;
141 }
142 }
143
144 string ContractId = Uri.AbsolutePath;
145
146 try
147 {
148 return await Client.GetContractAsync(ContractId);
149 }
150 catch (Exception)
151 {
152 TaskCompletionSource<ContractPetitionResponseEventArgs> Result = new TaskCompletionSource<ContractPetitionResponseEventArgs>();
153 string PetitionId = Guid.NewGuid().ToString();
154 string Purpose = null;
155
156 if (!string.IsNullOrEmpty(Uri.Query))
157 {
158 NameValueCollection Parameters = HttpUtility.ParseQueryString(Uri.Query);
159
160 foreach (string Parameter in Parameters.AllKeys)
161 {
162 switch (Parameter.ToLower())
163 {
164 case "p":
165 case "purpose":
166 Purpose = Parameters[Parameter];
167 break;
168 }
169 }
170 }
171
172 if (string.IsNullOrEmpty(Purpose))
173 Purpose = "Processing referenced contract.";
174
175 lock (this.syncObj)
176 {
177 this.contractPetitions[PetitionId] = Result;
178 }
179
180 try
181 {
182 await Client.PetitionContractAsync(ContractId, PetitionId, Purpose);
183
184 Task _ = Task.Delay(TimeoutMs).ContinueWith((T) =>
185 {
186 Result.TrySetException(new TimeoutException("Response to petition not received within allotted time."));
187 return Task.CompletedTask;
188 });
189 }
190 catch (Exception ex)
191 {
192 lock (this.syncObj)
193 {
194 this.contractPetitions.Remove(PetitionId);
195 }
196
197 ExceptionDispatchInfo.Capture(ex).Throw();
198 }
199
200 ContractPetitionResponseEventArgs e = await Result.Task;
201
202 return e.RequestedContract;
203 }
204 }
205
206 private Task Client_PetitionedContractResponseReceived(object Sender, ContractPetitionResponseEventArgs e)
207 {
208 lock (this.syncObj)
209 {
210 if (this.contractPetitions.TryGetValue(e.PetitionId, out TaskCompletionSource<ContractPetitionResponseEventArgs> Result))
211 Result.TrySetResult(e);
212 }
213
214 return Task.CompletedTask;
215 }
216
225 public Task<KeyValuePair<string, TemporaryStream>> GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
226 RemoteCertificateEventHandler RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
227 {
228 return this.GetTempStreamAsync(Uri, Certificate, RemoteCertificateValidator, defaultTimeoutMilliseconds, Headers);
229 }
230
240 public async Task<KeyValuePair<string, TemporaryStream>> GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
241 RemoteCertificateEventHandler RemoteCertificateValidator, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
242 {
243 Contract Contract = (Contract)await this.GetAsync(Uri, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
244 StringBuilder Xml = new StringBuilder();
245 Contract.Serialize(Xml, true, true, true, true, true, true, true);
246 byte[] Bin = Encoding.UTF8.GetBytes(Xml.ToString());
247
248 TemporaryStream Result = new TemporaryStream();
249 try
250 {
251 await Result.WriteAsync(Bin, 0, Bin.Length);
252 }
253 catch (Exception ex)
254 {
255 Result.Dispose();
256 ExceptionDispatchInfo.Capture(ex).Throw();
257 Result = null;
258 }
259
260 return new KeyValuePair<string, TemporaryStream>("application/xml; charset=utf-8", Result);
261 }
262 }
263}
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:1542
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...
async Task< KeyValuePair< string, TemporaryStream > > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) 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< KeyValuePair< string, TemporaryStream > > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, using a Uniform Resource Identifier (or Locator).
Task< object > GetAsync(Uri Uri, X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets a resource, using a Uniform Resource Identifier (or Locator).
async Task< object > GetAsync(Uri Uri, X509Certificate Certificate, RemoteCertificateEventHandler RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a resource, using a Uniform Resource Identifier (or Locator).
static int DefaultTimeoutMilliseconds
Default petition timeout, in milliseconds.
string[] UriSchemes
Supported URI schemes.
static string DefaultPurpose
Default purpose string.
Basic interface for Internet Content getters. A class implementing this interface and having a defaul...
delegate void RemoteCertificateEventHandler(object Sender, RemoteCertificateEventArgs e)
Delegate for remote certificate event handlers.
Grade
Grade enumeration
Definition: Grade.cs:7