Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
XmppOverHttp.cs
1using System;
2using System.Collections.Generic;
3using System.Runtime.ExceptionServices;
4using System.Text;
5using System.Threading.Tasks;
6using Waher.Content;
7using Waher.Events;
13
15{
20 {
22 private readonly object synchObj = new object();
23
29 : base(ResourceName)
30 {
31 }
32
36 public override bool HandlesSubPaths => true;
37
41 public override bool UserSessions => false;
42
46 public bool AllowsPOST => true;
47
54 public Task<string> GetUrl(EventHandlerAsync<PostBackEventArgs> Callback, object State)
55 {
56 byte[] Bin = Gateway.NextBytes(32);
57 string Key = Base64Url.Encode(Bin);
58
59 lock (this.synchObj)
60 {
61 if (this.queries is null)
62 {
63 this.queries = new Cache<string, KeyValuePair<EventHandlerAsync<PostBackEventArgs>, object>>(int.MaxValue, TimeSpan.FromMinutes(5), TimeSpan.FromMinutes(5), true);
64 this.queries.Removed += this.Queries_Removed;
65 }
66
67 this.queries[Key] = new KeyValuePair<EventHandlerAsync<PostBackEventArgs>, object>(Callback, State);
68 this.queries[string.Empty] = new KeyValuePair<EventHandlerAsync<PostBackEventArgs>, object>(null, null); // Keep cache active to avoid multiple recreation when a series of requests occur in sequence.
69 }
70
71 StringBuilder Url = new StringBuilder();
72 int[] Ports = Gateway.HttpServer.OpenHttpsPorts;
73
74 Url.Append("https://");
75 Url.Append(Gateway.Domain);
76
77 if (Array.IndexOf(Ports, HttpServer.DefaultHttpsPort) < 0 && Ports.Length > 0)
78 {
79 Url.Append(':');
80 Url.Append(Ports[0]);
81 }
82
83 Url.Append(this.ResourceName);
84 Url.Append("/");
85 Url.Append(Key);
86
87 return Task.FromResult(Url.ToString());
88 }
89
90 private Task Queries_Removed(object Sender, CacheItemEventArgs<string, KeyValuePair<EventHandlerAsync<PostBackEventArgs>, object>> e)
91 {
92 lock (this.synchObj)
93 {
94 if (!(this.queries is null) && this.queries.Count == 0)
95 {
96 this.queries.Dispose();
97 this.queries = null;
98 }
99 }
100
101 return Task.CompletedTask;
102 }
103
110 public async Task POST(HttpRequest Request, HttpResponse Response)
111 {
112 if (!Request.HasData)
113 throw new BadRequestException("Missing data.");
114
115 string ContentType = Request.Header.ContentType?.Value;
116 if (string.IsNullOrEmpty(ContentType) || Array.IndexOf(Content.Binary.BinaryCodec.BinaryContentTypes, ContentType) < 0)
117 throw new UnsupportedMediaTypeException("Expected Binary data.");
118
119 string From = Request.Header.From?.Value;
120 if (string.IsNullOrEmpty(From))
121 throw new BadRequestException("No From header.");
122
123 string To = Request.Header["Origin"];
124 if (string.IsNullOrEmpty(To))
125 throw new BadRequestException("No Origin header.");
126
127 string Referer = Request.Header.Referer?.Value;
128 string EndpointReference;
129 string SymmetricCipherReference;
130 int i;
131
132 if (!string.IsNullOrEmpty(Referer) && (i = Referer.IndexOf(':')) >= 0)
133 {
134 EndpointReference = Referer.Substring(0, i);
135 SymmetricCipherReference = Referer.Substring(i + 1);
136 }
137 else
138 {
139 EndpointReference = string.Empty;
140 SymmetricCipherReference = string.Empty;
141 }
142
143 string Key = Request.SubPath;
144 if (string.IsNullOrEmpty(Key))
145 throw new BadRequestException("No sub-path provided.");
146
147 Key = Key.Substring(1);
148
149 KeyValuePair<EventHandlerAsync<PostBackEventArgs>, object> Rec;
150
151 lock (this.synchObj)
152 {
153 if (this.queries is null || !this.queries.TryGetValue(Key, out Rec))
154 throw new NotFoundException("Resource sub-key not found.");
155 }
156
157 Request.DataStream.Position = 0;
158
159 TemporaryStream Data = new TemporaryStream();
160 try
161 {
162 await Request.DataStream.CopyToAsync(Data);
163 Data.Position = 0;
164 Task _ = Task.Run(() => this.Process(Data, Response, Rec.Key, Rec.Value, From, To, EndpointReference, SymmetricCipherReference));
165 }
166 catch (Exception ex)
167 {
168 Data.Dispose();
169 ExceptionDispatchInfo.Capture(ex).Throw();
170 }
171 }
172
173 private async Task Process(TemporaryStream Data, HttpResponse Response, EventHandlerAsync<PostBackEventArgs> Callback, object State,
174 string From, string To, string EndpointReference, string SymmetricCipherReference)
175 {
176 try
177 {
178 // Permit callback to raise exceptions.
179 await Callback(this, new PostBackEventArgs(Data, State, From, To, EndpointReference, SymmetricCipherReference));
180
181 Response.StatusCode = 200;
182 await Response.SendResponse();
183 }
184 catch (Exception ex)
185 {
186 await Response.SendResponse(ex);
187 }
188 finally
189 {
190 Data.Dispose();
191 await Response.DisposeAsync();
192 }
193 }
194
195 }
196}
Static class that does BASE64URL encoding (using URL and filename safe alphabet), as defined in RFC46...
Definition: Base64Url.cs:11
static string Encode(byte[] Data)
Converts a binary block of data to a Base64URL-encoded string.
Definition: Base64Url.cs:48
Static class managing the runtime environment of the IoT Gateway.
Definition: Gateway.cs:126
static CaseInsensitiveString Domain
Domain name.
Definition: Gateway.cs:2354
static HttpServer HttpServer
HTTP Server
Definition: Gateway.cs:3299
static byte[] NextBytes(int NrBytes)
Generates an array of random bytes.
Definition: Gateway.cs:3534
The request could not be understood by the server due to malformed syntax. The client SHOULD NOT repe...
Base class for all asynchronous HTTP resources. An asynchronous resource responds outside of the meth...
HttpFieldContentType ContentType
Content-Type HTTP Field header. (RFC 2616, §14.17)
Definition: HttpHeader.cs:265
HttpFieldReferer Referer
Referer HTTP Field header. (RFC 2616, §14.36)
HttpFieldFrom From
From HTTP Field header. (RFC 2616, §14.22)
Represents an HTTP request.
Definition: HttpRequest.cs:18
Stream DataStream
Data stream, if data is available, or null if data is not available.
Definition: HttpRequest.cs:139
HttpRequestHeader Header
Request header.
Definition: HttpRequest.cs:134
bool HasData
If the request has data.
Definition: HttpRequest.cs:74
string SubPath
Sub-path. If a resource is found handling the request, this property contains the trailing sub-path o...
Definition: HttpRequest.cs:146
string ResourceName
Name of resource.
Represets a response of an HTTP client request.
Definition: HttpResponse.cs:21
async Task DisposeAsync()
Closes the connection and disposes of all resources.
async Task SendResponse()
Sends the response back to the client. If the resource is synchronous, there's no need to call this m...
Implements an HTTP server.
Definition: HttpServer.cs:36
int[] OpenHttpsPorts
HTTPS Ports successfully opened.
Definition: HttpServer.cs:704
const int DefaultHttpsPort
Default HTTPS port (443).
Definition: HttpServer.cs:45
The server has not found anything matching the Request-URI. No indication is given of whether the con...
The server is refusing to service the request because the entity of the request is in a format not su...
Event arguments for post-back events or callbacks.
Implements an in-memory cache.
Definition: Cache.cs:15
void Dispose()
IDisposable.Dispose
Definition: Cache.cs:74
int Count
Number of items in cache
Definition: Cache.cs:229
bool TryGetValue(KeyType Key, out ValueType Value)
Tries to get a value from the cache.
Definition: Cache.cs:203
Event arguments for cache item removal events.
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...
Allows senders to send XMPP stanzas over HTTP POST.
Definition: XmppOverHttp.cs:20
bool AllowsPOST
If the POST method is allowed.
Definition: XmppOverHttp.cs:46
override bool UserSessions
If the resource uses user sessions.
Definition: XmppOverHttp.cs:41
override bool HandlesSubPaths
If the resource handles sub-paths.
Definition: XmppOverHttp.cs:36
XmppOverHttp(string ResourceName)
Allows senders to send XMPP stanzas over HTTP POST.
Definition: XmppOverHttp.cs:28
async Task POST(HttpRequest Request, HttpResponse Response)
Executes the POST method on the resource.
Task< string > GetUrl(EventHandlerAsync< PostBackEventArgs > Callback, object State)
Gets a Post-back URL
Definition: XmppOverHttp.cs:54
POST Interface for HTTP resources.
Interface for HTTP(S) Post-back resources. These can be used to allow HTTPX servers to HTTP POST back...