Skip to content

Commit bc90abd

Browse files
authored
Новый протокол дебаггера, совместимый с net8 и старыми версиями движка
2 parents 346ab70 + c2e4469 commit bc90abd

45 files changed

Lines changed: 1470 additions & 418 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/OneScript.DebugProtocol/Abstractions/ICommunicationChannel.cs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,5 +17,7 @@ public interface ICommunicationChannel : IDisposable
1717

1818
object Read();
1919

20+
bool Connected { get; }
21+
2022
}
2123
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*----------------------------------------------------------
2+
This Source Code Form is subject to the terms of the
3+
Mozilla Public License, v.2.0. If a copy of the MPL
4+
was not distributed with this file, You can obtain one
5+
at http://mozilla.org/MPL/2.0/.
6+
----------------------------------------------------------*/
7+
using System;
8+
9+
namespace OneScript.DebugProtocol
10+
{
11+
[Serializable]
12+
public class ExceptionBreakpointFilter
13+
{
14+
public string Id { get; set; }
15+
16+
public string Condition { get; set; }
17+
}
18+
}

src/OneScript.DebugProtocol/IDebuggerService.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ This Source Code Form is subject to the terms of the
55
at http://mozilla.org/MPL/2.0/.
66
----------------------------------------------------------*/
77

8+
using System;
9+
810
namespace OneScript.DebugProtocol
911
{
1012
/// <summary>
@@ -19,10 +21,17 @@ public interface IDebuggerService
1921
void Execute(int threadId);
2022

2123
/// <summary>
22-
/// Добавление фильтров точек останова для исплючений
24+
/// Добавление фильтров точек останова для исключений
2325
/// </summary>
2426
/// <param name="filters"></param>
27+
[Obsolete("Используется только для совместимости нового адаптера со старыми binary версиями движка")]
2528
void SetMachineExceptionBreakpoints((string Id, string Condition)[] filters);
29+
30+
/// <summary>
31+
/// Добавление фильтров точек останова для исключений
32+
/// </summary>
33+
/// <param name="filters"></param>
34+
void SetExceptionBreakpoints(ExceptionBreakpointFilter[] filters);
2635

2736
/// <summary>
2837
/// Установка точек остановки

src/OneScript.DebugProtocol/OneScript.DebugProtocol.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,6 @@
1717
</PropertyGroup>
1818

1919
<ItemGroup>
20-
<Folder Include="Properties\" />
20+
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
2121
</ItemGroup>
2222
</Project>

src/OneScript.DebugProtocol/StackFrame.cs

Lines changed: 38 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,11 @@ This Source Code Form is subject to the terms of the
88
using System.Collections;
99
using System.Collections.Generic;
1010
using System.Runtime.Serialization;
11+
using Newtonsoft.Json;
1112

1213
namespace OneScript.DebugProtocol
1314
{
14-
[DataContract, Serializable]
15+
[DataContract, JsonObject, Serializable]
1516
public class StackFrame : IVariableLocator
1617
{
1718
[DataMember]
@@ -35,30 +36,30 @@ int IVariableLocator.Count
3536
{
3637
get
3738
{
38-
ThrowIfNoVariables();
39-
39+
if (Variables == null)
40+
return 0;
41+
4042
return Variables.Length;
4143
}
4244
}
4345

44-
private void ThrowIfNoVariables()
45-
{
46-
if (Variables == null)
47-
throw new InvalidOperationException("No variables aquired yet");
48-
}
49-
5046
Variable IVariableLocator.this[int index]
5147
{
5248
get
5349
{
54-
ThrowIfNoVariables();
50+
if (Variables == null)
51+
throw new ArgumentOutOfRangeException();
52+
5553
return Variables[index];
5654
}
5755
}
5856

5957
IEnumerator<Variable> IEnumerable<Variable>.GetEnumerator()
6058
{
61-
ThrowIfNoVariables();
59+
if (Variables == null)
60+
{
61+
return EmptyEnumerator<Variable>.Instance;
62+
}
6263

6364
return ((IEnumerable<Variable>)Variables).GetEnumerator();
6465
}
@@ -81,4 +82,30 @@ public IVariableLocator CreateChildLocator(int variableIndex)
8182
return new VariableLocator(ThreadId, Index, variableIndex);
8283
}
8384
}
85+
86+
internal class EmptyEnumerator<T> : IEnumerator<T>
87+
{
88+
public static EmptyEnumerator<T> Instance { get; } = new EmptyEnumerator<T>();
89+
90+
private EmptyEnumerator()
91+
{
92+
}
93+
94+
public bool MoveNext()
95+
{
96+
return false;
97+
}
98+
99+
public void Reset()
100+
{
101+
}
102+
103+
public T Current { get; } = default;
104+
105+
object IEnumerator.Current => Current;
106+
107+
public void Dispose()
108+
{
109+
}
110+
}
84111
}

