Skip to content
This repository was archived by the owner on Aug 8, 2018. It is now read-only.

Commit df56306

Browse files
authored
Create RelayTransport.cs
1 parent ee7ca96 commit df56306

File tree

1 file changed

+355
-0
lines changed

1 file changed

+355
-0
lines changed

RelayTransport.cs

Lines changed: 355 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,355 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Net;
4+
using System.Text;
5+
using UnityEngine;
6+
using UnityEngine.Networking;
7+
8+
namespace MLAPI.Relay
9+
{
10+
public static class RelayTransport
11+
{
12+
private enum MessageType
13+
{
14+
StartServer,
15+
ConnectToServer,
16+
Data,
17+
ClientDisconnect
18+
}
19+
20+
//State
21+
private static int relayConnectionId;
22+
private static bool isClient = false;
23+
private static string address;
24+
private static ushort port;
25+
private static List<ChannelQOS> channels = new List<ChannelQOS>();
26+
27+
public static bool Enabled { get; set; }
28+
public static string RelayAddress { get; set; }
29+
public static ushort RelayPort { get; set; }
30+
31+
public static int Connect(int hostId, string serverAddress, int serverPort, int exceptionConnectionId, out byte error)
32+
{
33+
if (!Enabled) return NetworkTransport.Connect(hostId, serverAddress, serverPort, exceptionConnectionId, out error);
34+
35+
isClient = true;
36+
RelayTransport.address = serverAddress;
37+
RelayTransport.port = (ushort)serverPort;
38+
relayConnectionId = NetworkTransport.Connect(hostId, RelayAddress, RelayPort, exceptionConnectionId, out error); // Requests connection
39+
return relayConnectionId;
40+
// Wait here until connect event is accepted
41+
}
42+
43+
public static int ConnectWithSimulator(int hostId, string serverAddress, int serverPort, int exceptionConnectionId, out byte error, ConnectionSimulatorConfig conf)
44+
{
45+
if (!Enabled) return NetworkTransport.ConnectWithSimulator(hostId, serverAddress, serverPort, exceptionConnectionId, out error, conf);
46+
47+
isClient = true;
48+
RelayTransport.address = serverAddress;
49+
RelayTransport.port = (ushort)serverPort;
50+
relayConnectionId = NetworkTransport.ConnectWithSimulator(hostId, RelayAddress, RelayPort, exceptionConnectionId, out error, conf); // Requests connection
51+
return relayConnectionId;
52+
}
53+
54+
public static int ConnectEndPoint(int hostId, EndPoint endPoint, int exceptionConnectionId, out byte error)
55+
{
56+
if (!Enabled) return NetworkTransport.ConnectEndPoint(hostId, endPoint, exceptionConnectionId, out error);
57+
58+
isClient = true;
59+
RelayTransport.address = ((IPEndPoint)endPoint).Address.ToString();
60+
RelayTransport.port = (ushort)((IPEndPoint)endPoint).Port;
61+
relayConnectionId = NetworkTransport.Connect(hostId, RelayAddress, RelayPort, exceptionConnectionId, out error); // Requests connection
62+
return relayConnectionId;
63+
}
64+
65+
private static void SetChannelsFromTopology(HostTopology topology) => channels = topology.DefaultConfig.Channels;
66+
67+
public static int AddHost(HostTopology topology, bool createServer)
68+
{
69+
if (!Enabled) return NetworkTransport.AddHost(topology);
70+
71+
isClient = !createServer;
72+
SetChannelsFromTopology(topology);
73+
int ret = NetworkTransport.AddHost(topology);
74+
if (createServer) relayConnectionId = NetworkTransport.Connect(ret, RelayAddress, RelayPort, 0, out byte b);
75+
return ret;
76+
}
77+
public static int AddHost(HostTopology topology, int port, bool createServer)
78+
{
79+
if (!Enabled) return NetworkTransport.AddHost(topology, port);
80+
81+
isClient = !createServer;
82+
SetChannelsFromTopology(topology);
83+
int ret = NetworkTransport.AddHost(topology, port);
84+
if (createServer) relayConnectionId = NetworkTransport.Connect(ret, RelayAddress, RelayPort, 0, out byte b);
85+
return ret;
86+
}
87+
public static int AddHost(HostTopology topology, int port, string ip, bool createServer)
88+
{
89+
if (!Enabled) return NetworkTransport.AddHost(topology, port, ip);
90+
91+
isClient = !createServer;
92+
SetChannelsFromTopology(topology);
93+
int ret = NetworkTransport.AddHost(topology, port, ip);
94+
if (createServer) relayConnectionId = NetworkTransport.Connect(ret, RelayAddress, RelayPort, 0, out byte b);
95+
return ret;
96+
}
97+
98+
public static int AddHostWithSimulator(HostTopology topology, int minTimeout, int maxTimeout, int port, string ip, bool createServer)
99+
{
100+
if (!Enabled) return NetworkTransport.AddHostWithSimulator(topology, minTimeout, maxTimeout);
101+
102+
isClient = !createServer;
103+
SetChannelsFromTopology(topology);
104+
int ret = NetworkTransport.AddHostWithSimulator(topology, minTimeout, maxTimeout, port, ip);
105+
if (createServer) relayConnectionId = NetworkTransport.Connect(ret, RelayAddress, RelayPort, 0, out byte b);
106+
return ret;
107+
}
108+
109+
public static int AddHostWithSimulator(HostTopology topology, int minTimeout, int maxTimeout, bool createServer)
110+
{
111+
if (!Enabled) return NetworkTransport.AddHostWithSimulator(topology, minTimeout, maxTimeout);
112+
113+
isClient = !createServer;
114+
SetChannelsFromTopology(topology);
115+
int ret = NetworkTransport.AddHostWithSimulator(topology, minTimeout, maxTimeout);
116+
if (createServer) relayConnectionId = NetworkTransport.Connect(ret, RelayAddress, RelayPort, 0, out byte b);
117+
return ret;
118+
}
119+
120+
public static int AddHostWithSimulator(HostTopology topology, int minTimeout, int maxTimeout, int port, bool createServer)
121+
{
122+
if (!Enabled) return NetworkTransport.AddHostWithSimulator(topology, minTimeout, maxTimeout, port);
123+
124+
isClient = !createServer;
125+
SetChannelsFromTopology(topology);
126+
int ret = NetworkTransport.AddHostWithSimulator(topology, minTimeout, maxTimeout, port);
127+
if (createServer) relayConnectionId = NetworkTransport.Connect(ret, RelayAddress, RelayPort, 0, out byte b);
128+
return ret;
129+
}
130+
131+
public static int AddWebsocketHost(HostTopology topology, int port, bool createServer)
132+
{
133+
if (!Enabled) return NetworkTransport.AddWebsocketHost(topology, port);
134+
135+
isClient = !createServer;
136+
SetChannelsFromTopology(topology);
137+
int ret = NetworkTransport.AddWebsocketHost(topology, port);
138+
if (createServer) relayConnectionId = NetworkTransport.Connect(ret, RelayAddress, RelayPort, 0, out byte b);
139+
return ret;
140+
}
141+
142+
public static int AddWebsocketHost(HostTopology topology, int port, string ip, bool createServer)
143+
{
144+
if (!Enabled) return NetworkTransport.AddWebsocketHost(topology, port, ip);
145+
146+
isClient = !createServer;
147+
SetChannelsFromTopology(topology);
148+
int ret = NetworkTransport.AddWebsocketHost(topology, port, ip);
149+
if (createServer) relayConnectionId = NetworkTransport.Connect(ret, RelayAddress, RelayPort, 0, out byte b);
150+
return ret;
151+
}
152+
153+
private static byte[] disconnectBuffer = new byte[3] { (byte)MessageType.ClientDisconnect, 0, 0 };
154+
public static bool Disconnect(int hostId, int connectionId, out byte error)
155+
{
156+
if (!Enabled) NetworkTransport.Disconnect(hostId, connectionId, out error);
157+
158+
if (!isClient)
159+
{
160+
disconnectBuffer.ToBytes((ushort)connectionId, 1);
161+
return NetworkTransport.Send(hostId, relayConnectionId, GetReliableChannel(), disconnectBuffer, 3, out error);
162+
}
163+
else
164+
{
165+
return NetworkTransport.Disconnect(hostId, connectionId, out error);
166+
}
167+
}
168+
169+
public static bool Send(int hostId, int connectionId, int channelId, byte[] buffer, int size, out byte error)
170+
{
171+
if (!Enabled) return NetworkTransport.Send(hostId, connectionId, channelId, buffer, size, out error);
172+
173+
if (isClient)
174+
{
175+
ForwardOffset(buffer, 1, size); // Offsets just the bytes we're sending
176+
++size;
177+
}
178+
else
179+
{
180+
ForwardOffset(buffer, 3, size); // Offsets just the bytes we're sending
181+
size += 3;
182+
183+
buffer[1] = (byte)connectionId;
184+
buffer[2] = (byte)(connectionId >> 8);
185+
}
186+
buffer[0] = (byte)MessageType.Data;
187+
188+
return NetworkTransport.Send(hostId, relayConnectionId, channelId, buffer, size, out error);
189+
}
190+
191+
public static bool QueueMessageForSending(int hostId, int connectionId, int channelId, byte[] buffer, int size, out byte error)
192+
{
193+
if (!Enabled) return NetworkTransport.QueueMessageForSending(hostId, connectionId, channelId, buffer, size, out error);
194+
195+
if (isClient)
196+
{
197+
ForwardOffset(buffer, 1, size); // Offsets just the bytes we're sending
198+
++size;
199+
}
200+
else
201+
{
202+
ForwardOffset(buffer, 3, size); // Offsets just the bytes we're sending
203+
size += 3;
204+
205+
buffer[1] = (byte)connectionId;
206+
buffer[2] = (byte)(connectionId >> 8);
207+
}
208+
buffer[0] = (byte)MessageType.Data;
209+
210+
return NetworkTransport.QueueMessageForSending(hostId, relayConnectionId, channelId, buffer, size, out error);
211+
}
212+
213+
public static bool SendQueuedMessages(int hostId, int connectionId, out byte error)
214+
{
215+
return NetworkTransport.SendQueuedMessages(hostId, relayConnectionId, out error);
216+
}
217+
218+
public static NetworkEventType ReceiveFromHost(int hostId, out int connectionId, out int channelId, byte[] buffer, int bufferSize, out int receivedSize, out byte error)
219+
{
220+
if (!Enabled) return NetworkTransport.ReceiveFromHost(hostId, out connectionId, out channelId, buffer, bufferSize, out receivedSize, out error);
221+
222+
NetworkEventType @event = NetworkTransport.ReceiveFromHost(hostId, out connectionId, out channelId, buffer, bufferSize, out receivedSize, out error);
223+
return BaseReceive(@event, hostId, ref connectionId, ref channelId, buffer, bufferSize, ref receivedSize, ref error);
224+
}
225+
226+
public static NetworkEventType Receive(out int hostId, out int connectionId, out int channelId, byte[] buffer, int bufferSize, out int receivedSize, out byte error)
227+
{
228+
if (!Enabled) return NetworkTransport.Receive(out hostId, out connectionId, out channelId, buffer, bufferSize, out receivedSize, out error);
229+
230+
NetworkEventType @event = NetworkTransport.Receive(out hostId, out connectionId, out channelId, buffer, bufferSize, out receivedSize, out error);
231+
return BaseReceive(@event, hostId, ref connectionId, ref channelId, buffer, bufferSize, ref receivedSize, ref error);
232+
}
233+
234+
private static NetworkEventType BaseReceive(NetworkEventType @event, int hostId, ref int connectionId, ref int channelId, byte[] buffer, int bufferSize, ref int receivedSize, ref byte error)
235+
{
236+
switch (@event)
237+
{
238+
case NetworkEventType.DataEvent:
239+
MessageType messageType = (MessageType)buffer[0];
240+
switch (messageType)
241+
{
242+
case MessageType.ConnectToServer: // Connection approved
243+
{
244+
if (!isClient)
245+
{
246+
connectionId = (ushort)(buffer[1] | (buffer[2] << 8)); // Parse connection id
247+
}
248+
return NetworkEventType.ConnectEvent;
249+
}
250+
case MessageType.Data:
251+
{
252+
if (isClient)
253+
{
254+
// Remove our headers
255+
ReverseOffset(buffer, 1, receivedSize);
256+
--receivedSize;
257+
}
258+
else
259+
{
260+
// Remove our headers
261+
connectionId = buffer.FromBytes(1);
262+
ReverseOffset(buffer, 3, receivedSize);
263+
receivedSize -= 3;
264+
}
265+
return NetworkEventType.DataEvent;
266+
}
267+
case MessageType.ClientDisconnect:
268+
{
269+
connectionId = (ushort)(buffer[1] | (buffer[2] << 8)); // Parse connection id
270+
return NetworkEventType.DisconnectEvent;
271+
}
272+
}
273+
break;
274+
case NetworkEventType.ConnectEvent:
275+
{
276+
if (isClient)
277+
{
278+
//Connect via relay
279+
string s = new StringBuilder(address).Append(':').Append(port).ToString();
280+
buffer[0] = (byte)MessageType.ConnectToServer;
281+
buffer[1] = (byte)s.Length;
282+
for (int i = 0; i < s.Length; i++)
283+
{
284+
buffer[i + 2] = (byte)s[i]; // Get ASCII characters
285+
}
286+
287+
NetworkTransport.Send(hostId, connectionId, GetReliableChannel(), buffer, s.Length + 2, out error);
288+
}
289+
else
290+
{
291+
//Register us as a server
292+
buffer[0] = (byte)MessageType.StartServer;
293+
NetworkTransport.Send(hostId, connectionId, GetReliableChannel(), buffer, 1, out error);
294+
}
295+
return NetworkEventType.Nothing; // Connect event is ignored
296+
}
297+
case NetworkEventType.DisconnectEvent:
298+
{
299+
if ((NetworkError)error == NetworkError.CRCMismatch) Debug.LogError("[MLAPI.Relay] The MLAPI Relay detected a CRC missmatch. This could be due to the maxClients or other connectionConfig settings not being the same");
300+
return NetworkEventType.DisconnectEvent;
301+
}
302+
}
303+
return @event;
304+
}
305+
306+
public static void ReverseOffset(byte[] b, int offset, int dLen)
307+
{
308+
for(int i = offset; i < dLen; ++i)
309+
b[i - offset] = b[i];
310+
}
311+
312+
public static void ForwardOffset(byte[] b, int offset, int dLen)
313+
{
314+
for(int i = dLen; i>=0; --i)
315+
b[i+offset] = b[i];
316+
}
317+
318+
//TODO: Fix
319+
public static byte GetReliableChannel()
320+
{
321+
for (byte i = 0; i < channels.Count; i++)
322+
{
323+
switch (channels[i].QOS)
324+
{
325+
case QosType.Reliable:
326+
case QosType.ReliableFragmented:
327+
case QosType.ReliableFragmentedSequenced:
328+
case QosType.ReliableSequenced:
329+
case QosType.ReliableStateUpdate:
330+
return i;
331+
}
332+
}
333+
throw new InvalidConfigException("A reliable channel is required");
334+
}
335+
}
336+
337+
public static class Helpers
338+
{
339+
public static void ToBytes(this byte[] b, ushort data, int offset = 0)
340+
{
341+
b[offset] = (byte)data;
342+
b[offset + 1] = (byte)(data >> 8);
343+
}
344+
public static ushort FromBytes(this byte[] b, int offset = 0)
345+
{
346+
return (ushort)(b[offset] | (b[offset + 1] << 8));
347+
}
348+
}
349+
350+
public class InvalidConfigException : SystemException
351+
{
352+
public InvalidConfigException() { }
353+
public InvalidConfigException(string issue) : base(issue) { }
354+
}
355+
}

0 commit comments

Comments
 (0)