quakeball/Assets/Scripts/TeaNet/Peers/Peer.cs

162 lines
6.7 KiB
C#
Raw Normal View History

2020-08-02 20:32:30 +02:00
using System.Collections.Generic;
using UnityEngine;
using System;
using System.Net;
using System.Net.Sockets;
using NeonTea.Quakeball.TeaNet.Packets;
2020-08-02 20:32:30 +02:00
namespace NeonTea.Quakeball.TeaNet.Peers {
/// <summary>Main class for networking. Remember to register a protocol before using. Remember to call Update from a gameobject!</summary>
2020-08-05 03:21:04 +02:00
public class Peer : PeerMessageListener {
2020-08-06 20:49:51 +02:00
/// <summary>Underlying UdpClient. Do not touch unless you know what you are doing.</summary>
2020-08-05 03:21:04 +02:00
public UdpClient UdpClient { get; private set; }
2020-08-06 20:49:51 +02:00
/// <summary>The fingerprint for networking. Used to make sure incoming bytes are from a correct source.</summary>
2020-08-05 03:21:04 +02:00
public byte[] Fingerprint { get; private set; }
2020-08-06 20:49:51 +02:00
/// <summary>Shorthand for ConnectionManager.Timeout: The amount of milliseconds before a connection is timed out.</summary>
public long Timeout {
get {
return ConnectionManager.Timeout;
}
set {
ConnectionManager.Timeout = value;
}
}
/// <summary>Shorthand for ConnectionManager.Interval: The interval of updates and rate of re-sending reliable messages.</summary>
public long UpdateInterval {
get {
return ConnectionManager.Interval;
}
set {
ConnectionManager.Interval = value;
}
}
2020-08-02 20:32:30 +02:00
2020-08-05 03:21:04 +02:00
public ListenerThread ListenerThread;
public ConnectionManager ConnectionManager;
public Dictionary<byte, Protocol> RegisteredProtocols = new Dictionary<byte, Protocol>();
2020-08-02 20:32:30 +02:00
2020-08-06 20:49:51 +02:00
/// <summary>Listener for messages and errors from within the Peer.</summary>
2020-08-05 03:21:04 +02:00
public PeerMessageListener MessageListener;
2020-08-02 20:32:30 +02:00
2020-08-06 20:49:51 +02:00
/// <summary>Creates a new Peer with the given fingerprint. The fingerprint can be anything, it just must be same on both peers.</summary>
2020-08-05 03:21:04 +02:00
public Peer(byte[] fingerprint) {
Fingerprint = fingerprint;
ConnectionManager = new ConnectionManager(this);
MessageListener = this;
}
2020-08-02 20:32:30 +02:00
2020-08-06 20:49:51 +02:00
/// <summary>Starts the UdpClient, but does no networking as is.</summary>
2020-08-05 03:21:04 +02:00
public void Start(int sending_port) {
UdpClient = new UdpClient(sending_port);
MessageListener.Message("UdpClient Started");
2020-08-02 20:32:30 +02:00
}
2020-08-06 20:49:51 +02:00
/// <summary>Abruptly stops the UdpClient and all relevant threads.</summary>
2020-08-05 03:21:04 +02:00
public void Stop() {
ConnectionManager.StopThread();
if (ListenerThread != null) {
ListenerThread.Stop();
2020-08-02 20:32:30 +02:00
}
2020-08-05 03:21:04 +02:00
UdpClient.Dispose();
UdpClient.Close();
2020-08-02 20:32:30 +02:00
}
2020-08-06 20:49:51 +02:00
/// <summary>Start listening to a given address and port. Usually 0.0.0.0, 0 for clients and 0.0.0.0, port for servers</summary>
2020-08-05 03:21:04 +02:00
public void StartListen(string address, int port) {
IPEndPoint endpoint = new IPEndPoint(FindAddress(address), port);
StartListen(endpoint);
2020-08-02 20:32:30 +02:00
}
2020-08-05 03:21:04 +02:00
private void StartListen(IPEndPoint endpoint) {
if (ListenerThread != null) {
return; // Cant listen twice
}
2020-08-05 03:21:04 +02:00
ListenerThread = new ListenerThread(this, endpoint);
ListenerThread.Start();
MessageListener.Message($"Started listening to {endpoint}");
2020-08-02 20:32:30 +02:00
}
2020-08-06 20:49:51 +02:00
/// <summary>Connect to a remote host. Will initialize a listener to 0.0.0.0:0 if no listener is started.</summary>
2020-08-05 19:45:34 +02:00
public void Connect(string address, int port, byte protocolIdent, bool startListening = true) {
if (startListening) {
IPEndPoint listenEndpoint = (IPEndPoint)UdpClient.Client.LocalEndPoint;
StartListen(listenEndpoint);
}
2020-08-05 03:21:04 +02:00
IPEndPoint endpoint = new IPEndPoint(FindAddress(address), port);
ConnectionManager.StartConnection(endpoint, protocolIdent);
MessageListener.Message($"Connecting to {endpoint}");
2020-08-02 20:32:30 +02:00
}
/// <summary>Soft-disconnects the connection with the given uid, meaning it will wait until they acknowledge, before timing out.abstract</summary>
public void Disconnect(ulong uid) {
ConnectionManager.CloseConnection(uid, ClosingReason.Manual);
}
2020-08-06 20:49:51 +02:00
/// <summary>Send a reliable packet, meaning it will reliably be delivered.</summary>
public void SendReliable(ulong uid, Packet packet) {
ConnectionManager.AddPacketToQueue(uid, packet);
ConnectionManager.SendPacketQueue(uid);
}
2020-08-06 20:49:51 +02:00
/// <summary>Add reliable packet to queue, so that it will be sent on the next update.</summary>
2020-08-05 20:55:17 +02:00
public void SendReliableLater(ulong uid, Packet packet) {
ConnectionManager.AddPacketToQueue(uid, packet);
}
2020-08-06 20:49:51 +02:00
/// <summary>Send an unreliable packet, meaning its delivery is not reliable.</summary>
public void SendUnreliable(ulong uid, Packet packet) {
ConnectionManager.SendSingleUnreliable(uid, packet);
}
2020-08-06 20:49:51 +02:00
/// <summary>Get a Connection instance from the given uid, if such exists. Null otherwise.</summary>
public Connection GetConnection(ulong uid) {
return ConnectionManager.GetConnection(uid);
}
2020-08-06 20:49:51 +02:00
/// <summary>Register a given protocol. Returns protocol.Identifier if successful, 0 otherwise.</summary>
2020-08-05 03:21:04 +02:00
public byte RegisterProtocol(Protocol protocol) {
byte ident = protocol.Identifier;
if (RegisteredProtocols.ContainsKey(ident)) {
return 0;
2020-08-02 20:32:30 +02:00
}
2020-08-05 03:21:04 +02:00
RegisteredProtocols.Add(ident, protocol);
ConnectionManager.ProtocolActionQueues.Add(ident, new Queue<ProtocolAction>());
2020-08-05 03:21:04 +02:00
protocol.Peer = this;
return ident;
2020-08-02 20:32:30 +02:00
}
2020-08-06 20:49:51 +02:00
/// <summary>Get protocol instance from the given identifier, if such exists.</summary>
2020-08-05 03:21:04 +02:00
public Protocol GetProtocol(byte ident) {
if (RegisteredProtocols.ContainsKey(ident)) {
return RegisteredProtocols[ident];
}
return null;
2020-08-02 20:32:30 +02:00
}
/// <summary>Shorthand for Peer.ConnectionManager.Update(): Handles network stuff that was received since last update.</summary>
public void Update() {
ConnectionManager.Update();
}
2020-08-05 21:54:53 +02:00
public void Message(string msg) { }
public void Err(string msg) { }
2020-08-02 20:32:30 +02:00
2020-08-06 20:49:51 +02:00
private IPAddress FindAddress(string host) {
2020-08-05 03:21:04 +02:00
IPAddress addr;
try {
addr = Dns.GetHostAddresses(host)[0];
} catch (ArgumentException) {
addr = IPAddress.Parse(host);
}
return addr;
2020-08-02 20:32:30 +02:00
}
}
2020-08-06 20:49:51 +02:00
/// <summary>Listener for messages and errors from the Peer.</summary>
2020-08-05 03:21:04 +02:00
public interface PeerMessageListener {
void Message(string msg);
2020-08-05 21:54:53 +02:00
void Err(string msg);
2020-08-02 20:32:30 +02:00
}
}