Survivalcraft API 1.8.2.3 v1.8.2.3
Survivalcraft 2.4
载入中...
搜索中...
未找到
WebManager.cs
浏览该文件的文档.
1#if ANDROID
2using Android.OS;
3using Android.Net;
4#elif WINDOWS
5using System.Runtime.InteropServices;
6#elif LINUX
7using System.Net.NetworkInformation;
8#endif
9using System.Net;
10using System.Net.Http;
11using System.Text;
12using Engine;
13using OperationCanceledException = System.OperationCanceledException;
14using Uri = System.Uri;
15
16namespace Game {
17 public static class WebManager {
18 public class ProgressHttpContent : HttpContent {
19 public Stream m_sourceStream;
20
22
23 public ProgressHttpContent(Stream sourceStream, CancellableProgress progress) {
24 m_sourceStream = sourceStream;
25 m_progress = progress ?? new CancellableProgress();
26 }
27
28 protected override bool TryComputeLength(out long length) {
29 length = m_sourceStream.Length;
30 return true;
31 }
32
33 protected override async Task SerializeToStreamAsync(Stream targetStream, TransportContext context) {
34 byte[] buffer = new byte[8192];
35 long written = 0L;
36 m_progress.Total = m_sourceStream.Length;
37 while (true) {
38 int read = await m_sourceStream.ReadAsync(buffer, 0, buffer.Length, m_progress.CancellationToken);
39 if (read <= 0) {
40 break;
41 }
42 await targetStream.WriteAsync(buffer.AsMemory(0, read), m_progress.CancellationToken);
43 written += read;
44 m_progress.Completed = written;
45 }
46 }
47 }
48#if WINDOWS
49 [DllImport("wininet.dll")]
50 internal static extern bool InternetGetConnectedState(out int Description, int ReservedValue);
51#elif ANDROID
52#pragma warning disable CA1416
53#pragma warning disable CA1422
54 internal static ConnectivityManager m_connectivityManager { get; } = GetConnectivityManager();
55#endif
56 public static bool IsInternetConnectionAvailable() {
57 try {
58#if ANDROID
59 switch (Build.VERSION.SdkInt) {
60 case >= (BuildVersionCodes)29:
61 return m_connectivityManager?.GetNetworkCapabilities(m_connectivityManager.ActiveNetwork)
62 ?.HasCapability(NetCapability.Validated)
63 ?? false;
64 case >= (BuildVersionCodes)21: return m_connectivityManager?.ActiveNetworkInfo?.IsConnected ?? false;
65 default: return true;
66 }
67#elif WINDOWS
68 return InternetGetConnectedState(out int _, 0);
69#elif LINUX
70 return NetworkInterface.GetIsNetworkAvailable();
71#else
72 return true;
73#endif
74 }
75 catch (Exception e) {
76 Log.Warning(ExceptionManager.MakeFullErrorMessage("Could not check internet connection availability.", e));
77 }
78 return true;
79 }
80
81#if ANDROID
82 static ConnectivityManager GetConnectivityManager() => Build.VERSION.SdkInt >= (BuildVersionCodes)21
83 ? (ConnectivityManager)Window.Activity.GetSystemService("connectivity")
84 : null;
85#pragma warning restore CA1416
86#pragma warning restore CA1422
87#endif
88
89 public static void Get(string address,
90 Dictionary<string, string> parameters,
91 Dictionary<string, string> headers,
92 CancellableProgress progress,
93 Action<byte[]> success,
94 Action<Exception> failure) {
95 MemoryStream targetStream;
96 Exception e = null;
97 Task.Run(
98 async delegate {
99 Uri requestUri = parameters != null && parameters.Count > 0
100 ? new Uri($"{address}?{UrlParametersToString(parameters)}")
101 : new Uri(address);
102 try {
103 progress ??= new CancellableProgress();
105 throw new InvalidOperationException("Internet connection is unavailable.");
106 }
107 using (HttpClient client = new()) {
108 client.DefaultRequestHeaders.Referrer = new Uri(address);
109 if (headers != null) {
110 foreach (KeyValuePair<string, string> header in headers) {
111 client.DefaultRequestHeaders.Add(header.Key, header.Value);
112 }
113 }
114 HttpResponseMessage responseMessage = await client.GetAsync(
115 requestUri,
116 HttpCompletionOption.ResponseHeadersRead,
117 progress.CancellationToken
118 );
119 await VerifyResponse(responseMessage);
120 progress.Total = responseMessage.Content.Headers.ContentLength ?? 0;
121 await using Stream responseStream = await responseMessage.Content.ReadAsStreamAsync();
122 targetStream = new MemoryStream();
123 try {
124 long written = 0L;
125 byte[] buffer = new byte[8192];
126 while (true) {
127 int read = await responseStream.ReadAsync(buffer, progress.CancellationToken);
128 if (read == 0) {
129 break;
130 }
131 await targetStream.WriteAsync(buffer.AsMemory(0, read), progress.CancellationToken);
132 written += read;
133 progress.Completed = written;
134 }
135 if (success != null) {
137 delegate {
138 // ReSharper disable AccessToDisposedClosure
139 success(targetStream?.ToArray());
140 // ReSharper restore AccessToDisposedClosure
141 }
142 );
143 }
144 }
145 finally {
146 ((IDisposable)targetStream)?.Dispose();
147 }
148 }
149 }
150 catch (Exception ex) {
151 Log.Warning($"{e.Message}:\nThe connection is unavailable. Url: {requestUri}");
152 if (failure != null) {
153 Dispatcher.Dispatch(delegate { failure(ex); });
154 }
155 }
156 }
157 );
158 }
159
160 public static void Put(string address,
161 Dictionary<string, string> parameters,
162 Dictionary<string, string> headers,
163 Stream data,
164 CancellableProgress progress,
165 Action<byte[]> success,
166 Action<Exception> failure) {
167 PutOrPost(
168 false,
169 address,
170 parameters,
171 headers,
172 data,
173 progress,
174 success,
175 failure
176 );
177 }
178
179 public static void Post(string address,
180 Dictionary<string, string> parameters,
181 Dictionary<string, string> headers,
182 Stream data,
183 CancellableProgress progress,
184 Action<byte[]> success,
185 Action<Exception> failure) {
186 PutOrPost(
187 true,
188 address,
189 parameters,
190 headers,
191 data,
192 progress,
193 success,
194 failure
195 );
196 }
197
198 public static async Task<byte[]> GetAsync(string address,
199 Dictionary<string, string> parameters = null,
200 Dictionary<string, string> headers = null,
201 CancellableProgress progress = null) {
202 progress ??= new CancellableProgress();
203 Uri requestUri = parameters != null && parameters.Count > 0
204 ? new Uri($"{address}?{UrlParametersToString(parameters)}")
205 : new Uri(address);
207 throw new InvalidOperationException("Internet connection is unavailable.");
208 }
209 using HttpClient client = new();
210 client.DefaultRequestHeaders.Referrer = new Uri(address);
211 if (headers != null) {
212 foreach (KeyValuePair<string, string> header in headers) {
213 client.DefaultRequestHeaders.Add(header.Key, header.Value);
214 }
215 }
216 using HttpResponseMessage responseMessage = await client.GetAsync(
217 requestUri,
218 HttpCompletionOption.ResponseHeadersRead,
219 progress.CancellationToken
220 );
221 await VerifyResponse(responseMessage);
222 progress.Total = responseMessage.Content.Headers.ContentLength ?? 0;
223 await using Stream responseStream = await responseMessage.Content.ReadAsStreamAsync();
224 using MemoryStream targetStream = new();
225 long written = 0L;
226 byte[] buffer = new byte[8192];
227 while (true) {
228 int read = await responseStream.ReadAsync(buffer.AsMemory(0, buffer.Length), progress.CancellationToken);
229 if (read <= 0) {
230 break;
231 }
232 await targetStream.WriteAsync(buffer.AsMemory(0, read), progress.CancellationToken);
233 written += read;
234 progress.Completed = written;
235 }
236 return targetStream.ToArray();
237 }
238
239 public static async Task<byte[]> PutAsync(string address,
240 Dictionary<string, string> parameters,
241 Dictionary<string, string> headers,
242 Stream data,
243 CancellableProgress progress = null) {
244 return await PutOrPostAAsync(
245 false,
246 address,
247 parameters,
248 headers,
249 data,
250 progress
251 );
252 }
253
254 public static async Task<byte[]> PostAsync(string address,
255 Dictionary<string, string> parameters,
256 Dictionary<string, string> headers,
257 Stream data,
258 CancellableProgress progress = null) {
259 return await PutOrPostAAsync(
260 true,
261 address,
262 parameters,
263 headers,
264 data,
265 progress
266 );
267 }
268
269 public static string UrlParametersToString(Dictionary<string, string> values) {
270 StringBuilder stringBuilder = new();
271 string value = string.Empty;
272 foreach (KeyValuePair<string, string> value2 in values) {
273 stringBuilder.Append(value);
274 value = "&";
275 stringBuilder.Append(Uri.EscapeDataString(value2.Key));
276 stringBuilder.Append('=');
277 if (!string.IsNullOrEmpty(value2.Value)) {
278 stringBuilder.Append(Uri.EscapeDataString(value2.Value));
279 }
280 }
281 return stringBuilder.ToString();
282 }
283
284 public static byte[] UrlParametersToBytes(Dictionary<string, string> values) => Encoding.UTF8.GetBytes(UrlParametersToString(values));
285
286 public static MemoryStream UrlParametersToStream(Dictionary<string, string> values) =>
287 new(Encoding.UTF8.GetBytes(UrlParametersToString(values)));
288
289 public static Dictionary<string, string> UrlParametersFromString(string s) {
290 Dictionary<string, string> dictionary = new();
291 string[] array = s.Split('&', StringSplitOptions.RemoveEmptyEntries);
292 for (int i = 0; i < array.Length; i++) {
293 string[] array2 = Uri.UnescapeDataString(array[i]).Split('=');
294 if (array2.Length == 2) {
295 dictionary[array2[0]] = array2[1];
296 }
297 }
298 return dictionary;
299 }
300
301 public static Dictionary<string, string> UrlParametersFromBytes(byte[] bytes) =>
302 UrlParametersFromString(Encoding.UTF8.GetString(bytes, 0, bytes.Length));
303
304 public static void PutOrPost(bool isPost,
305 string address,
306 Dictionary<string, string> parameters,
307 Dictionary<string, string> headers,
308 Stream data,
309 CancellableProgress progress,
310 Action<byte[]> success,
311 Action<Exception> failure) {
312 Task.Run(
313 async delegate {
314 Uri requestUri = parameters != null && parameters.Count > 0
315 ? new Uri($"{address}?{UrlParametersToString(parameters)}")
316 : new Uri(address);
317 try {
319 throw new InvalidOperationException("Internet connection is unavailable.");
320 }
321 using HttpClient client = new();
322 Dictionary<string, string> dictionary = new();
323 if (headers != null) {
324 foreach (KeyValuePair<string, string> header in headers) {
325 if (!client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value)) {
326 dictionary.Add(header.Key, header.Value);
327 }
328 }
329 }
330#if !ANDROID
331 ProgressHttpContent httpContent = new(data, progress);
332#else
333 HttpContent httpContent = progress != null ? new ProgressHttpContent(data, progress) : new StreamContent(data);
334#endif
335 foreach (KeyValuePair<string, string> item in dictionary) {
336 httpContent.Headers.Add(item.Key, item.Value);
337 }
338#if !ANDROID
339 HttpResponseMessage responseMessage = isPost
340 ? await client.PostAsync(requestUri, httpContent, progress.CancellationToken)
341 : await client.PutAsync(requestUri, httpContent, progress.CancellationToken);
342#else
343 HttpResponseMessage responseMessage = isPost ?
344 progress == null
345 ? await client.PostAsync(requestUri, httpContent)
346 : await client.PostAsync(requestUri, httpContent, progress.CancellationToken) :
347 progress == null ? await client.PutAsync(requestUri, httpContent) :
348 await client.PutAsync(requestUri, httpContent, progress.CancellationToken);
349#endif
350 await VerifyResponse(responseMessage);
351 byte[] responseData = await responseMessage.Content.ReadAsByteArrayAsync();
352 if (success != null) {
353 Dispatcher.Dispatch(delegate { success(responseData); });
354 }
355 }
356 catch (Exception e) {
357 Log.Warning($"{e.Message}:\nThe connection is unavailable. Url: {requestUri}");
358 if (failure != null) {
359 Dispatcher.Dispatch(delegate { failure(e); });
360 }
361 }
362 }
363 );
364 }
365
366 public static async Task<byte[]> PutOrPostAAsync(bool isPost,
367 string address,
368 Dictionary<string, string> parameters,
369 Dictionary<string, string> headers,
370 Stream data,
371 CancellableProgress progress) {
372 Uri requestUri = parameters != null && parameters.Count > 0
373 ? new Uri($"{address}?{UrlParametersToString(parameters)}")
374 : new Uri(address);
376 throw new InvalidOperationException("Internet connection is unavailable.");
377 }
378 using HttpClient client = new();
379 Dictionary<string, string> dictionary = new();
380 if (headers != null) {
381 foreach (KeyValuePair<string, string> header in headers) {
382 if (!client.DefaultRequestHeaders.TryAddWithoutValidation(header.Key, header.Value)) {
383 dictionary.Add(header.Key, header.Value);
384 }
385 }
386 }
387#if !ANDROID
388 ProgressHttpContent httpContent = new(data, progress);
389#else
390 HttpContent httpContent = progress != null ? new ProgressHttpContent(data, progress) : new StreamContent(data);
391#endif
392 foreach (KeyValuePair<string, string> item in dictionary) {
393 httpContent.Headers.Add(item.Key, item.Value);
394 }
395#if !ANDROID
396 HttpResponseMessage responseMessage = isPost
397 ? await client.PostAsync(requestUri, httpContent, progress.CancellationToken)
398 : await client.PutAsync(requestUri, httpContent, progress.CancellationToken);
399#else
400 HttpResponseMessage responseMessage = isPost ?
401 progress == null
402 ? await client.PostAsync(requestUri, httpContent)
403 : await client.PostAsync(requestUri, httpContent, progress.CancellationToken) :
404 progress == null ? await client.PutAsync(requestUri, httpContent) :
405 await client.PutAsync(requestUri, httpContent, progress.CancellationToken);
406#endif
407 await VerifyResponse(responseMessage);
408 byte[] responseData = await responseMessage.Content.ReadAsByteArrayAsync();
409 return responseData;
410 }
411
412 public static async Task VerifyResponse(HttpResponseMessage message) {
413 if (!message.IsSuccessStatusCode) {
414 string responseText = string.Empty;
415 try {
416 responseText = await message.Content.ReadAsStringAsync();
417 }
418 catch {
419 // ignored
420 }
421 throw new InvalidOperationException($"{message.StatusCode} ({(int)message.StatusCode})\n{responseText}");
422 }
423 }
424 }
425}
Android.Net.Uri Uri
System.OperationCanceledException OperationCanceledException
static void Dispatch(Action action, bool waitUntilCompleted=false)
static void Warning(object message)
定义 Log.cs:68
readonly CancellationToken CancellationToken
static string MakeFullErrorMessage(Exception e)
override bool TryComputeLength(out long length)
override async Task SerializeToStreamAsync(Stream targetStream, TransportContext context)
ProgressHttpContent(Stream sourceStream, CancellableProgress progress)
static void Post(string address, Dictionary< string, string > parameters, Dictionary< string, string > headers, Stream data, CancellableProgress progress, Action< byte[]> success, Action< Exception > failure)
static async Task VerifyResponse(HttpResponseMessage message)
static async Task< byte[]> PostAsync(string address, Dictionary< string, string > parameters, Dictionary< string, string > headers, Stream data, CancellableProgress progress=null)
static bool IsInternetConnectionAvailable()
static byte[] UrlParametersToBytes(Dictionary< string, string > values)
static void Put(string address, Dictionary< string, string > parameters, Dictionary< string, string > headers, Stream data, CancellableProgress progress, Action< byte[]> success, Action< Exception > failure)
static void PutOrPost(bool isPost, string address, Dictionary< string, string > parameters, Dictionary< string, string > headers, Stream data, CancellableProgress progress, Action< byte[]> success, Action< Exception > failure)
static Dictionary< string, string > UrlParametersFromBytes(byte[] bytes)
static MemoryStream UrlParametersToStream(Dictionary< string, string > values)
static void Get(string address, Dictionary< string, string > parameters, Dictionary< string, string > headers, CancellableProgress progress, Action< byte[]> success, Action< Exception > failure)
static async Task< byte[]> GetAsync(string address, Dictionary< string, string > parameters=null, Dictionary< string, string > headers=null, CancellableProgress progress=null)
static Dictionary< string, string > UrlParametersFromString(string s)
static async Task< byte[]> PutAsync(string address, Dictionary< string, string > parameters, Dictionary< string, string > headers, Stream data, CancellableProgress progress=null)
static async Task< byte[]> PutOrPostAAsync(bool isPost, string address, Dictionary< string, string > parameters, Dictionary< string, string > headers, Stream data, CancellableProgress progress)
static string UrlParametersToString(Dictionary< string, string > values)