src/OneScript.DebugProtocol/TcpServer/BinaryChannel.cs

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ This Source Code Form is subject to the terms of the
55
at http://mozilla.org/MPL/2.0/.
66
----------------------------------------------------------*/
77

8+
using System;
89
using System.Net.Sockets;
910
using System.Runtime.Serialization;
1011
using System.Runtime.Serialization.Formatters.Binary;
@@ -15,23 +16,38 @@ namespace OneScript.DebugProtocol
1516
/// <summary>
1617
/// TCP-канал, использующий стандартную Binary-сериализацию .NET
1718
/// </summary>
19+
[Obsolete("Используется только со стороны адаптера, для работы со старыми версиями 1Script")]
1820
public sealed class BinaryChannel : ICommunicationChannel
1921
{
2022
private readonly TcpClient _client;
2123
private readonly NetworkStream _clientStream;
24+
#if NET48
2225
private readonly BinaryFormatter _serializer;
26+
#else
27+
private readonly IFormatter _serializer = null;
28+
#endif
29+
30+
private bool _enabled;
2331

2432
public BinaryChannel(TcpClient client)
2533
{
2634
_client = client;
2735
_clientStream = _client.GetStream();
36+
_enabled = true;
37+
#if NET48
2838
_serializer = new BinaryFormatter();
39+
#else
40+
throw new NotSupportedException("Binary channel should be used only in .NET 48.");
41+
#endif
2942
}
3043

31-
public bool Connected => _client.Connected;
44+
public bool Connected => _enabled && _client.Connected;
3245

3346
public void Write(object data)
3447
{
48+
if (!_enabled)
49+
throw new ObjectDisposedException(nameof(BinaryChannel));
50+
3551
_serializer.Serialize(_clientStream, data);
3652
}
3753

@@ -42,6 +58,9 @@ public T Read<T>()
4258

4359
public object Read()
4460
{
61+
if (!_enabled)
62+
throw new ObjectDisposedException(nameof(BinaryChannel));
63+
4564
try
4665
{
4766
return _serializer.Deserialize(_clientStream);
@@ -56,6 +75,7 @@ public void Dispose()
5675
{
5776
_clientStream.Dispose();
5877
_client.Close();
78+
_enabled = false;
5979
}
6080
}
6181
}

src/OneScript.DebugProtocol/TcpServer/DefaultMessageServer.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,10 @@ private void RunCommandsLoop()
8181
// свойство в исключении может быть уcтановлено в обработчике евента
8282
_serverStopped = e.StopChannel;
8383
}
84+
catch (ObjectDisposedException)
85+
{
86+
_serverStopped = true;
87+
}
8488
catch (Exception e)
8589
{
8690
var eventData = new CommunicationEventArgs
Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
/*----------------------------------------------------------
2+
This Source Code Form is subject to the terms of the
3+
Mozilla Public License, v.2.0. If a copy of the MPL
4+
was not distributed with this file, You can obtain one
5+
at http://mozilla.org/MPL/2.0/.
6+
----------------------------------------------------------*/
7+
using System;
8+
9+
namespace OneScript.DebugProtocol.TcpServer
10+
{
11+
public static class FormatReconcileUtils
12+
{
13+
/// <summary>
14+
/// Массив байт, который вызовет SerializationException при чтении его через BinaryFormatter
15+
/// И при этом оставит поток пустым, для следующего валидного сообщения
16+
/// <see>[MS-NRBF] .NET Remoting: Binary Format Data Structure</see>
17+
/// </summary>
18+
public static readonly byte[] FORMAT_RECONCILE_MAGIC =
19+
{
20+
0x11, // RecordTypeEnum
21+
0,0,0,0, // RootId
22+
0,0,0,0, // HeaderId
23+
0x00, 0x0A, 0x00, 0x0A, // Version Major
24+
0xAA, 0xAA, 0xAA, 0xAA // Version Minor,
25+
};
26+
27+
/// <summary>
28+
/// Ответ на запрос формата
29+
/// </summary>
30+
public static readonly byte[] FORMAT_RECONCILE_RESPONSE_PREFIX =
31+
{
32+
0x1C,
33+
0x1C,
34+
0x1C,
35+
0x1C
36+
};
37+
38+
public static readonly TimeSpan FORMAT_RECONCILE_TIMEOUT = TimeSpan.FromMilliseconds(500);
39+
40+
public static bool CheckReconcilePrefix(byte[] data)
41+
{
42+
for (int i = 0; i < FORMAT_RECONCILE_RESPONSE_PREFIX.Length; i++)
43+
{
44+
if (data[i] != FORMAT_RECONCILE_RESPONSE_PREFIX[i])
45+
return false;
46+
}
47+
48+
return true;
49+
}
50+
51+
public static bool CheckReconcileRequest(byte[] data)
52+
{
53+
for (int i = 0; i < FORMAT_RECONCILE_MAGIC.Length; i++)
54+
{
55+
if (data[i] != FORMAT_RECONCILE_MAGIC[i])
56+
return false;
57+
}
58+
59+
return true;
60+
}
61+
62+
public static int EncodeFormatMarker(short transport, short dataVersion)
63+
{
64+
var marker = transport << 16;
65+
return marker | dataVersion;
66+
}
67+
68+
public static (int, int) DecodeFormatMarker(int marker)
69+
{
70+
var transport = marker >> 16;
71+
var dataVersion = marker & 0x0000FFFF;
72+
73+
return (transport, dataVersion);
74+
}
75+
}
76+
}
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*----------------------------------------------------------
2+
This Source Code Form is subject to the terms of the
3+
Mozilla Public License, v.2.0. If a copy of the MPL
4+
was not distributed with this file, You can obtain one
5+
at http://mozilla.org/MPL/2.0/.
6+
----------------------------------------------------------*/
7+
8+
using System;
9+
using System.IO;
10+
using System.Net.Sockets;
11+
using System.Text;
12+
using Newtonsoft.Json;
13+
using OneScript.DebugProtocol.Abstractions;
14+
15+
namespace OneScript.DebugProtocol.TcpServer
16+
{
17+
public class JsonDtoChannel : ICommunicationChannel
18+
{
19+
private readonly TcpClient _tcpClient;
20+
private readonly Stream _dataStream;
21+
22+
private bool _enabled = true;
23+
24+
public JsonDtoChannel(TcpClient tcpClient)
25+
{
26+
_tcpClient = tcpClient;
27+
_dataStream = tcpClient.GetStream();
28+
}
29+
30+
public JsonDtoChannel(Stream dataStream)
31+
{
32+
_tcpClient = null;
33+
_dataStream = dataStream;
34+
}
35+
36+
public void Dispose()
37+
{
38+
_dataStream.Dispose();
39+
_tcpClient?.Close();
40+
_enabled = false;
41+
}
42+
43+
public void Write(object data)
44+
{
45+
if (!_enabled)
46+
throw new ObjectDisposedException(nameof(JsonDtoChannel));
47+
48+
using var streamWriter = new StreamWriter(_dataStream, Encoding.UTF8, 1024, leaveOpen: true);
49+
using var writer = new JsonTextWriter(streamWriter);
50+
51+
JsonSerializer.CreateDefault().Serialize(writer, data);
52+
writer.Flush();
53+
}
54+
55+
public T Read<T>()
56+
{
57+
return (T)Read();
58+
}
59+
60+
public object Read()
61+
{
62+
if (!_enabled)
63+
throw new ObjectDisposedException(nameof(JsonDtoChannel));
64+
65+
using var streamReader = new StreamReader(_dataStream, Encoding.UTF8, false, 1024, leaveOpen: true);
66+
using var reader = new JsonTextReader(streamReader);
67+
68+
return JsonSerializer.CreateDefault().Deserialize<TcpProtocolDtoBase>(reader);
69+
}
70+
71+
public bool Connected => _enabled && (_tcpClient?.Connected ?? true);
72+
}
73+
}

0 commit comments

Comments
 (0)