Repository navigation
Expand file tree
/
Copy pathSwitchConnectionAsync.cs
More file actions
136 lines (115 loc) · 4.87 KB
/
Copy pathSwitchConnectionAsync.cs
File metadata and controls
136 lines (115 loc) · 4.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Threading.Tasks;
namespace SysBot.Base
{
/// <summary>
/// Connection to a Nintendo Switch hosting the sys-module.
/// </summary>
public class SwitchConnectionAsync : SwitchConnectionBase
{
public SwitchConnectionAsync(string ipaddress, int port) : base(ipaddress, port) { }
public SwitchConnectionAsync(SwitchBotConfig cfg) : this(cfg.IP, cfg.Port) { }
public void Connect()
{
if (Connected)
{
Log("Already connected prior, skipping initial connection.");
return;
}
Log("Connecting to device...");
Connection.Connect(IP, Port);
Connected = true;
Log("Connected!");
}
public void Reset(string ip)
{
Disconnect();
Connection = new Socket(SocketType.Stream, ProtocolType.Tcp);
Log("Connecting to device...");
var address = Dns.GetHostAddresses(ip);
foreach (IPAddress adr in address)
{
IPEndPoint ep = new IPEndPoint(adr, Port);
Connection.BeginConnect(ep, ConnectCallback, Connection);
Connected = true;
Log("Connected!");
}
}
public void Disconnect()
{
Log("Disconnecting from device...");
Connection.Shutdown(SocketShutdown.Both);
Connection.BeginDisconnect(true, DisconnectCallback, Connection);
Connected = false;
Log("Disconnected!");
}
private readonly AutoResetEvent connectionDone = new AutoResetEvent(false);
private void ConnectCallback(IAsyncResult ar)
{
// Complete the connection request.
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
// Signal that the connection is complete.
connectionDone.Set();
LogUtil.LogInfo("Connected.", Name);
}
private readonly AutoResetEvent disconnectDone = new AutoResetEvent(false);
private void DisconnectCallback(IAsyncResult ar)
{
// Complete the disconnect request.
Socket client = (Socket)ar.AsyncState;
client.EndDisconnect(ar);
// Signal that the disconnect is complete.
disconnectDone.Set();
LogUtil.LogInfo("Disconnected.", Name);
}
public int Read(byte[] buffer)
{
int br = Connection.Receive(buffer, 0, 1, SocketFlags.None);
while (buffer[br - 1] != (byte)'\n')
br += Connection.Receive(buffer, br, 1, SocketFlags.None);
return br;
}
public async Task<int> SendAsync(byte[] buffer, CancellationToken token) => await Task.Run(() => Connection.Send(buffer), token).ConfigureAwait(false);
private async Task<byte[]> ReadBytesFromCmdAsync(byte[] cmd, int length, CancellationToken token)
{
await SendAsync(cmd, token).ConfigureAwait(false);
var buffer = new byte[(length * 2) + 1];
var _ = Read(buffer);
return Decoder.ConvertHexByteStringToBytes(buffer);
}
public async Task<byte[]> ReadBytesAsync(uint offset, int length, CancellationToken token)
{
return await ReadBytesFromCmdAsync(SwitchCommand.Peek(offset, length), length, token).ConfigureAwait(false);
}
public async Task<byte[]> ReadBytesAbsoluteAsync(ulong offset, int length, CancellationToken token)
{
return await ReadBytesFromCmdAsync(SwitchCommand.PeekAbsolute(offset, length), length, token).ConfigureAwait(false);
}
public async Task<ulong> GetMainNsoBaseAsync(CancellationToken token)
{
byte[] baseBytes = await ReadBytesFromCmdAsync(SwitchCommand.GetMainNsoBase(), sizeof(ulong), token).ConfigureAwait(false);
Array.Reverse(baseBytes, 0, 8);
return BitConverter.ToUInt64(baseBytes, 0);
}
public async Task<ulong> GetHeapBaseAsync(CancellationToken token)
{
var baseBytes = await ReadBytesFromCmdAsync(SwitchCommand.GetHeapBase(), sizeof(ulong), token).ConfigureAwait(false);
Array.Reverse(baseBytes, 0, 8);
return BitConverter.ToUInt64(baseBytes, 0);
}
public async Task WriteBytesAsync(byte[] data, uint offset, CancellationToken token)
{
var cmd = SwitchCommand.Poke(offset, data);
await SendAsync(cmd, token).ConfigureAwait(false);
}
public async Task WriteBytesAbsoluteAsync(byte[] data, ulong offset, CancellationToken token)
{
var cmd = SwitchCommand.PokeAbsolute(offset, data);
await SendAsync(cmd, token).ConfigureAwait(false);
}
}
}