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