Document everyting relevant in TeaNet
This commit is contained in:
parent
338a51b75e
commit
a086f02f93
@ -3,140 +3,173 @@ using System;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
|
||||||
namespace NeonTea.Quakeball.TeaNet.Packets {
|
namespace NeonTea.Quakeball.TeaNet.Packets {
|
||||||
|
/// <summary>Contains a stream of bytes for sending or receiving over the internet.</summary>
|
||||||
public class ByteBuffer {
|
public class ByteBuffer {
|
||||||
private List<byte> Bytes;
|
private List<byte> Bytes;
|
||||||
private int pos = 0;
|
private int pos = 0;
|
||||||
|
|
||||||
|
/// <summary>Creates a new empty ByteBuffer</summary>
|
||||||
public ByteBuffer() {
|
public ByteBuffer() {
|
||||||
Bytes = new List<byte>();
|
Bytes = new List<byte>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Creates a new ByteBuffer from the given byte[]</summary>
|
||||||
public ByteBuffer(byte[] bytes) {
|
public ByteBuffer(byte[] bytes) {
|
||||||
Bytes = new List<byte>(bytes);
|
Bytes = new List<byte>(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Packs the byte buffer in to a byte[] array.</summary>
|
||||||
public byte[] Pack() {
|
public byte[] Pack() {
|
||||||
return Bytes.ToArray();
|
return Bytes.ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>is there a byte to read next?</summary>
|
||||||
public bool CanRead() {
|
public bool CanRead() {
|
||||||
return pos < Bytes.Count;
|
return pos < Bytes.Count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Reads a given object with Serializable implemented. Assumes there is one next.</summary>
|
||||||
public void ReadSerializable(Serializable s) {
|
public void ReadSerializable(Serializable s) {
|
||||||
s.Read(this);
|
s.Read(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read a char on the buffer. Assumes there is one next.</summary>
|
||||||
public char ReadChar() {
|
public char ReadChar() {
|
||||||
return BitConverter.ToChar(Read(2), 0);
|
return BitConverter.ToChar(Read(2), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read a boolean on the buffer. Assumes there is one next.</summary>
|
||||||
public bool ReadBool() {
|
public bool ReadBool() {
|
||||||
return Read() == 1;
|
return Read() == 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read a double on the buffer. Assumes there is one next.</summary>
|
||||||
public double ReadDouble() {
|
public double ReadDouble() {
|
||||||
return BitConverter.ToDouble(Read(8), 0);
|
return BitConverter.ToDouble(Read(8), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read a float on the buffer. Assumes there is one next.</summary>
|
||||||
public float ReadFloat() {
|
public float ReadFloat() {
|
||||||
return BitConverter.ToSingle(Read(4), 0);
|
return BitConverter.ToSingle(Read(4), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read an unsigned long on the buffer. Assumes there is one next.</summary>
|
||||||
public ulong ReadULong() {
|
public ulong ReadULong() {
|
||||||
return BitConverter.ToUInt64(Read(8), 0);
|
return BitConverter.ToUInt64(Read(8), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read an unsigned integer on the buffer. Assumes there is one next.</summary>
|
||||||
public uint ReadUInt() {
|
public uint ReadUInt() {
|
||||||
return BitConverter.ToUInt32(Read(4), 0);
|
return BitConverter.ToUInt32(Read(4), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read an unsigned short on the buffer. Assumes there is one next.</summary>
|
||||||
public ushort ReadUShort() {
|
public ushort ReadUShort() {
|
||||||
return BitConverter.ToUInt16(Read(2), 0);
|
return BitConverter.ToUInt16(Read(2), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read a long on the buffer. Assumes there is one next.</summary>
|
||||||
public long ReadLong() {
|
public long ReadLong() {
|
||||||
return BitConverter.ToInt64(Read(8), 0);
|
return BitConverter.ToInt64(Read(8), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read an integer on the buffer. Assumes there is one next.</summary>
|
||||||
public int ReadInt() {
|
public int ReadInt() {
|
||||||
return BitConverter.ToInt32(Read(4), 0);
|
return BitConverter.ToInt32(Read(4), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read a short on the buffer. Assumes there is one next.</summary>
|
||||||
public short ReadShort() {
|
public short ReadShort() {
|
||||||
return BitConverter.ToInt16(Read(2), 0);
|
return BitConverter.ToInt16(Read(2), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read a string on the buffer. Assumes there is one next.</summary>
|
||||||
public string ReadString() {
|
public string ReadString() {
|
||||||
int length = ReadInt();
|
int length = ReadInt();
|
||||||
string s = Encoding.UTF8.GetString(Read(length));
|
string s = Encoding.UTF8.GetString(Read(length));
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read an integer on the buffer. Assumes there is one next.</summary>
|
||||||
public byte[] Read(int amount) {
|
public byte[] Read(int amount) {
|
||||||
byte[] bytes = Bytes.GetRange(pos, amount).ToArray();
|
byte[] bytes = Bytes.GetRange(pos, amount).ToArray();
|
||||||
pos += amount;
|
pos += amount;
|
||||||
return bytes;
|
return bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read the next byte on the buffer. Assumes there is one next.</summary>
|
||||||
public byte Read() {
|
public byte Read() {
|
||||||
return Bytes[pos++];
|
return Bytes[pos++];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write something that implements Serializable.</summary>
|
||||||
public void Write(Serializable s) {
|
public void Write(Serializable s) {
|
||||||
s.Write(this);
|
s.Write(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write a char to the buffer.</summary>
|
||||||
public void Write(char c) {
|
public void Write(char c) {
|
||||||
Bytes.AddRange(BitConverter.GetBytes(c));
|
Bytes.AddRange(BitConverter.GetBytes(c));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write a boolean to the buffer.</summary>
|
||||||
public void Write(bool b) {
|
public void Write(bool b) {
|
||||||
Write(b ? (byte)0b1 : (byte)0b0);
|
Write(b ? (byte)0b1 : (byte)0b0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write a double to the buffer.</summary>
|
||||||
public void Write(double d) {
|
public void Write(double d) {
|
||||||
Bytes.AddRange(BitConverter.GetBytes(d));
|
Bytes.AddRange(BitConverter.GetBytes(d));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write a float to the buffer.</summary>
|
||||||
public void Write(float f) {
|
public void Write(float f) {
|
||||||
Bytes.AddRange(BitConverter.GetBytes(f));
|
Bytes.AddRange(BitConverter.GetBytes(f));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write an unsigned long to the buffer.</summary>
|
||||||
public void Write(ulong l) {
|
public void Write(ulong l) {
|
||||||
Bytes.AddRange(BitConverter.GetBytes(l));
|
Bytes.AddRange(BitConverter.GetBytes(l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write an unsigned integer to the buffer.</summary>
|
||||||
public void Write(uint i) {
|
public void Write(uint i) {
|
||||||
Bytes.AddRange(BitConverter.GetBytes(i));
|
Bytes.AddRange(BitConverter.GetBytes(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write an unsigned short to the buffer.</summary>
|
||||||
public void Write(ushort s) {
|
public void Write(ushort s) {
|
||||||
Bytes.AddRange(BitConverter.GetBytes(s));
|
Bytes.AddRange(BitConverter.GetBytes(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write a long to the buffer.</summary>
|
||||||
public void Write(long l) {
|
public void Write(long l) {
|
||||||
Bytes.AddRange(BitConverter.GetBytes(l));
|
Bytes.AddRange(BitConverter.GetBytes(l));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write an integer to the buffer.</summary>
|
||||||
public void Write(int i) {
|
public void Write(int i) {
|
||||||
Bytes.AddRange(BitConverter.GetBytes(i));
|
Bytes.AddRange(BitConverter.GetBytes(i));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write a short to the buffer.</summary>
|
||||||
public void Write(short s) {
|
public void Write(short s) {
|
||||||
Bytes.AddRange(BitConverter.GetBytes(s));
|
Bytes.AddRange(BitConverter.GetBytes(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write a string to the buffer.</summary>
|
||||||
public void Write(string s) {
|
public void Write(string s) {
|
||||||
byte[] bytes = Encoding.UTF8.GetBytes(s);
|
byte[] bytes = Encoding.UTF8.GetBytes(s);
|
||||||
Write(bytes.Length);
|
Write(bytes.Length);
|
||||||
Bytes.AddRange(bytes);
|
Bytes.AddRange(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write a byte to the buffer.</summary>
|
||||||
public void Write(byte b) {
|
public void Write(byte b) {
|
||||||
Bytes.Add(b);
|
Bytes.Add(b);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read weather the given fingerprint is next on the buffer.</summary>
|
||||||
public bool ReadFingerprint(byte[] fingerprint) {
|
public bool ReadFingerprint(byte[] fingerprint) {
|
||||||
foreach (byte b in fingerprint) {
|
foreach (byte b in fingerprint) {
|
||||||
if (!(CanRead() && Read() == b)) {
|
if (!(CanRead() && Read() == b)) {
|
||||||
@ -178,12 +211,14 @@ namespace NeonTea.Quakeball.TeaNet.Packets {
|
|||||||
return reason;
|
return reason;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Write an entire packet using the protocol to the buffer.</summary>
|
||||||
public void WritePacket(Protocol protocol, Packet p) {
|
public void WritePacket(Protocol protocol, Packet p) {
|
||||||
Write(protocol.GetPacketTypeID(p));
|
Write(protocol.GetPacketTypeID(p));
|
||||||
p.WriteMeta(this);
|
p.WriteMeta(this);
|
||||||
p.Write(this);
|
p.Write(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Read an entire packet using the given protocol from the buffer.</summary>
|
||||||
public Packet ReadPacket(Protocol protocol) {
|
public Packet ReadPacket(Protocol protocol) {
|
||||||
int packetType = ReadInt();
|
int packetType = ReadInt();
|
||||||
Type t = protocol.GetPacketType(packetType);
|
Type t = protocol.GetPacketType(packetType);
|
||||||
|
@ -1,26 +1,35 @@
|
|||||||
namespace NeonTea.Quakeball.TeaNet.Packets {
|
namespace NeonTea.Quakeball.TeaNet.Packets {
|
||||||
|
/// <summary>A packet for sending stuff over to connections.</summary>
|
||||||
public abstract class Packet {
|
public abstract class Packet {
|
||||||
|
/// <summary>Packet meta-information: Is this packet reliable. Set just before sending.</summary>
|
||||||
public bool Reliable = true;
|
public bool Reliable = true;
|
||||||
|
/// <summary>Packet meta-information: Id of this packet. Set just before sending.</summary>
|
||||||
public int Id;
|
public int Id;
|
||||||
|
|
||||||
|
/// <summary>Write any relevant information about this packet into the buffer.</summary>
|
||||||
public abstract void Write(ByteBuffer buffer);
|
public abstract void Write(ByteBuffer buffer);
|
||||||
|
/// <summary>Read and assign any relevant information about this packet from the buffer.</summary>
|
||||||
public abstract void Read(ByteBuffer buffer);
|
public abstract void Read(ByteBuffer buffer);
|
||||||
|
|
||||||
|
/// <summary>Reads packet meta-information from the buffer.</summary>
|
||||||
public void ReadMeta(ByteBuffer buffer) {
|
public void ReadMeta(ByteBuffer buffer) {
|
||||||
Id = buffer.ReadInt();
|
Id = buffer.ReadInt();
|
||||||
Reliable = buffer.ReadBool();
|
Reliable = buffer.ReadBool();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Writes packet meta-information to the buffer.</summary>
|
||||||
public void WriteMeta(ByteBuffer buffer) {
|
public void WriteMeta(ByteBuffer buffer) {
|
||||||
buffer.Write(Id);
|
buffer.Write(Id);
|
||||||
buffer.Write(Reliable);
|
buffer.Write(Reliable);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Make a shallow copy for this packet, copying any primitives but retaining any references to instances.</summary>
|
||||||
public Packet ShallowCopy() {
|
public Packet ShallowCopy() {
|
||||||
return (Packet)this.MemberwiseClone();
|
return (Packet)this.MemberwiseClone();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Defines something as writeable/readable by the buffer. Useful for creating abstractions within packets.</summary>
|
||||||
public interface Serializable {
|
public interface Serializable {
|
||||||
void Write(ByteBuffer buffer);
|
void Write(ByteBuffer buffer);
|
||||||
void Read(ByteBuffer buffer);
|
void Read(ByteBuffer buffer);
|
||||||
|
@ -5,25 +5,28 @@ using NeonTea.Quakeball.TeaNet.Peers;
|
|||||||
|
|
||||||
|
|
||||||
namespace NeonTea.Quakeball.TeaNet.Packets {
|
namespace NeonTea.Quakeball.TeaNet.Packets {
|
||||||
|
/// <summary>Manages a single form of conversation between clients for the Peer. Don't forget to register your packets with <see cref="Protocol.RegisterPacket(Type)"/></summary>
|
||||||
public abstract class Protocol {
|
public abstract class Protocol {
|
||||||
private Dictionary<Type, int> PacketToId = new Dictionary<Type, int>();
|
private Dictionary<Type, int> PacketToId = new Dictionary<Type, int>();
|
||||||
private Dictionary<int, Type> IdToPacket = new Dictionary<int, Type>();
|
private Dictionary<int, Type> IdToPacket = new Dictionary<int, Type>();
|
||||||
private int PacketIdCounter;
|
private int PacketIdCounter;
|
||||||
|
|
||||||
|
/// <summary>Refers to the peer it is registered to</summary>
|
||||||
public Peer Peer;
|
public Peer Peer;
|
||||||
|
|
||||||
|
/// <summary>Unique identifier for the protocol. This should be different for every protocol.</summary>
|
||||||
public abstract byte Identifier { get; }
|
public abstract byte Identifier { get; }
|
||||||
|
/// <summary>Version of the protocol, should be changed if existing packets are changed, new packets are registered or old packets are removed.</summary>
|
||||||
public abstract string Version { get; }
|
public abstract string Version { get; }
|
||||||
|
|
||||||
|
/// <summary>Called when the Peer receives a packet from a connection that uses this protocol</summary>
|
||||||
public abstract void Receive(Connection conn, Packet packet);
|
public abstract void Receive(Connection conn, Packet packet);
|
||||||
|
/// <summary>Called when a ConnectionStatus is changed for a connection that uses this protocol</summary>
|
||||||
public abstract void ConnectionStatusChanged(ConnectionStatus oldStatus, ConnectionStatus newStatus, Connection conn);
|
public abstract void ConnectionStatusChanged(ConnectionStatus oldStatus, ConnectionStatus newStatus, Connection conn);
|
||||||
|
/// <summary>Called when a connection that uses this protocol is timed out suddenly.</summary>
|
||||||
public abstract void Timeout(Connection conn);
|
public abstract void Timeout(Connection conn);
|
||||||
|
|
||||||
public void SendPacket(Packet p, Connection conn) {
|
/// <summary>Register a packet for sending and receiving.</summary>
|
||||||
Peer.ConnectionManager.AddPacketToQueue(conn.uid, p);
|
|
||||||
Peer.ConnectionManager.SendPacketQueue(conn.uid);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int RegisterPacket(Type t) {
|
public int RegisterPacket(Type t) {
|
||||||
if (t.BaseType != typeof(Packet) || PacketToId.ContainsKey(t)) {
|
if (t.BaseType != typeof(Packet) || PacketToId.ContainsKey(t)) {
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -6,13 +6,19 @@ using System;
|
|||||||
using NeonTea.Quakeball.TeaNet.Packets;
|
using NeonTea.Quakeball.TeaNet.Packets;
|
||||||
|
|
||||||
namespace NeonTea.Quakeball.TeaNet.Peers {
|
namespace NeonTea.Quakeball.TeaNet.Peers {
|
||||||
|
/// <summary>Represents a connection to a remot host over the internet.</summary>
|
||||||
public class Connection {
|
public class Connection {
|
||||||
|
|
||||||
|
/// <summary>The IP end point of the connection</summary>
|
||||||
public IPEndPoint Endpoint;
|
public IPEndPoint Endpoint;
|
||||||
|
/// <summary>The unique identifier of the connection.</summary>
|
||||||
public ulong uid;
|
public ulong uid;
|
||||||
|
/// <summary>Connection status of the current connection.</summary>
|
||||||
public ConnectionStatus Status;
|
public ConnectionStatus Status;
|
||||||
|
/// <summary>Reason why the connection closed. Null if no reason.</summary>
|
||||||
public ClosingReason ClosingReason;
|
public ClosingReason ClosingReason;
|
||||||
|
|
||||||
|
/// <summary>Internal data for the connection. Do not touch, unless you know what you're doing.</summary>
|
||||||
public ConnectionInternalData Internal = new ConnectionInternalData();
|
public ConnectionInternalData Internal = new ConnectionInternalData();
|
||||||
|
|
||||||
public Connection(IPEndPoint endpoint, ConnectionStatus status = ConnectionStatus.Establishing) {
|
public Connection(IPEndPoint endpoint, ConnectionStatus status = ConnectionStatus.Establishing) {
|
||||||
@ -26,10 +32,12 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
Internal.LatestOutwardUnreliable = -1;
|
Internal.LatestOutwardUnreliable = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Is the connection ready and established for sending packets.</summary>
|
||||||
public bool IsReady() {
|
public bool IsReady() {
|
||||||
return Status == ConnectionStatus.Ready;
|
return Status == ConnectionStatus.Ready;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Is the connection disconnected. Shorthand for weather Status is Rejected, Closed, Stopped or Lost.</summary>
|
||||||
public bool IsDisconnected() {
|
public bool IsDisconnected() {
|
||||||
return !(Status == ConnectionStatus.Ready
|
return !(Status == ConnectionStatus.Ready
|
||||||
|| Status == ConnectionStatus.Awaiting
|
|| Status == ConnectionStatus.Awaiting
|
||||||
@ -38,24 +46,40 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public struct ConnectionInternalData {
|
public struct ConnectionInternalData {
|
||||||
|
/// <summary>The protocol identifier, which this connection uses.</summary>
|
||||||
public byte AssignedProtocol;
|
public byte AssignedProtocol;
|
||||||
|
/// <summary>Last unix timestamp in milliseconds, when this connection was last heard of.</summary>
|
||||||
public long LastMessage;
|
public long LastMessage;
|
||||||
public int LatestOutwardReliable; // Last reliable Packet ID the connection has told us they have
|
/// <summary>Last reliable Packet ID the connection has told us they have</summary>
|
||||||
public int LatestOutwardUnreliable; // Last unreliablePacket ID the connection has told us they have
|
public int LatestOutwardReliable;
|
||||||
public int LatestInwardReliable; // Last reliable Packet ID we've received from the connection
|
/// <summary>Last unreliablePacket ID the connection has told us they have</summary>
|
||||||
public int LatestInwardUnreliable; // Last unreliable Packet ID we've received from the connection
|
public int LatestOutwardUnreliable;
|
||||||
|
/// <summary>Last reliable Packet ID we've received from the connection</summary>
|
||||||
|
public int LatestInwardReliable;
|
||||||
|
/// <summary>Last unreliable Packet ID we've received from the connection</summary>
|
||||||
|
public int LatestInwardUnreliable;
|
||||||
|
|
||||||
public int ReliablePacketIDCounter; // Reliable Packet ID counter for packets we're sending them
|
/// <summary>Reliable Packet ID counter for packets we're sending them</summary>
|
||||||
public int UnreliablePacketIDCounter; // Unreliable Packet ID counter for packets we're sending them
|
public int ReliablePacketIDCounter;
|
||||||
|
/// <summary>Unreliable Packet ID counter for packets we're sending them</summary>
|
||||||
|
public int UnreliablePacketIDCounter;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Initiali</summary>
|
||||||
public enum ConnectionStatus {
|
public enum ConnectionStatus {
|
||||||
Awaiting, // Awaiting an establishing
|
/// <summary>Awaiting the other endpoint to establish the connection.</summary>
|
||||||
Establishing, // Attempting to establish
|
Awaiting,
|
||||||
Ready, // Ready for packet sending
|
/// <summary>Attempting to establish the connection.</summary>
|
||||||
Rejected, // Rejected connection at endpoint, sending Rejected
|
Establishing,
|
||||||
Closed, // Closed connection at endpoint, sending Closed
|
/// <summary>Ready for packet sending</summary>
|
||||||
Stopped, // Not sending packages
|
Ready,
|
||||||
Lost, // Connection Lost
|
/// <summary>Rejected connection at endpoint, sending information that it was rejected.</summary>
|
||||||
|
Rejected,
|
||||||
|
/// <summary>Closed the endpoint, and informing the connection that it should stop.</summary>
|
||||||
|
Closed,
|
||||||
|
/// <summary>Connection is stopped and waiting for timeout.</summary>
|
||||||
|
Stopped,
|
||||||
|
/// <summary>Connection Lost</summary>
|
||||||
|
Lost,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using System;
|
|||||||
using NeonTea.Quakeball.TeaNet.Packets;
|
using NeonTea.Quakeball.TeaNet.Packets;
|
||||||
|
|
||||||
namespace NeonTea.Quakeball.TeaNet.Peers {
|
namespace NeonTea.Quakeball.TeaNet.Peers {
|
||||||
|
/// <summary>Manages connections for Peer, sends them keepalives and sends and handles incoming messages.</summary>
|
||||||
public class ConnectionManager {
|
public class ConnectionManager {
|
||||||
private ulong ConnectionCounter;
|
private ulong ConnectionCounter;
|
||||||
private Dictionary<ulong, Connection> Connections = new Dictionary<ulong, Connection>();
|
private Dictionary<ulong, Connection> Connections = new Dictionary<ulong, Connection>();
|
||||||
@ -28,6 +29,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
UpdateThread.Abort();
|
UpdateThread.Abort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Find a given Connection. Should not be used, unless expecting to establish a connection with the endpoint.</summary>
|
||||||
public Connection Find(IPEndPoint endpoint) {
|
public Connection Find(IPEndPoint endpoint) {
|
||||||
if (IPtoID.ContainsKey(endpoint)) {
|
if (IPtoID.ContainsKey(endpoint)) {
|
||||||
return Connections[IPtoID[endpoint]];
|
return Connections[IPtoID[endpoint]];
|
||||||
@ -37,6 +39,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Start establishing a connection to a given endpoint with the given protocol</summary>
|
||||||
public bool StartConnection(IPEndPoint endpoint, byte protocolIdent) {
|
public bool StartConnection(IPEndPoint endpoint, byte protocolIdent) {
|
||||||
if (IPtoID.ContainsKey(endpoint)) {
|
if (IPtoID.ContainsKey(endpoint)) {
|
||||||
return false;
|
return false;
|
||||||
@ -47,12 +50,14 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Get the connection instance from the given uid, if such exists. Null otherwise.</summary>
|
||||||
public Connection GetConnection(ulong uid) {
|
public Connection GetConnection(ulong uid) {
|
||||||
Connection conn;
|
Connection conn;
|
||||||
Connections.TryGetValue(uid, out conn);
|
Connections.TryGetValue(uid, out conn);
|
||||||
return conn;
|
return conn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Add a reliable packet to the packet queue, to be sent on the next update, or when SendPacketQueue is called.</summary>
|
||||||
public void AddPacketToQueue(ulong uid, Packet p) {
|
public void AddPacketToQueue(ulong uid, Packet p) {
|
||||||
if (!Connections.ContainsKey(uid)) {
|
if (!Connections.ContainsKey(uid)) {
|
||||||
return;
|
return;
|
||||||
@ -62,6 +67,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
PacketQueue[uid].Add(p);
|
PacketQueue[uid].Add(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Send the current packet queue instantly.</summary>
|
||||||
public void SendPacketQueue(ulong uid) {
|
public void SendPacketQueue(ulong uid) {
|
||||||
if (!Connections.ContainsKey(uid)) {
|
if (!Connections.ContainsKey(uid)) {
|
||||||
return;
|
return;
|
||||||
@ -79,6 +85,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Send a single unreliable packet.</summary>
|
||||||
public void SendSingleUnreliable(ulong uid, Packet p) {
|
public void SendSingleUnreliable(ulong uid, Packet p) {
|
||||||
if (!Connections.ContainsKey(uid)) {
|
if (!Connections.ContainsKey(uid)) {
|
||||||
return;
|
return;
|
||||||
|
@ -7,6 +7,7 @@ using System.Threading;
|
|||||||
using NeonTea.Quakeball.TeaNet.Packets;
|
using NeonTea.Quakeball.TeaNet.Packets;
|
||||||
|
|
||||||
namespace NeonTea.Quakeball.TeaNet.Peers {
|
namespace NeonTea.Quakeball.TeaNet.Peers {
|
||||||
|
/// <summary>Manager for the thread that listens from the given endpoint. Initiated with <see cref="Peer.StartListen(string, int)"/></summary>
|
||||||
public class ListenerThread {
|
public class ListenerThread {
|
||||||
private IPEndPoint EndPoint;
|
private IPEndPoint EndPoint;
|
||||||
private Thread Thread;
|
private Thread Thread;
|
||||||
@ -21,7 +22,6 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
Peer = peer;
|
Peer = peer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public bool Start() {
|
public bool Start() {
|
||||||
if (Thread != null) {
|
if (Thread != null) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -6,27 +6,53 @@ using System.Net.Sockets;
|
|||||||
using NeonTea.Quakeball.TeaNet.Packets;
|
using NeonTea.Quakeball.TeaNet.Packets;
|
||||||
|
|
||||||
namespace NeonTea.Quakeball.TeaNet.Peers {
|
namespace NeonTea.Quakeball.TeaNet.Peers {
|
||||||
|
/// <summary>Main class for networking. Remember to register a protocol before using.</summary>
|
||||||
public class Peer : PeerMessageListener {
|
public class Peer : PeerMessageListener {
|
||||||
|
/// <summary>Underlying UdpClient. Do not touch unless you know what you are doing.</summary>
|
||||||
public UdpClient UdpClient { get; private set; }
|
public UdpClient UdpClient { get; private set; }
|
||||||
|
|
||||||
|
/// <summary>The fingerprint for networking. Used to make sure incoming bytes are from a correct source.</summary>
|
||||||
public byte[] Fingerprint { get; private set; }
|
public byte[] Fingerprint { get; private set; }
|
||||||
|
/// <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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public ListenerThread ListenerThread;
|
public ListenerThread ListenerThread;
|
||||||
public ConnectionManager ConnectionManager;
|
public ConnectionManager ConnectionManager;
|
||||||
public Dictionary<byte, Protocol> RegisteredProtocols = new Dictionary<byte, Protocol>();
|
public Dictionary<byte, Protocol> RegisteredProtocols = new Dictionary<byte, Protocol>();
|
||||||
|
|
||||||
|
/// <summary>Listener for messages and errors from within the Peer.</summary>
|
||||||
public PeerMessageListener MessageListener;
|
public PeerMessageListener MessageListener;
|
||||||
|
|
||||||
|
/// <summary>Creates a new Peer with the given fingerprint. The fingerprint can be anything, it just must be same on both peers.</summary>
|
||||||
public Peer(byte[] fingerprint) {
|
public Peer(byte[] fingerprint) {
|
||||||
Fingerprint = fingerprint;
|
Fingerprint = fingerprint;
|
||||||
ConnectionManager = new ConnectionManager(this);
|
ConnectionManager = new ConnectionManager(this);
|
||||||
MessageListener = this;
|
MessageListener = this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Starts the UdpClient, but does no networking as is.</summary>
|
||||||
public void Start(int sending_port) {
|
public void Start(int sending_port) {
|
||||||
UdpClient = new UdpClient(sending_port);
|
UdpClient = new UdpClient(sending_port);
|
||||||
MessageListener.Message("UdpClient Started");
|
MessageListener.Message("UdpClient Started");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Abruptly stops the UdpClient and all relevant threads.</summary>
|
||||||
public void Stop() {
|
public void Stop() {
|
||||||
ConnectionManager.StopThread();
|
ConnectionManager.StopThread();
|
||||||
if (ListenerThread != null) {
|
if (ListenerThread != null) {
|
||||||
@ -36,6 +62,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
UdpClient.Close();
|
UdpClient.Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <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>
|
||||||
public void StartListen(string address, int port) {
|
public void StartListen(string address, int port) {
|
||||||
IPEndPoint endpoint = new IPEndPoint(FindAddress(address), port);
|
IPEndPoint endpoint = new IPEndPoint(FindAddress(address), port);
|
||||||
StartListen(endpoint);
|
StartListen(endpoint);
|
||||||
@ -50,6 +77,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
MessageListener.Message($"Started listening to {endpoint}");
|
MessageListener.Message($"Started listening to {endpoint}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Connect to a remote host. Will initialize a listener to 0.0.0.0:0 if no listener is started.</summary>
|
||||||
public void Connect(string address, int port, byte protocolIdent, bool startListening = true) {
|
public void Connect(string address, int port, byte protocolIdent, bool startListening = true) {
|
||||||
if (startListening) {
|
if (startListening) {
|
||||||
IPEndPoint listenEndpoint = (IPEndPoint)UdpClient.Client.LocalEndPoint;
|
IPEndPoint listenEndpoint = (IPEndPoint)UdpClient.Client.LocalEndPoint;
|
||||||
@ -60,23 +88,28 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
MessageListener.Message($"Connecting to {endpoint}");
|
MessageListener.Message($"Connecting to {endpoint}");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Send a reliable packet, meaning it will reliably be delivered.</summary>
|
||||||
public void SendReliable(ulong uid, Packet packet) {
|
public void SendReliable(ulong uid, Packet packet) {
|
||||||
ConnectionManager.AddPacketToQueue(uid, packet);
|
ConnectionManager.AddPacketToQueue(uid, packet);
|
||||||
ConnectionManager.SendPacketQueue(uid);
|
ConnectionManager.SendPacketQueue(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Add reliable packet to queue, so that it will be sent on the next update.</summary>
|
||||||
public void SendReliableLater(ulong uid, Packet packet) {
|
public void SendReliableLater(ulong uid, Packet packet) {
|
||||||
ConnectionManager.AddPacketToQueue(uid, packet);
|
ConnectionManager.AddPacketToQueue(uid, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Send an unreliable packet, meaning its delivery is not reliable.</summary>
|
||||||
public void SendUnreliable(ulong uid, Packet packet) {
|
public void SendUnreliable(ulong uid, Packet packet) {
|
||||||
ConnectionManager.SendSingleUnreliable(uid, packet);
|
ConnectionManager.SendSingleUnreliable(uid, packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Get a Connection instance from the given uid, if such exists. Null otherwise.</summary>
|
||||||
public Connection GetConnection(ulong uid) {
|
public Connection GetConnection(ulong uid) {
|
||||||
return ConnectionManager.GetConnection(uid);
|
return ConnectionManager.GetConnection(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Register a given protocol. Returns protocol.Identifier if successful, 0 otherwise.</summary>
|
||||||
public byte RegisterProtocol(Protocol protocol) {
|
public byte RegisterProtocol(Protocol protocol) {
|
||||||
byte ident = protocol.Identifier;
|
byte ident = protocol.Identifier;
|
||||||
if (RegisteredProtocols.ContainsKey(ident)) {
|
if (RegisteredProtocols.ContainsKey(ident)) {
|
||||||
@ -87,6 +120,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
return ident;
|
return ident;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Get protocol instance from the given identifier, if such exists.</summary>
|
||||||
public Protocol GetProtocol(byte ident) {
|
public Protocol GetProtocol(byte ident) {
|
||||||
if (RegisteredProtocols.ContainsKey(ident)) {
|
if (RegisteredProtocols.ContainsKey(ident)) {
|
||||||
return RegisteredProtocols[ident];
|
return RegisteredProtocols[ident];
|
||||||
@ -97,7 +131,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
public void Message(string msg) { }
|
public void Message(string msg) { }
|
||||||
public void Err(string msg) { }
|
public void Err(string msg) { }
|
||||||
|
|
||||||
public IPAddress FindAddress(string host) {
|
private IPAddress FindAddress(string host) {
|
||||||
IPAddress addr;
|
IPAddress addr;
|
||||||
try {
|
try {
|
||||||
addr = Dns.GetHostAddresses(host)[0];
|
addr = Dns.GetHostAddresses(host)[0];
|
||||||
@ -108,6 +142,7 @@ namespace NeonTea.Quakeball.TeaNet.Peers {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>Listener for messages and errors from the Peer.</summary>
|
||||||
public interface PeerMessageListener {
|
public interface PeerMessageListener {
|
||||||
void Message(string msg);
|
void Message(string msg);
|
||||||
void Err(string msg);
|
void Err(string msg);
|
||||||
|
Loading…
Reference in New Issue
Block a user