233 lines
7.7 KiB
C#
233 lines
7.7 KiB
C#
using System.Collections.Generic;
|
|
using System;
|
|
using System.Text;
|
|
|
|
namespace NeonTea.Quakeball.TeaNet.Packets {
|
|
/// <summary>Contains a stream of bytes for sending or receiving over the internet.</summary>
|
|
public class ByteBuffer {
|
|
public int Size => Bytes.Count;
|
|
|
|
private List<byte> Bytes;
|
|
private int pos = 0;
|
|
|
|
/// <summary>Creates a new empty ByteBuffer</summary>
|
|
public ByteBuffer() {
|
|
Bytes = new List<byte>();
|
|
}
|
|
|
|
/// <summary>Creates a new ByteBuffer from the given byte[]</summary>
|
|
public ByteBuffer(byte[] bytes) {
|
|
Bytes = new List<byte>(bytes);
|
|
}
|
|
|
|
/// <summary>Packs the byte buffer in to a byte[] array.</summary>
|
|
public byte[] Pack() {
|
|
return Bytes.ToArray();
|
|
}
|
|
|
|
/// <summary>is there a byte to read next?</summary>
|
|
public bool CanRead() {
|
|
return pos < Bytes.Count;
|
|
}
|
|
|
|
/// <summary>Reads a given object with Serializable implemented. Assumes there is one next.</summary>
|
|
public void ReadSerializable(Serializable s) {
|
|
s.Read(this);
|
|
}
|
|
|
|
/// <summary>Read a char on the buffer. Assumes there is one next.</summary>
|
|
public char ReadChar() {
|
|
return BitConverter.ToChar(Read(2), 0);
|
|
}
|
|
|
|
/// <summary>Read a boolean on the buffer. Assumes there is one next.</summary>
|
|
public bool ReadBool() {
|
|
return Read() == 1;
|
|
}
|
|
|
|
/// <summary>Read a double on the buffer. Assumes there is one next.</summary>
|
|
public double ReadDouble() {
|
|
return BitConverter.ToDouble(Read(8), 0);
|
|
}
|
|
|
|
/// <summary>Read a float on the buffer. Assumes there is one next.</summary>
|
|
public float ReadFloat() {
|
|
return BitConverter.ToSingle(Read(4), 0);
|
|
}
|
|
|
|
/// <summary>Read an unsigned long on the buffer. Assumes there is one next.</summary>
|
|
public ulong ReadULong() {
|
|
return BitConverter.ToUInt64(Read(8), 0);
|
|
}
|
|
|
|
/// <summary>Read an unsigned integer on the buffer. Assumes there is one next.</summary>
|
|
public uint ReadUInt() {
|
|
return BitConverter.ToUInt32(Read(4), 0);
|
|
}
|
|
|
|
/// <summary>Read an unsigned short on the buffer. Assumes there is one next.</summary>
|
|
public ushort ReadUShort() {
|
|
return BitConverter.ToUInt16(Read(2), 0);
|
|
}
|
|
|
|
/// <summary>Read a long on the buffer. Assumes there is one next.</summary>
|
|
public long ReadLong() {
|
|
return BitConverter.ToInt64(Read(8), 0);
|
|
}
|
|
|
|
/// <summary>Read an integer on the buffer. Assumes there is one next.</summary>
|
|
public int ReadInt() {
|
|
return BitConverter.ToInt32(Read(4), 0);
|
|
}
|
|
|
|
/// <summary>Read a short on the buffer. Assumes there is one next.</summary>
|
|
public short ReadShort() {
|
|
return BitConverter.ToInt16(Read(2), 0);
|
|
}
|
|
|
|
/// <summary>Read a string on the buffer. Assumes there is one next.</summary>
|
|
public string ReadString() {
|
|
int length = ReadInt();
|
|
string s = Encoding.UTF8.GetString(Read(length));
|
|
return s;
|
|
}
|
|
|
|
/// <summary>Read an integer on the buffer. Assumes there is one next.</summary>
|
|
public byte[] Read(int amount) {
|
|
byte[] bytes = Bytes.GetRange(pos, amount).ToArray();
|
|
pos += amount;
|
|
return bytes;
|
|
}
|
|
|
|
/// <summary>Read the next byte on the buffer. Assumes there is one next.</summary>
|
|
public byte Read() {
|
|
return Bytes[pos++];
|
|
}
|
|
|
|
/// <summary>Write something that implements Serializable.</summary>
|
|
public void Write(Serializable s) {
|
|
s.Write(this);
|
|
}
|
|
|
|
/// <summary>Write a char to the buffer.</summary>
|
|
public void Write(char c) {
|
|
Bytes.AddRange(BitConverter.GetBytes(c));
|
|
}
|
|
|
|
/// <summary>Write a boolean to the buffer.</summary>
|
|
public void Write(bool b) {
|
|
Write(b ? (byte)0b1 : (byte)0b0);
|
|
}
|
|
|
|
/// <summary>Write a double to the buffer.</summary>
|
|
public void Write(double d) {
|
|
Bytes.AddRange(BitConverter.GetBytes(d));
|
|
}
|
|
|
|
/// <summary>Write a float to the buffer.</summary>
|
|
public void Write(float f) {
|
|
Bytes.AddRange(BitConverter.GetBytes(f));
|
|
}
|
|
|
|
/// <summary>Write an unsigned long to the buffer.</summary>
|
|
public void Write(ulong l) {
|
|
Bytes.AddRange(BitConverter.GetBytes(l));
|
|
}
|
|
|
|
/// <summary>Write an unsigned integer to the buffer.</summary>
|
|
public void Write(uint i) {
|
|
Bytes.AddRange(BitConverter.GetBytes(i));
|
|
}
|
|
|
|
/// <summary>Write an unsigned short to the buffer.</summary>
|
|
public void Write(ushort s) {
|
|
Bytes.AddRange(BitConverter.GetBytes(s));
|
|
}
|
|
|
|
/// <summary>Write a long to the buffer.</summary>
|
|
public void Write(long l) {
|
|
Bytes.AddRange(BitConverter.GetBytes(l));
|
|
}
|
|
|
|
/// <summary>Write an integer to the buffer.</summary>
|
|
public void Write(int i) {
|
|
Bytes.AddRange(BitConverter.GetBytes(i));
|
|
}
|
|
|
|
/// <summary>Write a short to the buffer.</summary>
|
|
public void Write(short s) {
|
|
Bytes.AddRange(BitConverter.GetBytes(s));
|
|
}
|
|
|
|
/// <summary>Write a string to the buffer.</summary>
|
|
public void Write(string s) {
|
|
byte[] bytes = Encoding.UTF8.GetBytes(s);
|
|
Write(bytes.Length);
|
|
Bytes.AddRange(bytes);
|
|
}
|
|
|
|
/// <summary>Write a byte to the buffer.</summary>
|
|
public void Write(byte b) {
|
|
Bytes.Add(b);
|
|
}
|
|
|
|
/// <summary>Read weather the given fingerprint is next on the buffer.</summary>
|
|
public bool ReadFingerprint(byte[] fingerprint) {
|
|
foreach (byte b in fingerprint) {
|
|
if (!(CanRead() && Read() == b)) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public PacketStage ReadStage() {
|
|
PacketStage stage = PacketStage.Closed;
|
|
switch (Read()) {
|
|
case 0:
|
|
stage = PacketStage.Establishing;
|
|
break;
|
|
case 1:
|
|
stage = PacketStage.Rejected;
|
|
break;
|
|
case 2:
|
|
stage = PacketStage.Closed;
|
|
break;
|
|
case 3:
|
|
stage = PacketStage.Ready;
|
|
break;
|
|
}
|
|
return stage;
|
|
}
|
|
|
|
public ClosingReason ReadClosingReason() {
|
|
ClosingReason reason = ClosingReason.Unknown;
|
|
switch (Read()) {
|
|
case 0:
|
|
reason = ClosingReason.Unknown;
|
|
break;
|
|
case 1:
|
|
reason = ClosingReason.IncorrectVersion;
|
|
break;
|
|
}
|
|
return reason;
|
|
}
|
|
|
|
/// <summary>Write an entire packet using the protocol to the buffer.</summary>
|
|
public void WritePacket(Protocol protocol, Packet p) {
|
|
Write(protocol.GetPacketTypeID(p));
|
|
p.WriteMeta(this);
|
|
p.Write(this);
|
|
}
|
|
|
|
/// <summary>Read an entire packet using the given protocol from the buffer.</summary>
|
|
public Packet ReadPacket(Protocol protocol) {
|
|
int packetType = ReadInt();
|
|
Type t = protocol.GetPacketType(packetType);
|
|
Packet p = (Packet)Activator.CreateInstance(t);
|
|
p.ReadMeta(this);
|
|
p.Read(this);
|
|
return p;
|
|
}
|
|
}
|
|
} |