Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'sdks/wasm/DebuggerTestSuite/DevToolsClient.cs')
-rw-r--r--sdks/wasm/DebuggerTestSuite/DevToolsClient.cs297
1 files changed, 161 insertions, 136 deletions
diff --git a/sdks/wasm/DebuggerTestSuite/DevToolsClient.cs b/sdks/wasm/DebuggerTestSuite/DevToolsClient.cs
index 4fb0fd0f866..5caae92eee1 100644
--- a/sdks/wasm/DebuggerTestSuite/DevToolsClient.cs
+++ b/sdks/wasm/DebuggerTestSuite/DevToolsClient.cs
@@ -1,142 +1,167 @@
-using System;
-using System.Threading.Tasks;
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
-using System.Net.WebSockets;
-using System.Threading;
+using System;
+using System.Collections.Generic;
using System.IO;
+using System.Net.WebSockets;
using System.Text;
-using System.Collections.Generic;
+using System.Threading;
+using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
-namespace WebAssembly.Net.Debugging {
- internal class DevToolsClient: IDisposable {
- ClientWebSocket socket;
- List<Task> pending_ops = new List<Task> ();
- TaskCompletionSource<bool> side_exit = new TaskCompletionSource<bool> ();
- List<byte []> pending_writes = new List<byte []> ();
- Task current_write;
- readonly ILogger logger;
-
- public DevToolsClient (ILogger logger) {
- this.logger = logger;
- }
-
- ~DevToolsClient() {
- Dispose(false);
- }
-
- public void Dispose() {
- Dispose(true);
- }
-
- public async Task Close (CancellationToken cancellationToken)
- {
- if (socket.State == WebSocketState.Open)
- await socket.CloseOutputAsync (WebSocketCloseStatus.NormalClosure, "Closing", cancellationToken);
- }
-
- protected virtual void Dispose (bool disposing) {
- if (disposing)
- socket.Dispose ();
- }
-
- Task Pump (Task task, CancellationToken token)
- {
- if (task != current_write)
- return null;
- current_write = null;
-
- pending_writes.RemoveAt (0);
-
- if (pending_writes.Count > 0) {
- current_write = socket.SendAsync (new ArraySegment<byte> (pending_writes [0]), WebSocketMessageType.Text, true, token);
- return current_write;
- }
- return null;
- }
-
- async Task<string> ReadOne (CancellationToken token)
- {
- byte [] buff = new byte [4000];
- var mem = new MemoryStream ();
- while (true) {
- var result = await this.socket.ReceiveAsync (new ArraySegment<byte> (buff), token);
- if (result.MessageType == WebSocketMessageType.Close) {
- return null;
- }
-
- if (result.EndOfMessage) {
- mem.Write (buff, 0, result.Count);
- return Encoding.UTF8.GetString (mem.GetBuffer (), 0, (int)mem.Length);
- } else {
- mem.Write (buff, 0, result.Count);
- }
- }
- }
-
- protected void Send (byte [] bytes, CancellationToken token)
- {
- pending_writes.Add (bytes);
- if (pending_writes.Count == 1) {
- if (current_write != null)
- throw new Exception ("Internal state is bad. current_write must be null if there are no pending writes");
-
- current_write = socket.SendAsync (new ArraySegment<byte> (bytes), WebSocketMessageType.Text, true, token);
- pending_ops.Add (current_write);
- }
- }
-
- async Task MarkCompleteAfterward (Func<CancellationToken, Task> send, CancellationToken token)
- {
- try {
- await send(token);
- side_exit.SetResult (true);
- } catch (Exception e) {
- side_exit.SetException (e);
- }
- }
-
- protected async Task<bool> ConnectWithMainLoops(
- Uri uri,
- Func<string, CancellationToken, Task> receive,
- Func<CancellationToken, Task> send,
- CancellationToken token) {
-
- logger.LogDebug ("connecting to {0}", uri);
- this.socket = new ClientWebSocket ();
- this.socket.Options.KeepAliveInterval = Timeout.InfiniteTimeSpan;
-
- await this.socket.ConnectAsync (uri, token);
- pending_ops.Add (ReadOne (token));
- pending_ops.Add (side_exit.Task);
- pending_ops.Add (MarkCompleteAfterward (send, token));
-
- while (!token.IsCancellationRequested) {
- var task = await Task.WhenAny (pending_ops);
- if (task == pending_ops [0]) { //pending_ops[0] is for message reading
- var msg = ((Task<string>)task).Result;
- pending_ops [0] = ReadOne (token);
- Task tsk = receive (msg, token);
- if (tsk != null)
- pending_ops.Add (tsk);
- } else if (task == pending_ops [1]) {
- var res = ((Task<bool>)task).Result;
- //it might not throw if exiting successfull
- return res;
- } else { //must be a background task
- pending_ops.Remove (task);
- var tsk = Pump (task, token);
- if (tsk != null)
- pending_ops.Add (tsk);
- }
- }
-
- return false;
- }
-
- protected virtual void Log (string priority, string msg)
- {
- //
- }
- }
+namespace Microsoft.WebAssembly.Diagnostics
+{
+ internal class DevToolsClient : IDisposable
+ {
+ ClientWebSocket socket;
+ List<Task> pending_ops = new List<Task>();
+ TaskCompletionSource<bool> side_exit = new TaskCompletionSource<bool>();
+ List<byte[]> pending_writes = new List<byte[]>();
+ Task current_write;
+ readonly ILogger logger;
+
+ public DevToolsClient(ILogger logger)
+ {
+ this.logger = logger;
+ }
+
+ ~DevToolsClient()
+ {
+ Dispose(false);
+ }
+
+ public void Dispose()
+ {
+ Dispose(true);
+ }
+
+ public async Task Close(CancellationToken cancellationToken)
+ {
+ if (socket.State == WebSocketState.Open)
+ await socket.CloseOutputAsync(WebSocketCloseStatus.NormalClosure, "Closing", cancellationToken);
+ }
+
+ protected virtual void Dispose(bool disposing)
+ {
+ if (disposing)
+ socket.Dispose();
+ }
+
+ Task Pump(Task task, CancellationToken token)
+ {
+ if (task != current_write)
+ return null;
+ current_write = null;
+
+ pending_writes.RemoveAt(0);
+
+ if (pending_writes.Count > 0)
+ {
+ current_write = socket.SendAsync(new ArraySegment<byte>(pending_writes[0]), WebSocketMessageType.Text, true, token);
+ return current_write;
+ }
+ return null;
+ }
+
+ async Task<string> ReadOne(CancellationToken token)
+ {
+ byte[] buff = new byte[4000];
+ var mem = new MemoryStream();
+ while (true)
+ {
+ var result = await this.socket.ReceiveAsync(new ArraySegment<byte>(buff), token);
+ if (result.MessageType == WebSocketMessageType.Close)
+ {
+ return null;
+ }
+
+ if (result.EndOfMessage)
+ {
+ mem.Write(buff, 0, result.Count);
+ return Encoding.UTF8.GetString(mem.GetBuffer(), 0, (int)mem.Length);
+ }
+ else
+ {
+ mem.Write(buff, 0, result.Count);
+ }
+ }
+ }
+
+ protected void Send(byte[] bytes, CancellationToken token)
+ {
+ pending_writes.Add(bytes);
+ if (pending_writes.Count == 1)
+ {
+ if (current_write != null)
+ throw new Exception("Internal state is bad. current_write must be null if there are no pending writes");
+
+ current_write = socket.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, token);
+ pending_ops.Add(current_write);
+ }
+ }
+
+ async Task MarkCompleteAfterward(Func<CancellationToken, Task> send, CancellationToken token)
+ {
+ try
+ {
+ await send(token);
+ side_exit.SetResult(true);
+ }
+ catch (Exception e)
+ {
+ side_exit.SetException(e);
+ }
+ }
+
+ protected async Task<bool> ConnectWithMainLoops(
+ Uri uri,
+ Func<string, CancellationToken, Task> receive,
+ Func<CancellationToken, Task> send,
+ CancellationToken token)
+ {
+
+ logger.LogDebug("connecting to {0}", uri);
+ this.socket = new ClientWebSocket();
+ this.socket.Options.KeepAliveInterval = Timeout.InfiniteTimeSpan;
+
+ await this.socket.ConnectAsync(uri, token);
+ pending_ops.Add(ReadOne(token));
+ pending_ops.Add(side_exit.Task);
+ pending_ops.Add(MarkCompleteAfterward(send, token));
+
+ while (!token.IsCancellationRequested)
+ {
+ var task = await Task.WhenAny(pending_ops);
+ if (task == pending_ops[0])
+ { //pending_ops[0] is for message reading
+ var msg = ((Task<string>)task).Result;
+ pending_ops[0] = ReadOne(token);
+ Task tsk = receive(msg, token);
+ if (tsk != null)
+ pending_ops.Add(tsk);
+ }
+ else if (task == pending_ops[1])
+ {
+ var res = ((Task<bool>)task).Result;
+ //it might not throw if exiting successfull
+ return res;
+ }
+ else
+ { //must be a background task
+ pending_ops.Remove(task);
+ var tsk = Pump(task, token);
+ if (tsk != null)
+ pending_ops.Add(tsk);
+ }
+ }
+
+ return false;
+ }
+
+ protected virtual void Log(string priority, string msg)
+ {
+ //
+ }
+ }
}