sockscape/server/Libraries/Kneesocks/Connection.cs

144 lines
4.4 KiB
C#
Raw Normal View History

2017-04-21 21:04:03 +00:00
using System;
using System.Collections.Generic;
using System.Linq;
2017-04-23 04:55:29 +00:00
using System.Net.Sockets;
2017-04-21 21:04:03 +00:00
using System.Text;
using System.Threading.Tasks;
2017-05-09 12:22:04 +00:00
using Square;
2017-04-21 21:04:03 +00:00
namespace Kneesocks {
2017-05-04 12:21:27 +00:00
public class Connection {
public UInt64? _Id = null;
public UInt64 Id {
get {
if(_Id == null)
throw new ArgumentNullException();
else
return (UInt64)_Id;
}
set {
if(_Id == null)
_Id = value;
}
}
2017-04-23 04:55:29 +00:00
private TcpClient Socket;
private NetworkStream Stream;
2017-05-05 21:05:52 +00:00
ReadBuffer Buffer;
private Frame PartialFrame = null;
2017-05-04 21:09:38 +00:00
private List<Frame> FrameBuffer = new List<Frame>();
public bool Disconnected { get; private set; } = false;
public string DisconnectReason { get; private set; } = null;
public bool Handshaked { get; private set; } = false;
2017-05-08 21:06:17 +00:00
public Handshake ClientHandshake { get; private set; } = null;
2017-04-23 04:55:29 +00:00
2017-05-04 12:21:27 +00:00
public Connection(TcpClient sock) {
2017-04-23 04:55:29 +00:00
Socket = sock;
Socket.ReceiveTimeout = 1;
Stream = sock.GetStream();
2017-05-05 21:05:52 +00:00
Buffer = new ReadBuffer(Stream);
2017-04-23 04:55:29 +00:00
}
2017-05-04 12:21:27 +00:00
public Connection(UInt64 id, TcpClient sock) : this(sock) {
Id = id;
}
2017-05-05 21:05:52 +00:00
public Connection(Connection conn, bool preserveId = true) {
if(preserveId)
_Id = conn._Id;
Socket = conn.Socket;
2017-05-05 21:05:52 +00:00
Stream = conn.Stream;
Buffer = conn.Buffer;
PartialFrame = conn.PartialFrame;
FrameBuffer = conn.FrameBuffer;
Disconnected = conn.Disconnected;
DisconnectReason = conn.DisconnectReason;
Handshaked = conn.Handshaked;
2017-05-08 21:06:17 +00:00
ClientHandshake = conn.ClientHandshake;
2017-05-05 21:05:52 +00:00
}
2017-05-04 21:09:38 +00:00
public byte[] Parse() {
2017-05-05 21:05:52 +00:00
byte[] readBuffer = null;
if(Buffer.IsReading) {
readBuffer = Buffer.AttemptRead();
2017-05-08 21:06:17 +00:00
if(readBuffer == null) {
if(Buffer.ElapsedReadTime.Seconds > 30)
Disconnect(Frame.kClosingReason.ProtocolError, "Timed out waiting for a full response");
2017-05-05 21:05:52 +00:00
return null;
2017-05-08 21:06:17 +00:00
}
2017-05-05 21:05:52 +00:00
}
2017-05-04 21:09:38 +00:00
if(!Handshaked) {
2017-05-08 21:06:17 +00:00
if(!Buffer.IsReading) {
readBuffer = Buffer.AttemptRead("\r\n\r\n");
if(readBuffer == null)
return null;
}
try {
Handshake request = new Handshake(Encoding.ASCII.GetString(readBuffer));
var response = Handshake.AcceptRequest(request).ToBytes();
Stream.Write(response, 0, response.Length);
ClientHandshake = request;
Handshaked = true;
} catch(Exception e) {
Disconnect(Frame.kClosingReason.ProtocolError, e.Message);
return null;
}
2017-05-04 21:09:38 +00:00
2017-05-08 21:06:17 +00:00
OnOpen();
2017-05-05 21:05:52 +00:00
return null;
2017-05-04 21:09:38 +00:00
}
2017-05-08 21:06:17 +00:00
/*if(!Buffer.IsReading) {
readBuffer = Buffer.AttemptRead("\r\n\r\n");
if(readBuffer == null)
return null;
}*/
OnParse();
return null;
2017-05-04 21:09:38 +00:00
}
public void Disconnect(string reason = null) {
Disconnect(Frame.kClosingReason.Normal, reason);
}
public void Disconnect(Frame.kClosingReason status, string reason = null) {
Disconnected = true;
DisconnectReason = reason;
if(Socket.Connected) {
Socket.SendTimeout = 1000;
var raw = Handshaked ? Frame.Closing(status, reason).GetBytes()
: Handshake.DenyRequest().ToString().GetBytes();
Stream.Write(raw, 0, raw.Length);
Socket.Close();
}
OnClose();
}
// called after the client successfully handshakes
2017-05-05 21:05:52 +00:00
protected virtual void OnOpen() { }
2017-05-04 12:21:27 +00:00
// called when the thread manager iterates through
// the thread list and stops on this thread
2017-05-05 21:05:52 +00:00
protected virtual void OnParse() { }
// called when data has been received
2017-05-05 21:05:52 +00:00
protected virtual void OnReceive(byte[] data) { }
2017-04-23 04:55:29 +00:00
// called when the connection is disconnected
2017-05-05 21:05:52 +00:00
protected virtual void OnClose() { }
2017-04-21 21:04:03 +00:00
}
}