Make Peer more generic

This commit is contained in:
Sofia 2020-08-02 21:32:30 +03:00
parent 2939eecc8b
commit 5687a22090
17 changed files with 432 additions and 188 deletions

View File

@ -2,7 +2,7 @@
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using NeonTea.Quakeball.Net.Endpoint;
using NeonTea.Quakeball.Net.Peers;
namespace NeonTea.Quakeball.Net {
public class CanvasInput : MonoBehaviour {
@ -16,12 +16,12 @@ namespace NeonTea.Quakeball.Net {
Host.onClick.AddListener(() => {
//Destroy(Join.gameObject);
//Host.interactable = false;
Network.Singleton.Start(new Server(), "0.0.0.0", 8080);
Net.Singleton.Start(new Server(), "0.0.0.0", 8080);
});
Join.onClick.AddListener(() => {
//Destroy(Host.gameObject);
//Join.interactable = false;
Network.Singleton.Start(new Client(), "127.0.0.1", 8080);
Net.Singleton.Start(new Client(), "127.0.0.1", 8080);
});
}

View File

@ -6,12 +6,16 @@ namespace NeonTea.Quakeball.Net {
public class Connection {
public IPEndPoint Endpoint;
public uint uuid;
public bool ShouldExist = true;
public ConnectionStatus Status = ConnectionStatus.Establishing;
public Connection(IPEndPoint endpoint, uint uuid) {
public Connection(IPEndPoint endpoint) {
this.Endpoint = endpoint;
this.uuid = uuid;
}
}
public enum ConnectionStatus {
Establishing,
Ready,
Closed,
}
}

View File

@ -1,46 +0,0 @@
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace NeonTea.Quakeball.Net.Endpoint {
public class Client : AbstractEndpoint {
public override UdpClient UdpClient {
get { return InnerClient; }
}
private Connection Connection;
private UdpClient InnerClient;
public override void Start(string host, int port) {
InnerClient = new UdpClient(0);
try {
Connection = new Connection(new IPEndPoint(FindAddress(host), port), 0);
} catch (Exception e) {
Debug.Log($"Failed to create initial connection: {e.ToString()}");
Network.Singleton.Stop();
}
StartListen(Connection);
SendBytes(Encoding.UTF8.GetBytes("Hello! This is testing."));
Debug.Log($"Client started at {host}:{port}!");
}
public void OnStop() {
Connection.ShouldExist = false;
}
public override void ConnectionClosed(Connection conn, ClosingReason reason) {
if (Connection == conn) { // Make sure the closed connection is this one
Debug.Log($"Closing client. Connection was closed: {reason.Description}");
Network.Singleton.Stop();
}
}
private void SendBytes(Byte[] bytes) {
UdpClient.Send(bytes, bytes.Length, Connection.Endpoint);
}
}
}

View File

@ -1,80 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Text;
namespace NeonTea.Quakeball.Net.Endpoint {
public abstract class AbstractEndpoint {
private Dictionary<uint, Thread> ListenThreads = new Dictionary<uint, Thread>();
public abstract void Start(string host, int port);
public abstract UdpClient UdpClient { get; }
public virtual void ConnectionClosed(Connection conn, ClosingReason reason) {
}
public void Stop() {
UdpClient.Close();
foreach (Thread thread in ListenThreads.Values) {
thread.Abort();
}
}
protected IPAddress FindAddress(string host) {
IPAddress addr;
try {
addr = Dns.GetHostAddresses(host)[0];
} catch (ArgumentException) {
addr = IPAddress.Parse(host);
}
return addr;
}
protected bool StartListen(Connection connection) {
if (ListenThreads.ContainsKey(connection.uuid)) {
return false;
}
Thread t = new Thread(ListenThread);
t.Start(connection);
ListenThreads.Add(connection.uuid, t);
return true;
}
private void ListenThread(object obj) {
Connection listened;
try {
listened = (Connection)obj;
} catch (InvalidCastException) {
Debug.Log($"Can not cast {obj} to a Connection");
return;
}
while (listened.ShouldExist) {
try {
Byte[] Received = UdpClient.Receive(ref listened.Endpoint);
Debug.Log(Encoding.UTF8.GetString(Received));
} catch (Exception e) {
Debug.Log($"Error listening to connection, closing connection: {e.ToString()}");
listened.ShouldExist = false;
ConnectionClosed(listened, new ClosingReason(Reason.LISTENING_ERROR, e.ToString()));
}
}
}
}
}
public struct ClosingReason {
public Reason Reason;
public string Description;
public ClosingReason(Reason reason, string description) {
Reason = reason;
Description = description;
}
}
public enum Reason {
LISTENING_ERROR
}

View File

@ -1,43 +0,0 @@
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
namespace NeonTea.Quakeball.Net.Endpoint {
public class Server : AbstractEndpoint {
public override UdpClient UdpClient {
get { return InnerClient; }
}
private static uint ConnectionUUIDCounter;
private Dictionary<uint, Connection> Connections = new Dictionary<uint, Connection>();
private UdpClient InnerClient;
public override void Start(string host, int port) {
InnerClient = new UdpClient(port);
Connection conn;
try {
conn = AddConnection(new IPEndPoint(FindAddress(host), port), uint.MaxValue);
} catch (Exception e) {
Debug.Log($"Failed to create initial connection: {e.ToString()}");
Network.Singleton.Stop();
return;
}
StartListen(conn);
Debug.Log($"Server started at {host}:{port}!");
}
private Connection AddConnection(IPEndPoint endpoint, uint uuid = 0) {
if (uuid == 0) {
uuid = ConnectionUUIDCounter++;
}
Connection conn = new Connection(endpoint, uuid);
Connections.Add(uuid, conn);
return conn;
}
}
}

View File

@ -1,15 +1,15 @@
using UnityEngine;
using NeonTea.Quakeball.Net.Endpoint;
using NeonTea.Quakeball.Net.Peers;
using System.Threading;
namespace NeonTea.Quakeball.Net {
public class Network {
public static Network Singleton = new Network();
public class Net {
public static Net Singleton = new Net();
private AbstractEndpoint Endpoint;
private Peer Endpoint;
public void Start(AbstractEndpoint endpoint, string host, int port) {
public void Start(Peer endpoint, string host, int port) {
if (Endpoint != null) {
Debug.Log("Can not start multiple endpoints at once! Use Server if multiple connections are required.");
return;
@ -18,9 +18,11 @@ namespace NeonTea.Quakeball.Net {
Endpoint.Start(host, port);
}
public void Stop() {
Endpoint.Stop();
Endpoint = null;
public void Stop(DisconnectReason reason) {
if (Endpoint != null) {
Endpoint.Stop(reason);
Endpoint = null;
}
}
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: d8773e20fdc6d1842848081eaf595ad5
guid: 4f84b114622507742a4fa2404326fd64
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 928cabe03c8ac0d4fb8361c947698310
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:

View File

@ -0,0 +1,27 @@
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net.Sockets;
using System.Text;
using System.Net;
namespace NeonTea.Quakeball.Net.Peers {
public class Client : Peer {
public override void OnStart(string host, int port) {
SendBytes(Encoding.UTF8.GetBytes("Hello! This is testing."), MainConnection.Endpoint);
Debug.Log($"Client started at {host}:{port}!");
}
public override void HandlePacket(IPEndPoint endpoint, ByteReader reader) {
if (endpoint.Equals(MainConnection.Endpoint)) {
Debug.Log("Got stuff!");
}
}
public override void OnStop(DisconnectReason reason) {
Debug.Log($"Client closed: {reason.Description}");
}
}
}

View File

@ -0,0 +1,139 @@
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace NeonTea.Quakeball.Net.Peers {
public abstract class Peer {
private Thread ListenThread;
public byte[] Fingerprint = new byte[] { 0xCA, 0x11, 0x7F, 0xF8 };
protected UdpClient UdpClient;
protected Connection MainConnection;
public abstract void OnStart(string orighost, int origport);
public abstract void OnStop(DisconnectReason reason);
public abstract void HandlePacket(IPEndPoint endpoint, ByteReader reader);
public void Start(string host, int port) {
int own_port = port;
if (this.GetType() == typeof(Client)) {
own_port = 0;
}
UdpClient = new UdpClient(own_port);
try {
MainConnection = new Connection(new IPEndPoint(FindAddress(host), port));
} catch (Exception e) {
Debug.Log($"Failed to create initial connection: {e.ToString()}");
Net.Singleton.Stop(new DisconnectReason(Reason.INITIAL_ERROR, e.ToString()));
return;
}
StartListen(MainConnection);
OnStart(host, port);
}
public void Stop(DisconnectReason reason) {
UdpClient.Close();
if (ListenThread != null) {
ListenThread.Abort();
}
MainConnection.Status = ConnectionStatus.Closed;
OnStop(reason);
}
protected IPAddress FindAddress(string host) {
IPAddress addr;
try {
addr = Dns.GetHostAddresses(host)[0];
} catch (ArgumentException) {
addr = IPAddress.Parse(host);
}
return addr;
}
protected void SendBytes(byte[] bytes, IPEndPoint endpoint) {
if (bytes != null) {
List<byte> ByteList = new List<byte>();
ByteList.AddRange(Fingerprint);
ByteList.AddRange(bytes);
byte[] sent = ByteList.ToArray();
UdpClient.Send(sent, sent.Length, endpoint);
}
}
private bool StartListen(Connection connection) {
if (ListenThread != null) {
return false;
}
Thread t = new Thread(ListenThreadMethod);
t.Start(connection);
ListenThread = t;
return true;
}
private void ListenThreadMethod(object obj) {
Connection listened;
try {
listened = (Connection)obj;
} catch (InvalidCastException) {
Debug.Log($"Can not cast {obj} to a Connection");
return;
}
while (listened.Status != ConnectionStatus.Closed) {
try {
IPEndPoint Listened = new IPEndPoint(listened.Endpoint.Address, listened.Endpoint.Port);
ByteReader Received = new ByteReader(UdpClient.Receive(ref Listened));
foreach (byte b in Fingerprint) {
if (!(Received.hasNext() && Received.next() == b)) {
goto end_of_handle;
}
}
HandlePacket(Listened, Received);
} catch (Exception e) {
Net.Singleton.Stop(new DisconnectReason(Reason.LISTENING_ERROR, e.ToString()));
}
end_of_handle: { };
}
}
}
public class ByteReader {
private byte[] ByteList;
private uint pos = 0;
public ByteReader(byte[] list) {
ByteList = list;
}
public bool hasNext() {
return pos < ByteList.Length;
}
public byte next() {
return ByteList[pos++];
}
}
public struct DisconnectReason {
public static DisconnectReason LOCAL_MANUAL = new DisconnectReason(Reason.LOCAL_MANUAL, "");
public Reason Reason;
public string Description;
public DisconnectReason(Reason reason, string description) {
Reason = reason;
Description = description;
}
}
public enum Reason {
LOCAL_MANUAL,
LISTENING_ERROR,
INITIAL_ERROR,
}
}

View File

@ -1,5 +1,5 @@
fileFormatVersion: 2
guid: de661f9bd7cfa694db4111a798643dd3
guid: 78ce8008bfd56364d9f9972db616f444
MonoImporter:
externalObjects: {}
serializedVersion: 2

View File

@ -0,0 +1,35 @@
using System.Collections.Generic;
using UnityEngine;
using System.Net;
namespace NeonTea.Quakeball.Net.Peers {
public class Server : Peer {
private static uint ConnectionUUIDCounter;
private Dictionary<IPEndPoint, Connection> Connections = new Dictionary<IPEndPoint, Connection>();
public override void OnStart(string host, int port) {
MainConnection.Status = ConnectionStatus.Ready;
Debug.Log($"Server started at {host}:{port}!");
}
public override void OnStop(DisconnectReason reason) {
Debug.Log($"Server closed: {reason.Description}");
}
public override void HandlePacket(IPEndPoint endpoint, ByteReader reader) {
if (Connections.ContainsKey(endpoint)) {
Debug.Log("Got stuff from an existing connection!");
} else {
Connections.Add(endpoint, new Connection(endpoint));
Debug.Log($"Initialized new connection from {endpoint.ToString()}");
}
}
private Connection AddConnection(IPEndPoint endpoint) {
Connection conn = new Connection(endpoint);
Connections.Add(endpoint, conn);
return conn;
}
}
}

View File

@ -293,3 +293,195 @@ InputManager:
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Enable Debug Button 1
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: left ctrl
altNegativeButton:
altPositiveButton: joystick button 8
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Enable Debug Button 2
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: backspace
altNegativeButton:
altPositiveButton: joystick button 9
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Reset
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: left alt
altNegativeButton:
altPositiveButton: joystick button 1
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Next
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: page down
altNegativeButton:
altPositiveButton: joystick button 5
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Previous
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: page up
altNegativeButton:
altPositiveButton: joystick button 4
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Validate
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: return
altNegativeButton:
altPositiveButton: joystick button 0
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Persistent
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: right shift
altNegativeButton:
altPositiveButton: joystick button 2
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Multiplier
descriptiveName:
descriptiveNegativeName:
negativeButton:
positiveButton: left shift
altNegativeButton:
altPositiveButton: joystick button 3
gravity: 0
dead: 0
sensitivity: 0
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Horizontal
descriptiveName:
descriptiveNegativeName:
negativeButton: left
positiveButton: right
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Vertical
descriptiveName:
descriptiveNegativeName:
negativeButton: down
positiveButton: up
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 0
axis: 0
joyNum: 0
- serializedVersion: 3
m_Name: Debug Vertical
descriptiveName:
descriptiveNegativeName:
negativeButton: down
positiveButton: up
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 2
axis: 6
joyNum: 0
- serializedVersion: 3
m_Name: Debug Horizontal
descriptiveName:
descriptiveNegativeName:
negativeButton: left
positiveButton: right
altNegativeButton:
altPositiveButton:
gravity: 1000
dead: 0.001
sensitivity: 1000
snap: 0
invert: 0
type: 2
axis: 5
joyNum: 0

View File

@ -27,6 +27,11 @@
"type": "UnityEngine.ProBuilder.SemVer, Unity.ProBuilder, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null",
"key": "preferences.version",
"value": "{\"m_Value\":{\"m_Major\":4,\"m_Minor\":2,\"m_Patch\":3,\"m_Build\":-1,\"m_Type\":\"\",\"m_Metadata\":\"\",\"m_Date\":\"\"}}"
},
{
"type": "System.Boolean, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089",
"key": "lightmapping.autoUnwrapLightmapUV",
"value": "{\"m_Value\":true}"
}
]
}

View File

@ -95,7 +95,7 @@ PlayerSettings:
xboxEnableFitness: 0
visibleInBackground: 1
allowFullscreenSwitch: 1
fullscreenMode: 1
fullscreenMode: 3
xboxSpeechDB: 0
xboxEnableHeadOrientation: 0
xboxEnableGuest: 0
@ -126,7 +126,8 @@ PlayerSettings:
16:9: 1
Others: 1
bundleVersion: 0.1
preloadedAssets: []
preloadedAssets:
- {fileID: 0}
metroInputSource: 0
wsaTransparentSwapchain: 0
m_HolographicPauseOnTrackingLoss: 1