1150 lines
40 KiB
C#
1150 lines
40 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.Text;
|
|
using System.Net;
|
|
using System.Net.Sockets;
|
|
using System.Collections;
|
|
using System.Collections.Generic;
|
|
|
|
namespace MrAG
|
|
{
|
|
public class Networking
|
|
{
|
|
public class GamerServicesNetworkingException : Exception{
|
|
public GamerServicesNetworkingException(string msg): base(msg){
|
|
}
|
|
}
|
|
|
|
public class Packet
|
|
{
|
|
#region Packet
|
|
TcpClient Client;
|
|
byte[] Data;
|
|
byte[] Buffer;
|
|
int curpos;
|
|
int recpos;
|
|
bool sending, recieving;
|
|
bool forcestreamclose;
|
|
|
|
public bool ShouldSwapEndian;
|
|
|
|
/// <summary>
|
|
/// Create instance of networking packet
|
|
/// </summary>
|
|
public Packet(){
|
|
this.Data = new byte[0];
|
|
this.Buffer = new byte[0];
|
|
}
|
|
|
|
public Packet(System.Net.Sockets.TcpClient c){
|
|
this.Data = new byte[0];
|
|
this.Buffer = new byte[0];
|
|
this.Client = c;
|
|
}
|
|
|
|
public Packet(TCPClient c){
|
|
this.Data = new byte[0];
|
|
this.Buffer = new byte[0];
|
|
this.Client = c.Connection.GetClient();
|
|
}
|
|
|
|
public Packet(string ip, int port){
|
|
this.Data = new byte[0];
|
|
this.Buffer = new byte[0];
|
|
this.Client = new TcpClient();
|
|
|
|
IAsyncResult ar = this.Client.BeginConnect(ip, port, null, null);
|
|
if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1), false)) {
|
|
this.Client.Close();
|
|
throw new TimeoutException();
|
|
}
|
|
|
|
this.Client.EndConnect(ar);
|
|
}
|
|
|
|
public TcpClient GetClient(){
|
|
return this.Client;
|
|
}
|
|
|
|
public bool Pending(){
|
|
return this.Client.Available > 0;
|
|
}
|
|
|
|
public void Close(){
|
|
this.forcestreamclose = true;
|
|
|
|
this.Buffer = null;
|
|
this.Data = null;
|
|
|
|
this.curpos = 0;
|
|
this.recpos = 0;
|
|
|
|
if (this.Client != null)
|
|
this.Client.Close();
|
|
}
|
|
|
|
public void SetTimeout(int timeout) {
|
|
this.Client.ReceiveTimeout = timeout;
|
|
this.Client.SendTimeout = timeout;
|
|
}
|
|
|
|
public byte[] GetRawSendBuffer() {
|
|
return Data;
|
|
}
|
|
|
|
public byte[] GetRawRecieveBuffer() {
|
|
return Buffer;
|
|
}
|
|
|
|
public void SetRawSendBuffer(byte[] buffer) {
|
|
Data = buffer;
|
|
curpos = buffer.Length > 0 ? buffer.Length - 1 : 0;
|
|
}
|
|
|
|
public void SetRawRecieveBuffer(byte[] buffer) {
|
|
Buffer = buffer;
|
|
recpos = 0;
|
|
}
|
|
|
|
public bool IsStillConnected() {
|
|
return !forcestreamclose;
|
|
}
|
|
|
|
public void Rewind_Send(int num) {
|
|
this.curpos -= num;
|
|
}
|
|
|
|
public void Rewind_Recieve(int num) {
|
|
this.recpos -= num;
|
|
}
|
|
|
|
public byte Shift_Left(byte b, int dist) {
|
|
if ((dist &= 7) == 0){
|
|
return b;
|
|
}
|
|
|
|
return (byte)((b << dist) | (b >> (8 - dist)));
|
|
}
|
|
|
|
public byte Shift_Right(byte b, int dist) {
|
|
if ((dist &= 7) == 0){
|
|
return b;
|
|
}
|
|
|
|
return (byte)((b >> dist) | (b << (8 - dist)));
|
|
}
|
|
|
|
|
|
public void Encrypt(string key) { Encrypt(key, 1, this.Data.Length - 1); }
|
|
public void Encrypt(string key, int startpos) { Encrypt(key, startpos, this.Data.Length - startpos); }
|
|
public void Encrypt(string key, int startpos, int length) {
|
|
key = MrAG.Networking.MD5(key);
|
|
int keynumber = 0;
|
|
|
|
for (int i = 0; i < key.Length; i++) {
|
|
if (char.IsNumber(key[i])) {
|
|
keynumber += int.Parse(key[i].ToString());
|
|
}
|
|
}
|
|
|
|
Encrypt(keynumber, startpos, length);
|
|
}
|
|
|
|
public void Encrypt(int key) { Encrypt(key, 1, this.Data.Length - 1); }
|
|
public void Encrypt(int key, int startpos) { Encrypt(key, startpos, this.Data.Length - startpos); }
|
|
public void Encrypt(int key, int startpos, int length) {
|
|
if (key % 8 == 0)
|
|
key++;
|
|
|
|
for (int i = startpos; i < startpos + length; i++ ) {
|
|
this.Data[i] = Shift_Left(this.Data[i], key);
|
|
}
|
|
}
|
|
|
|
public void Decrypt(string key, int LengthToDecrypt) {
|
|
CheckBuffer(LengthToDecrypt);
|
|
key = MrAG.Networking.MD5(key);
|
|
int keynumber = 0;
|
|
|
|
for (int i = 0; i < key.Length; i++) {
|
|
if (char.IsNumber(key[i])) {
|
|
keynumber += int.Parse(key[i].ToString());
|
|
}
|
|
}
|
|
|
|
Decrypt(keynumber, LengthToDecrypt);
|
|
}
|
|
|
|
public void Decrypt(int key, int LengthToDecrypt) {
|
|
if (key % 8 == 0)
|
|
key++;
|
|
|
|
CheckBuffer(LengthToDecrypt);
|
|
for (int i = this.recpos; i < this.Buffer.Length; i++ ) {
|
|
this.Buffer[i] = Shift_Right(this.Buffer[i], key);
|
|
}
|
|
|
|
this.Rewind_Recieve(LengthToDecrypt);
|
|
}
|
|
|
|
#region Writer
|
|
/// <summary>
|
|
/// Sends an packet whit the ID and infinite arguments
|
|
/// </summary>
|
|
public void Send(byte packetID, int size, params object[] args) {
|
|
Start_Send();
|
|
AddByte(packetID);
|
|
|
|
if (args != null) {
|
|
foreach (object obj in args) {
|
|
Type t = obj.GetType();
|
|
|
|
// texts
|
|
if (t == typeof(string)) AddText((string)obj);
|
|
|
|
// numbers
|
|
else if (t == typeof(short)) AddShort((short)obj);
|
|
else if (t == typeof(int)) AddInt((int)obj);
|
|
else if (t == typeof(float)) AddFloat((float)obj);
|
|
else if (t == typeof(double)) AddDouble((double)obj);
|
|
else if (t == typeof(long)) AddLong((long)obj);
|
|
|
|
// single
|
|
else if (t == typeof(byte)) AddByte((byte)obj);
|
|
else if (t == typeof(bool)) AddBool((bool)obj);
|
|
|
|
// other
|
|
else if (t == typeof(byte[])) AddBytes((byte[])obj);
|
|
}
|
|
}
|
|
Finish_Send();
|
|
}
|
|
|
|
public void SendEncrypted(string encryptionkey, byte packetID, int size, params object[] args) {
|
|
Start_Send();
|
|
AddByte(packetID);
|
|
|
|
if (args != null) {
|
|
foreach (object obj in args) {
|
|
Type t = obj.GetType();
|
|
|
|
// texts
|
|
if (t == typeof(string)) AddText((string)obj);
|
|
|
|
// numbers
|
|
else if (t == typeof(short)) AddShort((short)obj);
|
|
else if (t == typeof(int)) AddInt((int)obj);
|
|
else if (t == typeof(float)) AddFloat((float)obj);
|
|
else if (t == typeof(double)) AddDouble((double)obj);
|
|
else if (t == typeof(long)) AddLong((long)obj);
|
|
|
|
// single
|
|
else if (t == typeof(byte)) AddByte((byte)obj);
|
|
else if (t == typeof(bool)) AddBool((bool)obj);
|
|
|
|
// other
|
|
else if (t == typeof(byte[])) AddBytes((byte[])obj);
|
|
}
|
|
}
|
|
Encrypt(encryptionkey);
|
|
Finish_Send();
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Create instance of networking packet
|
|
/// </summary>
|
|
public void Start_Send(){
|
|
while(this.sending){}
|
|
|
|
this.sending = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Çreate an instance of an networked packet, whit an sendbuffer size, use this to speed up sending by estemating the size in bytes of the packet
|
|
/// </summary>
|
|
public void Start_Send(int sendbuffer){
|
|
while(this.sending){}
|
|
this.Data = new byte[sendbuffer];
|
|
this.curpos = 0;
|
|
|
|
this.sending = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Çreate an instance of an networked packet, whit an sendbuffer size, use this to speed up sending by estemating the size in bytes of the packet
|
|
/// </summary>
|
|
public void Start_Send(long sendbuffer){
|
|
while(this.sending){}
|
|
this.Data = new byte[sendbuffer];
|
|
this.curpos = 0;
|
|
|
|
this.sending = true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Sends the created packet, and then flushes the current data.
|
|
/// </summary>
|
|
public void Finish_Send(){
|
|
if (this.curpos != this.Data.Length - 1){
|
|
byte[] tempb = new byte[this.curpos];
|
|
for (int i = 0; i < this.curpos; i++)tempb[i] = Data[i];
|
|
|
|
Data = tempb;
|
|
}
|
|
try{
|
|
this.Client.GetStream().Write(this.Data, 0, this.Data.Length);
|
|
}catch{
|
|
forcestreamclose = true;
|
|
this.Client.Close();
|
|
}
|
|
|
|
this.Data = new byte[0];
|
|
this.curpos = 0;
|
|
|
|
this.sending = false;
|
|
}
|
|
|
|
private void CheckSize(int count)
|
|
{
|
|
if (Data.Length - curpos < count)
|
|
{
|
|
byte[] tempb = new byte[Data.Length + count];
|
|
Data.CopyTo(tempb, 0);
|
|
|
|
Data = tempb;
|
|
}
|
|
}
|
|
|
|
public void AddByte(byte b)
|
|
{
|
|
this.CheckSize(1);
|
|
|
|
Data[curpos] = b;
|
|
curpos += 1;
|
|
}
|
|
|
|
public void AddByte(int b)
|
|
{
|
|
this.CheckSize(1);
|
|
|
|
Data[curpos] = (byte)b;
|
|
curpos += 1;
|
|
}
|
|
|
|
public void AddBytes(byte[] b)
|
|
{
|
|
this.CheckSize(b.Length + 4);
|
|
this.AddInt(b.Length);
|
|
|
|
for (int i = 0; i < b.Length; i++) Data[curpos + i] = b[i];
|
|
|
|
curpos += b.Length;
|
|
}
|
|
|
|
public void AddBytes(byte[] b, int start, int count)
|
|
{
|
|
this.CheckSize(b.Length + 4);
|
|
this.AddInt(count);
|
|
|
|
for (int i = start; i < start + count; i++) Data[curpos + i] = b[i];
|
|
|
|
curpos += b.Length;
|
|
}
|
|
|
|
public void AddBytesNoLength(byte[] b)
|
|
{
|
|
this.CheckSize(b.Length);
|
|
|
|
for (int i = 0; i < b.Length; i++) Data[curpos + i] = b[i];
|
|
|
|
curpos += b.Length;
|
|
}
|
|
|
|
public void AddBytesNoLength(byte[] b, int start, int count)
|
|
{
|
|
this.CheckSize(b.Length);
|
|
|
|
for (int i = start; i < start + count; i++) Data[curpos + i] = b[i];
|
|
|
|
curpos += b.Length;
|
|
}
|
|
|
|
public void AddShort(short number)
|
|
{
|
|
this.CheckSize(2);
|
|
|
|
number = this.ShouldSwapEndian ? this.SwapEndian(number) : number;
|
|
|
|
Data[curpos + 1] = (byte)((number & 0xff00) >> 8);
|
|
Data[curpos + 0] = (byte)(number & 0x00ff);
|
|
|
|
curpos += 2;
|
|
}
|
|
public void AddInt16(short number){this.AddShort(number);}
|
|
|
|
public void AddInt(int number){
|
|
this.CheckSize(4);
|
|
|
|
number = this.ShouldSwapEndian ? this.SwapEndian(number) : number;
|
|
|
|
this.Data[curpos + 3] = (byte)((number & 0xff000000) >> 24);
|
|
this.Data[curpos + 2] = (byte)((number & 0x00ff0000) >> 16);
|
|
this.Data[curpos + 1] = (byte)((number & 0x0000ff00) >> 8);
|
|
this.Data[curpos + 0] = (byte)(number & 0x000000ff);
|
|
|
|
this.curpos += 4;
|
|
}
|
|
public void AddInt32(int number){this.AddInt(number);}
|
|
|
|
public void AddDouble(double number)
|
|
{
|
|
this.CheckSize(8);
|
|
|
|
number = this.ShouldSwapEndian ? this.SwapEndian(number) : number;
|
|
|
|
byte[] tmpb = BitConverter.GetBytes(number);
|
|
Array.Reverse(tmpb);
|
|
|
|
Data[curpos + 7] = (byte)tmpb[0];
|
|
Data[curpos + 6] = (byte)tmpb[1];
|
|
Data[curpos + 5] = (byte)tmpb[2];
|
|
Data[curpos + 4] = (byte)tmpb[3];
|
|
Data[curpos + 3] = (byte)tmpb[4];
|
|
Data[curpos + 2] = (byte)tmpb[5];
|
|
Data[curpos + 1] = (byte)tmpb[6];
|
|
Data[curpos + 0] = (byte)tmpb[7];
|
|
|
|
curpos += 8;
|
|
}
|
|
|
|
public void AddFloat(float number)
|
|
{
|
|
this.CheckSize(4);
|
|
|
|
number = this.ShouldSwapEndian ? this.SwapEndian(number) : number;
|
|
|
|
byte[] tmpb = BitConverter.GetBytes(number);
|
|
Array.Reverse(tmpb);
|
|
|
|
Data[curpos + 3] = (byte)tmpb[0];
|
|
Data[curpos + 2] = (byte)tmpb[1];
|
|
Data[curpos + 1] = (byte)tmpb[2];
|
|
Data[curpos + 0] = (byte)tmpb[3];
|
|
|
|
curpos += 4;
|
|
}
|
|
public void AddSingle(float number){this.AddFloat(number);}
|
|
|
|
public void AddBool(bool bul)
|
|
{
|
|
this.CheckSize(1);
|
|
if (bul)
|
|
Data[curpos] = (byte)1;
|
|
else
|
|
Data[curpos] = (byte)0;
|
|
|
|
curpos += 1;
|
|
}
|
|
|
|
public void AddLong(long number)
|
|
{
|
|
this.CheckSize(8);
|
|
|
|
number = this.ShouldSwapEndian ? this.SwapEndian(number) : number;
|
|
|
|
byte[] b = System.BitConverter.GetBytes(number);
|
|
for (int i = 0; i < b.Length; i++) Data[i + curpos] = b[i];
|
|
|
|
curpos += 8;
|
|
}
|
|
public void AddInt64(long number){this.AddLong(number);}
|
|
|
|
public void AddString(string text){
|
|
int len = Encoding.UTF8.GetByteCount(text);
|
|
|
|
this.CheckSize(len + 4);
|
|
this.AddInt(len);
|
|
|
|
this.curpos += Encoding.UTF8.GetBytes(text, 0, text.Length, this.Data, this.curpos);
|
|
}
|
|
public void AddText(string text){this.AddString(text);}
|
|
|
|
|
|
public void AddString_ASCII(string text){
|
|
int len = Encoding.ASCII.GetByteCount(text);
|
|
|
|
this.CheckSize(len + 4);
|
|
this.AddInt(len);
|
|
|
|
|
|
this.curpos += Encoding.ASCII.GetBytes(text, 0, text.Length, this.Data, this.curpos);
|
|
}
|
|
|
|
public void AddString_Unicode(string text){
|
|
int len = Encoding.Unicode.GetByteCount(text);
|
|
|
|
this.CheckSize(len + 4);
|
|
this.AddInt(len);
|
|
|
|
|
|
this.curpos += Encoding.Unicode.GetBytes(text, 0, text.Length, this.Data, this.curpos);
|
|
}
|
|
|
|
public void AddStringShort(string text){
|
|
int len = Encoding.UTF8.GetByteCount(text);
|
|
|
|
this.CheckSize(len + 2);
|
|
this.AddShort((short)len);
|
|
|
|
this.curpos += Encoding.UTF8.GetBytes(text, 0, text.Length, this.Data, this.curpos);
|
|
}
|
|
|
|
public void AddStringByte(string text){
|
|
int len = Encoding.UTF8.GetByteCount(text);
|
|
|
|
this.CheckSize(len + 1);
|
|
this.AddByte((byte)len);
|
|
|
|
|
|
|
|
this.curpos += Encoding.UTF8.GetBytes(text, 0, text.Length, this.Data, this.curpos);
|
|
}
|
|
|
|
public void AddStringNullTerminated(string text) {
|
|
int len = Encoding.UTF8.GetByteCount(text);
|
|
|
|
this.CheckSize(len + 1);
|
|
|
|
|
|
this.Data[this.curpos + len] = 0;
|
|
|
|
this.curpos += Encoding.UTF8.GetBytes(text, 0, text.Length, this.Data, this.curpos);
|
|
}
|
|
|
|
public void AddLine(string text){
|
|
byte[] tmpb = Encoding.UTF8.GetBytes(text + "\r\n");
|
|
this.CheckSize(tmpb.Length);
|
|
|
|
for (int i = 0; i < tmpb.Length; i++) this.Data[i + curpos] = tmpb[i];
|
|
|
|
this.curpos += tmpb.Length;
|
|
}
|
|
#endregion
|
|
|
|
#region Reader
|
|
public void Flush(){
|
|
this.Buffer = new byte[0];
|
|
this.recpos = 0;
|
|
}
|
|
|
|
public void Start_Recieve(){
|
|
while(this.recieving){}
|
|
|
|
this.recieving = true;
|
|
}
|
|
|
|
public void Start_Recieve(int buffersize){
|
|
while(this.recieving){}
|
|
this.Buffer = new byte[buffersize];
|
|
this.recpos = 0;
|
|
|
|
this.recieving = true;
|
|
}
|
|
|
|
public void Start_Recieve(long buffersize){
|
|
while(this.recieving){}
|
|
this.Buffer = new byte[buffersize];
|
|
this.recpos = 0;
|
|
|
|
this.recieving = true;
|
|
}
|
|
|
|
public void Finish_Recieve(){
|
|
this.Buffer = new byte[0];
|
|
this.recpos = 0;
|
|
this.recieving = false;
|
|
}
|
|
|
|
private void CheckBuffer(int size){
|
|
if (this.Buffer.Length < this.recpos + size) {
|
|
int oldlen = this.Buffer.Length;
|
|
byte[] tempb = new byte[this.Buffer.Length + size];
|
|
this.Buffer.CopyTo(tempb, 0);
|
|
|
|
this.Buffer = tempb;
|
|
} else
|
|
return;
|
|
|
|
this.Client.GetStream().Read(this.Buffer, recpos, size);
|
|
}
|
|
|
|
public string ReadLine(){
|
|
List<byte> tmpb = new List<byte>();
|
|
|
|
while(true){
|
|
CheckBuffer(1);
|
|
tmpb.Add(this.Buffer[this.recpos]);
|
|
|
|
this.recpos++;
|
|
if (tmpb.Count > 1 && tmpb[tmpb.Count - 2] == '\r' && tmpb[tmpb.Count - 1] == '\n'){
|
|
tmpb.RemoveAt(tmpb.Count - 1);
|
|
tmpb.RemoveAt(tmpb.Count - 1);
|
|
|
|
return Encoding.UTF8.GetString(tmpb.ToArray());
|
|
}
|
|
}
|
|
}
|
|
|
|
public byte ReadByte(){
|
|
this.CheckBuffer(1);
|
|
recpos += 1;
|
|
|
|
return this.Buffer[recpos - 1];
|
|
}
|
|
|
|
public byte[] ReadBytes(){
|
|
int size = this.ReadInt();
|
|
this.CheckBuffer(size);
|
|
|
|
byte[] tmp = new byte[size];
|
|
for (int i = 0; i < size; i++)tmp[i] = this.Buffer[recpos + i];
|
|
|
|
recpos += size;
|
|
return tmp;
|
|
}
|
|
|
|
public byte[] ReadBytes(int size){
|
|
this.CheckBuffer(size);
|
|
|
|
byte[] tmp = new byte[size];
|
|
for (int i = 0; i < size; i++)tmp[i] = this.Buffer[recpos + i];
|
|
//this.Buffer.CopyTo(tmp, recpos);
|
|
|
|
recpos += size;
|
|
return tmp;
|
|
}
|
|
|
|
public bool ReadBool(){
|
|
this.CheckBuffer(1);
|
|
recpos += 1;
|
|
|
|
return this.Buffer[recpos - 1] == (byte)1;
|
|
}
|
|
|
|
public short ReadShort(){
|
|
this.CheckBuffer(2);
|
|
recpos += 2;
|
|
|
|
short res = System.BitConverter.ToInt16(this.Buffer, recpos - 2);
|
|
return this.ShouldSwapEndian ? this.SwapEndian(res) : res;
|
|
}
|
|
|
|
public int ReadInt(){
|
|
this.CheckBuffer(4);
|
|
recpos += 4;
|
|
|
|
int res = System.BitConverter.ToInt32(this.Buffer, recpos - 4);
|
|
return this.ShouldSwapEndian ? this.SwapEndian(res) : res;
|
|
}
|
|
|
|
public float ReadFloat(){
|
|
this.CheckBuffer(4);
|
|
recpos += 4;
|
|
|
|
float res = System.BitConverter.ToSingle(this.Buffer, recpos - 4);
|
|
return this.ShouldSwapEndian ? this.SwapEndian(res) : res;
|
|
}
|
|
|
|
public double ReadDouble(){
|
|
this.CheckBuffer(8);
|
|
recpos += 8;
|
|
|
|
double res = System.BitConverter.ToDouble(this.Buffer, recpos - 8);
|
|
return this.ShouldSwapEndian ? this.SwapEndian(res) : res;
|
|
}
|
|
|
|
public long ReadLong(){
|
|
this.CheckBuffer(8);
|
|
recpos += 8;
|
|
|
|
long res = System.BitConverter.ToInt64(this.Buffer, recpos - 8);
|
|
return this.ShouldSwapEndian ? this.SwapEndian(res) : res;
|
|
}
|
|
|
|
public string ReadString(){
|
|
return this.ReadString(int.MaxValue);
|
|
}
|
|
|
|
public string ReadString(int maxlen){
|
|
int stringlen = this.ReadInt();
|
|
if (stringlen > maxlen)
|
|
return "";
|
|
|
|
if (stringlen > 0) {
|
|
this.CheckBuffer(stringlen);
|
|
|
|
recpos += stringlen;
|
|
|
|
return Encoding.UTF8.GetString(this.Buffer, recpos - stringlen, stringlen);
|
|
} else return "";
|
|
}
|
|
|
|
public string ReadStringShort(){
|
|
return this.ReadStringShort(short.MaxValue);
|
|
}
|
|
|
|
public string ReadStringShort(short maxlen){
|
|
int stringlen = this.ReadShort();
|
|
|
|
if (stringlen > maxlen)
|
|
return "";
|
|
|
|
if (stringlen > 0) {
|
|
this.CheckBuffer(stringlen);
|
|
|
|
recpos += stringlen;
|
|
|
|
return Encoding.UTF8.GetString(this.Buffer, recpos - stringlen, stringlen);
|
|
} else return "";
|
|
}
|
|
|
|
public string ReadStringByte(){
|
|
return this.ReadStringByte(byte.MaxValue);
|
|
}
|
|
|
|
public string ReadStringByte(byte maxlen){
|
|
byte stringlen = this.ReadByte();
|
|
if (stringlen > maxlen)
|
|
return "";
|
|
|
|
if (stringlen > 0) {
|
|
this.CheckBuffer(stringlen);
|
|
|
|
recpos += stringlen;
|
|
|
|
return Encoding.UTF8.GetString(this.Buffer, recpos - stringlen, stringlen);
|
|
} else return "";
|
|
}
|
|
|
|
public string ReadStringNullTerminated(){
|
|
StringBuilder sb = new StringBuilder();
|
|
|
|
while(true){
|
|
CheckBuffer(1);
|
|
this.recpos++;
|
|
if (this.Buffer[this.recpos - 1] != 0) {
|
|
sb.Append(Encoding.UTF8.GetString(this.Buffer, this.recpos - 1, 1));
|
|
} else {
|
|
return sb.ToString();
|
|
}
|
|
}
|
|
}
|
|
|
|
public int GetBufferSize(){
|
|
return this.Buffer.Length;
|
|
}
|
|
#endregion
|
|
|
|
#region Endian Swapping
|
|
public short SwapEndian(short num)
|
|
{
|
|
return (short)((num & 0x00FF) << 8 | (num & 0xFF00) >> 8);
|
|
}
|
|
|
|
public Int32 SwapEndian(Int32 num)
|
|
{
|
|
return (Int32)((num & 0x000000FF) << 24 | (num & 0x0000FF00) << 8 | (num & 0x00FF0000) >> 8 | (num & 0xFF000000) >> 24);
|
|
}
|
|
|
|
public float SwapEndian(float num)
|
|
{
|
|
return BitConverter.ToSingle(BitConverter.GetBytes(SwapEndian(BitConverter.ToInt32(BitConverter.GetBytes(num),0))),0);
|
|
}
|
|
|
|
public double SwapEndian(double num)
|
|
{
|
|
byte[] dblBytes = BitConverter.GetBytes(num);
|
|
byte[] swappedBytes = new byte[8];
|
|
for (int i = 0; i < 8; i++) swappedBytes[i] = dblBytes[7 - i];
|
|
|
|
return BitConverter.ToDouble(swappedBytes, 0);
|
|
}
|
|
|
|
public long SwapEndian(long num)
|
|
{
|
|
byte[] lngBytes = BitConverter.GetBytes(num);
|
|
byte[] swappedBytes = new byte[8];
|
|
for (int i = 0; i < 8; i++) swappedBytes[i] = lngBytes[7 - i];
|
|
|
|
return BitConverter.ToInt64(swappedBytes, 0);
|
|
}
|
|
#endregion
|
|
#endregion
|
|
}
|
|
|
|
public class IncomingConnection{
|
|
public string Username;
|
|
public TCPClient Connection;
|
|
public int Ping;
|
|
public string IP;
|
|
public uint Port;
|
|
public bool FinishedConnecting;
|
|
|
|
public string _KickReason;
|
|
public void Kick(string reason) {
|
|
_KickReason = reason;
|
|
|
|
if (this.FinishedConnecting && this.Connection != null) {
|
|
this.Connection.Close();
|
|
//throw new MrAG.Networking.GamerServicesNetworkingException("Cannot kick an finished connection handle, call Connection.Close() instead!");
|
|
}
|
|
}
|
|
}
|
|
|
|
public class TCPClient{
|
|
public Packet Connection;
|
|
public Action<byte, Packet> OnRecieve;
|
|
public Action OnDisconnect;
|
|
public Action<Packet>[] Packets;
|
|
public bool DebugMode;
|
|
public bool Connected = true;
|
|
|
|
public TCPClient(string ip, int port) {
|
|
TcpClient c = new TcpClient();
|
|
|
|
IAsyncResult ar = c.BeginConnect(ip, port, null, null);
|
|
if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1), false)) {
|
|
c.Close();
|
|
throw new TimeoutException();
|
|
}
|
|
|
|
c.EndConnect(ar);
|
|
|
|
Packets = new Action<Packet>[256];
|
|
Connection = new Packet(c);
|
|
}
|
|
|
|
public TCPClient(Packet connection){
|
|
Packets = new Action<Packet>[256];
|
|
Connection = connection;
|
|
}
|
|
|
|
public TCPClient(System.Net.Sockets.TcpClient connection){
|
|
Packets = new Action<Packet>[256];
|
|
Connection = new Packet(connection);
|
|
}
|
|
|
|
public TCPClient(){
|
|
Packets = new Action<Packet>[256];
|
|
this.Connected = false;
|
|
}
|
|
|
|
public bool Connect(string ip, int port) {
|
|
if (this.Connected)
|
|
this.Close();
|
|
|
|
TcpClient c = new TcpClient();
|
|
|
|
IAsyncResult ar = c.BeginConnect(ip, port, null, null);
|
|
if (!ar.AsyncWaitHandle.WaitOne(TimeSpan.FromSeconds(1), false)) {
|
|
c.Close();
|
|
return false;
|
|
}
|
|
|
|
c.EndConnect(ar);
|
|
|
|
Packets = new Action<Packet>[256];
|
|
Connection = new Packet(c);
|
|
|
|
return true;
|
|
}
|
|
|
|
public bool Alive() {
|
|
return Connection.GetClient().Client.RemoteEndPoint == null;
|
|
}
|
|
|
|
public void Send(byte packetID, int size, params object[] args) {
|
|
Connection.Start_Send(size);
|
|
Connection.AddByte(packetID);
|
|
if (args != null) {
|
|
foreach (object obj in args) {
|
|
Type t = obj.GetType();
|
|
|
|
// texts
|
|
if (t == typeof(string)) Connection.AddText((string)obj);
|
|
|
|
// numbers
|
|
else if (t == typeof(short)) Connection.AddShort((short)obj);
|
|
else if (t == typeof(int)) Connection.AddInt((int)obj);
|
|
else if (t == typeof(float)) Connection.AddFloat((float)obj);
|
|
else if (t == typeof(double)) Connection.AddDouble((double)obj);
|
|
else if (t == typeof(long)) Connection.AddLong((long)obj);
|
|
|
|
// single
|
|
else if (t == typeof(byte)) Connection.AddByte((byte)obj);
|
|
else if (t == typeof(bool)) Connection.AddBool((bool)obj);
|
|
|
|
// other
|
|
else if (t == typeof(byte[])) Connection.AddBytes((byte[])obj);
|
|
else throw new MrAG.Networking.GamerServicesNetworkingException("Unsupported type: " + t.Name + ", value: " + obj.ToString());
|
|
}
|
|
}
|
|
Connection.Finish_Send();
|
|
}
|
|
|
|
public void SendEncrypted(string encryptionkey, byte packetID, int size, params object[] args) {
|
|
this.Connection.Start_Send(size);
|
|
this.Connection.AddByte(packetID);
|
|
|
|
if (args != null) {
|
|
foreach (object obj in args) {
|
|
Type t = obj.GetType();
|
|
System.Diagnostics.Debug.Print("Data type " + t.FullName + ", value: " + obj.ToString());
|
|
|
|
// texts
|
|
if (t == typeof(string)) Connection.AddText((string)obj);
|
|
|
|
// numbers
|
|
else if (t == typeof(short)) Connection.AddShort((short)obj);
|
|
else if (t == typeof(int)) Connection.AddInt((int)obj);
|
|
else if (t == typeof(float)) Connection.AddFloat((float)obj);
|
|
else if (t == typeof(double)) Connection.AddDouble((double)obj);
|
|
else if (t == typeof(long)) Connection.AddLong((long)obj);
|
|
|
|
// single
|
|
else if (t == typeof(byte)) Connection.AddByte((byte)obj);
|
|
else if (t == typeof(bool)) Connection.AddBool((bool)obj);
|
|
|
|
// other
|
|
else if (t == typeof(byte[])) Connection.AddBytes((byte[])obj);
|
|
else throw new MrAG.Networking.GamerServicesNetworkingException("Unsupported type: " + t.Name + ", value: " + obj.ToString());
|
|
}
|
|
}
|
|
this.Connection.Encrypt(encryptionkey);
|
|
this.Connection.Finish_Send();
|
|
}
|
|
|
|
public void Update(){
|
|
if (this.Connected && !this.Connection.IsStillConnected()) {
|
|
this.Connected = false;
|
|
if (this.OnDisconnect != null)
|
|
this.OnDisconnect.DynamicInvoke();
|
|
}
|
|
|
|
if (this.Connected && this.Connection.Pending()) {
|
|
while (this.Connected && this.Connection.Pending()) {
|
|
this.Connection.Start_Recieve();
|
|
byte PacketID = this.Connection.ReadByte();
|
|
if (this.DebugMode) Console.WriteLine("Packet: " + PacketID);
|
|
|
|
if (this.Packets[PacketID] != null) {
|
|
this.Packets[PacketID](this.Connection);
|
|
} else {
|
|
if (this.OnRecieve != null) {
|
|
this.OnRecieve(PacketID, this.Connection);
|
|
} else {
|
|
while (this.Connection.GetClient().GetStream().DataAvailable) {
|
|
this.Connection.GetClient().GetStream().ReadByte();
|
|
}
|
|
|
|
List<byte> remainingcrap = new List<byte>();
|
|
string remainingdata = "";
|
|
while (this.Connection.Pending()) {
|
|
remainingdata += ", " + this.Connection.ReadByte().ToString();
|
|
}
|
|
if (remainingdata.Length > 0) remainingdata = remainingdata.Substring(1);
|
|
this.Connection.Finish_Recieve();
|
|
|
|
throw new GamerServicesNetworkingException("Unhandled packetID: " + PacketID + "\n" + remainingdata);
|
|
}
|
|
}
|
|
if (this.Connection != null)
|
|
this.Connection.Finish_Recieve();
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Close() {
|
|
if (this.Connection != null)
|
|
this.Connection.Close();
|
|
|
|
this.Connected = false;
|
|
this.DebugMode = false;
|
|
this.Packets = null;
|
|
this.OnRecieve = null;
|
|
this.OnDisconnect = null;
|
|
this.Connection = null;
|
|
}
|
|
}
|
|
|
|
|
|
public static string[] PostData(string action, string data){
|
|
Hashtable hashtbl = new Hashtable();
|
|
|
|
foreach (string line in data.Split('&')){
|
|
if (data.Length > 0){
|
|
string[] dat = line.Split('=');
|
|
hashtbl[dat[0]] = dat[1];
|
|
}
|
|
}
|
|
|
|
return PostData(action, hashtbl);
|
|
}
|
|
|
|
public static string MD5(string input) {
|
|
System.Security.Cryptography.MD5CryptoServiceProvider x = new System.Security.Cryptography.MD5CryptoServiceProvider();
|
|
byte[] bs = System.Text.Encoding.UTF8.GetBytes(input);
|
|
|
|
bs = x.ComputeHash(bs);
|
|
System.Text.StringBuilder s = new System.Text.StringBuilder();
|
|
|
|
foreach (byte b in bs)
|
|
{
|
|
s.Append(b.ToString("x2"));
|
|
}
|
|
|
|
return s.ToString().ToLower();
|
|
}
|
|
|
|
|
|
private static string[] PostData(string action, Hashtable values){
|
|
try{
|
|
Networking.WebPostRequest c = new Networking.WebPostRequest("http://gs.mrag.nl/api");
|
|
c.Add("action", action);
|
|
string SessID = Gamerservices.GetSessID();
|
|
if (SessID != null && SessID.Length > 0) c.Add("sess", SessID);
|
|
|
|
foreach (DictionaryEntry entry in values){
|
|
c.Add((string)entry.Key, (string)entry.Value);
|
|
}
|
|
|
|
string[] res = c.GetResponse().Split('\n');
|
|
|
|
if (Gamerservices.GetDebug()){
|
|
string[] keys = new string[res.Length + values.Count + 2];
|
|
string[] vals = new string[res.Length + values.Count + 2];
|
|
|
|
int id = 0;
|
|
foreach (DictionaryEntry entry in values){
|
|
keys[id] = (string)entry.Key;
|
|
vals[id] = (string)entry.Value;
|
|
id++;
|
|
}
|
|
|
|
keys[id + 1] = "Responses";
|
|
vals[id + 1] = res.Length.ToString();
|
|
|
|
for (int i = 0; i < res.Length; i++){
|
|
keys[id + 2 + i] = i.ToString();
|
|
vals[id + 2 + i] = res[i];
|
|
}
|
|
|
|
Gamerservices.Print("WebPost", keys, vals);
|
|
}
|
|
|
|
if (res[0] == "no"){
|
|
throw new GamerServicesNetworkingException(res[1]);
|
|
}else{
|
|
string[] arr = new string[res.Length - 1];
|
|
for (int i = 1; i < res.Length; i++){
|
|
arr[i - 1] = res[i];
|
|
}
|
|
|
|
return arr;
|
|
}
|
|
}catch{
|
|
string[] keys = new string[values.Count];
|
|
string[] vals = new string[values.Count];
|
|
|
|
int id = 0;
|
|
foreach (DictionaryEntry entry in values){
|
|
keys[id] = (string)entry.Key;
|
|
vals[id] = (string)entry.Value;
|
|
id++;
|
|
}
|
|
|
|
Gamerservices.Print("FATALERROR AT WEBPOST", keys, vals);
|
|
|
|
return new string[0];
|
|
}
|
|
}
|
|
|
|
public class WebPostRequest
|
|
{
|
|
public bool broken = false;
|
|
public StreamReader sr;
|
|
public ArrayList theQueryData;
|
|
public WebRequest theRequest;
|
|
public HttpWebResponse theResponse;
|
|
|
|
public WebPostRequest(string url)
|
|
{
|
|
try{
|
|
this.theRequest = WebRequest.Create(url);
|
|
this.theRequest.Method = "POST";
|
|
}catch{
|
|
System.Diagnostics.Debug.Print("Server uri in properties is invalid!");
|
|
this.broken = true;
|
|
}
|
|
this.theQueryData = new ArrayList();
|
|
}
|
|
|
|
public WebPostRequest(string url, bool a)
|
|
{
|
|
try{
|
|
this.theRequest = WebRequest.Create(url);
|
|
}catch{
|
|
System.Diagnostics.Debug.Print("Server uri in properties is invalid!");
|
|
this.broken = true;
|
|
}
|
|
|
|
this.theQueryData = new ArrayList();
|
|
}
|
|
|
|
public void Add(string key, string value)
|
|
{
|
|
if (!this.broken){
|
|
this.theQueryData.Add(string.Format("{0}={1}", key, value));
|
|
}else{
|
|
System.Diagnostics.Debug.Print("Server uri in properties is invalid!");
|
|
}
|
|
}
|
|
|
|
public string GetResponse()
|
|
{
|
|
if (!this.broken)
|
|
{
|
|
this.theRequest.ContentType = "application/x-www-form-urlencoded";
|
|
string str = string.Join("&", (string[])this.theQueryData.ToArray(typeof(string)));
|
|
this.theRequest.ContentLength = str.Length;
|
|
this.theRequest.Proxy = null;
|
|
|
|
try{
|
|
StreamWriter writer = new StreamWriter(this.theRequest.GetRequestStream());
|
|
writer.Write(str);
|
|
writer.Close();
|
|
}catch{
|
|
return "";
|
|
}
|
|
|
|
try{
|
|
this.theResponse = (HttpWebResponse)this.theRequest.GetResponse();
|
|
this.sr = new StreamReader(this.theResponse.GetResponseStream());
|
|
}catch (Exception e){
|
|
System.Diagnostics.Debug.Print(e.Message);
|
|
return "";
|
|
}
|
|
|
|
try{
|
|
return this.sr.ReadToEnd();
|
|
}catch{
|
|
return "";
|
|
}
|
|
}
|
|
|
|
throw new MrAG.Networking.GamerServicesNetworkingException("Server uri in properties is invalid!");
|
|
}
|
|
}
|
|
}
|
|
} |