using system; using system.io; using system.net; using system.net.sockets; using system.text; using system.threading; using system.collections.generic; using system.collections.concurrent; namespace mrhassan.network.sockets { public class serversocket { public event action<clientwrapper> onclientconnect, onclientdisconnect; public event action<byte[], int, clientwrapper> onclientreceive; private concurrentdictionary<int, int> bruteforceprotection; private const int timelimit = 1000 * 15; // 1 connection every 10 seconds for one ip private object syncroot; private socket connection; private ushort port; private string ipstring; private bool enabled; private thread thread; public serversocket() { this.connection = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp); this.syncroot = new object(); thread = new thread(dosyncaccept); thread.start(); } public void enable(ushort port, string ip, bool bigsend = false) { this.ipstring = ip; this.port = port; this.connection.bind(new ipendpoint(ipaddress.parse(ipstring), this.port)); this.connection.listen((int)socketoptionname.maxconnections); if (bigsend) { this.connection.receivebuffersize = ushort.maxvalue; this.connection.sendbuffersize = ushort.maxvalue; } this.enabled = true; bruteforceprotection = new concurrentdictionary<int, int>(); } public bool printoutips = false; private void dosyncaccept() { while (true) { if (this.enabled) { try { processsocket(this.connection.accept()); } catch { } } thread.sleep(1); } } private void doasyncaccept(iasyncresult res) { try { socket socket = this.connection.endaccept(res); processsocket(socket); this.connection.beginaccept(doasyncaccept, null); } catch { } } private void processsocket(socket socket) { try { string ip = (socket.remoteendpoint as ipendpoint).address.tostring(); int iphash = ip.gethashcode(); /* if (!program.alexpc) { int time = time32.now.gethashcode(); int oldvalue; if (!bruteforceprotection.trygetvalue(iphash, out oldvalue)) { bruteforceprotection[iphash] = time; } else { if (time - oldvalue < timelimit) { if (printoutips) console.writeline("dropped connection: " + ip); socket.disconnect(false); socket.close(); return; } else { bruteforceprotection[iphash] = time; if (printoutips) console.writeline("allowed connection: " + ip); } } }*/ clientwrapper wrapper = new clientwrapper(); wrapper.create(socket, this, onclientreceive); wrapper.isalive = true; wrapper.ip = ip; if (this.onclientconnect != null) this.onclientconnect(wrapper); } catch { } } public void reset() { this.disable(); this.enable(); } public void disable() { this.enabled = false; this.connection.close(1); } public void enable() { if (!this.enabled) { this.connection = new socket(addressfamily.internetwork, sockettype.stream, protocoltype.tcp); this.connection.bind(new ipendpoint(ipaddress.parse(ipstring), this.port)); this.connection.listen((int)socketoptionname.maxconnections); this.enabled = true; //this.connection.beginaccept(doasyncaccept, null); } } public void invokedisconnect(clientwrapper client) { if (this.onclientdisconnect != null) this.onclientdisconnect(client); } public bool enabled { get { return this.enabled; } } } }
using system; using system.collections.generic; using system.linq; using system.net.sockets; using system.threading; using system.collections.concurrent; using system.runtime.interopservices; using mrhassan.network.cryptography; namespace mrhassan.network.sockets { public class clientwrapper { [dllimport("ws2_32.dll", charset = charset.unicode, setlasterror = true)] public static extern int closesocket(intptr s); [dllimport("ws2_32.dll", charset = charset.unicode, setlasterror = true)] public static extern int shutdown(intptr s, shutdownflags how); public enum shutdownflags : Int { sd_receive = 0, sd_send = 1, sd_both = 2 } public int buffersize; public byte[] buffer; public socket socket; public object owner; public serversocket server; public string ip; public string mac; public bool isalive; public bool overridetiming; private idisposable[] timersubscriptions; private queue<byte[]> sendqueue; private object sendsyncroot; public action<byte[], int, clientwrapper> callback; public void create(socket socket, serversocket server, action<byte[], int, clientwrapper> callback) { callback = callback; buffersize = 2047;//ushort.maxvalue socket = socket; server = server; buffer = new byte[buffersize]; lastreceive = time32.now; overridetiming = false; sendqueue = new queue<byte[]>(); sendsyncroot = new object(); timersubscriptions = new[] { world.subscribe<clientwrapper>(program.world.connectionreview, this, world.genericthreadpool), world.subscribe<clientwrapper>(program.world.connectionreceive, this, world.receivepool), world.subscribe<clientwrapper>(program.world.connectionsend, this, world.sendpool) }; } /// <summary> /// to be called only from a syncrhonized block of code /// </summary> /// <param name="data"></param> public void send(byte[] data) { #if directsend lock (sendsyncroot) socket.send(data); #else lock (sendsyncroot) { sendqueue.enqueue(data); } #endif } public time32 lastreceive; public time32 lastreceivecall; public bool connected; public void disconnect() { lock (socket) { int k = 1000; while (sendqueue.count > 0 && isalive && (k--) > 0) thread.sleep(1); if (!isalive) return; isalive = false; for (int i = 0; i < timersubscriptions.length; i++) timersubscriptions[i].dispose(); shutdown(socket.handle, shutdownflags.sd_both); closesocket(socket.handle); socket.dispose(); } } public static void tryreview(clientwrapper wrapper) { if (wrapper.isalive) { if (wrapper.overridetiming) { if (time32.now > wrapper.lastreceive.addmilliseconds(180000)) wrapper.server.invokedisconnect(wrapper); } else { if (time32.now < wrapper.lastreceivecall.addmilliseconds(2000)) if (time32.now > wrapper.lastreceive.addmilliseconds(60000)) wrapper.server.invokedisconnect(wrapper); } } } private bool isvalid() { if (!isalive) { for (int i = 0; i < timersubscriptions.length; i++) timersubscriptions[i].dispose(); return false; } return true; } private void doreceive(int available) { lastreceive = time32.now; try { if (available > buffer.length) available = buffer.length; int size = socket.receive(buffer, available, socketflags.none); if (size != 0) { if (callback != null) { callback(buffer, size, this); } } else { server.invokedisconnect(this); } } catch (socketexception) { server.invokedisconnect(this); } catch (exception e) { console.writeline(e); } } public static void tryreceive(clientwrapper wrapper) { wrapper.lastreceivecall = time32.now; if (!wrapper.isvalid()) return; try { bool poll = wrapper.socket.poll(0, selectmode.selectread); int available = wrapper.socket.available; if (available > 0) wrapper.doreceive(available); else if (poll) wrapper.server.invokedisconnect(wrapper); } catch (socketexception) { wrapper.server.invokedisconnect(wrapper); } } private bool trydequeuesend(out byte[] buffer) { buffer = null; lock (sendsyncroot) if (sendqueue.count != 0) buffer = sendqueue.dequeue(); return buffer != null; } public static void trysend(clientwrapper wrapper) { if (!wrapper.isvalid()) return; byte[] buffer; while (wrapper.trydequeuesend(out buffer)) { try { wrapper.socket.send(buffer); //wrapper.socket.beginsend(buffer, 0, buffer.length, socketflags.none, endsend, wrapper); } catch { wrapper.server.invokedisconnect(wrapper); } } } private static void endsend(iasyncresult ar) { var wrapper = ar.asyncstate as clientwrapper; try { wrapper.socket.endsend(ar); } catch { wrapper.server.invokedisconnect(wrapper); } } } }