private void Init(string url, uint conv) { if (conv == 0) { PlatDependant.LogError("KCP conversation id should not be 0."); } _Connection = new UDPClient(url); _Conv = conv; _ConnectionHandle = GCHandle.Alloc(_Connection); _KCP = KCPLib.kcp_create(conv, (IntPtr)_ConnectionHandle); _KCP.kcp_setoutput(Func_KCPOutput); _KCP.kcp_nodelay(1, 10, 2, 1); // set minrto to 10? _Connection.UpdateInterval = 10; _Connection.PreDispose = _con => DisposeSelf(); _Connection.OnReceive = (data, cnt, sender) => _KCP.kcp_input(data, cnt); _Connection.OnSend = (data, cnt) => { if (cnt > CONST.MTU) { int offset = 0; var buffer = BufferPool.GetBufferFromPool(); while (cnt > CONST.MTU) { Buffer.BlockCopy(data, offset, buffer, 0, CONST.MTU); _KCP.kcp_send(buffer, CONST.MTU); cnt -= CONST.MTU; offset += CONST.MTU; } if (cnt > 0) { Buffer.BlockCopy(data, offset, buffer, 0, cnt); _KCP.kcp_send(buffer, cnt); } BufferPool.ReturnBufferToPool(buffer); } else { _KCP.kcp_send(data, cnt); } return(true); }; _Connection.OnUpdate = _con => { _KCP.kcp_update((uint)Environment.TickCount); int recvcnt = _KCP.kcp_recv(_RecvBuffer, CONST.MTU); if (_OnReceive != null) { if (recvcnt > 0) { _OnReceive(_RecvBuffer, recvcnt, _Connection.RemoteEndPoint); } } }; }
public KCPConsultClient(string url) : base(url, 1) { _Conv = 0; _Connection.OnUpdate = _con => { _KCP.kcp_update((uint)Environment.TickCount); int recvcnt = _KCP.kcp_recv(_RecvBuffer, CONST.MTU); if (_Conv == 0) { if (recvcnt >= 4) { uint conv = 0; if (BitConverter.IsLittleEndian) { conv = BitConverter.ToUInt32(_RecvBuffer, 0); } else { for (int i = 0; i < 4; ++i) { conv <<= 8; conv += _RecvBuffer[i]; } } if (conv == 0 || conv == 1) { PlatDependant.LogError("KCP conversation id should not be 0 or 1 (with Consult)."); throw new ArgumentException("KCP conversation id should not be 0 or 1 (with Consult)."); } _KCP.kcp_release(); _Conv = conv; _KCP = KCPLib.kcp_create(conv, (IntPtr)_ConnectionHandle); _KCP.kcp_setoutput(Func_KCPOutput); _KCP.kcp_nodelay(1, 10, 2, 1); _Connection.HoldSending = false; } } else { if (_OnReceive != null) { if (recvcnt > 0) { _OnReceive(_RecvBuffer, recvcnt, _Connection.RemoteEndPoint); } } } }; _Connection.PreStart = _con => { var guid = _ConnectionGUID.ToByteArray(); _KCP.kcp_send(guid, guid.Length); }; _Connection.HoldSending = true; }
protected internal ServerConnection(KCPConsultServer server, uint pendingconv) : base(server) { _PendingConv = pendingconv; _Conv = 0; _KCP = KCPLib.kcp_create(1, (IntPtr)_InfoHandle); _Ready = true; _KCP.kcp_setoutput(Func_KCPOutput); _KCP.kcp_nodelay(1, 10, 2, 1); // set minrto to 10? }
public void SetConv(uint conv) { if (_Ready) { PlatDependant.LogError("Can not change conv. Please create another one."); } else { _Conv = conv; _KCP = KCPLib.kcp_create(conv, (IntPtr)_InfoHandle); _Ready = true; _KCP.kcp_setoutput(Func_KCPOutput); _KCP.kcp_nodelay(1, 10, 2, 1); // set minrto to 10? } }
protected internal override bool Feed(byte[] data, int cnt, IPEndPoint ep) { if (_Conv == 0) { // this means the conv has not been accepted by client. var conv = ReadConv(data, cnt); if (conv == 0) { // wrong packet. return(false); } else if (conv == 1) { // the unaccepted connection var guid = ReadGUID(data, cnt); if (guid == Guid.Empty) { if (EP != null && EP.Equals(ep)) { // this means the ack-packet or something else. return(_KCP.kcp_input(data, cnt) == 0); } else { // client should provide a guid for new connection return(false); } } else { if (_PendingGUID == Guid.Empty) { // accept this connection. bind this connection with the guid. if (_KCP.kcp_input(data, cnt) == 0) { _PendingGUID = guid; EP = ep; // send the pending conv-id to client. byte[] buffer = BufferPool.GetBufferFromPool(); if (BitConverter.IsLittleEndian) { var pconv = _PendingConv; for (int i = 0; i < 4; ++i) { buffer[i] = (byte)((pconv >> (i * 8)) & 0xFF); } } else { var pconv = _PendingConv; for (int i = 0; i < 4; ++i) { buffer[i] = (byte)((pconv >> ((3 - i) * 8)) & 0xFF); } } _KCP.kcp_send(buffer, 4); BufferPool.ReturnBufferToPool(buffer); _Connected = true; return(true); } else { return(false); } } else { // check the guid. if (_PendingGUID == guid) { if (_KCP.kcp_input(data, cnt) == 0) { if (!ep.Equals(EP)) { // check the ep changed? EP = ep; } return(true); } else { return(false); } } else { return(false); } } } } else { // the first packet from accepted connection? if (conv == _PendingConv) { // the first packet from accepted connection! // change the kcp to real conv-id. _Conv = conv; _KCP.kcp_release(); _KCP = KCPLib.kcp_create(conv, (IntPtr)_InfoHandle); _KCP.kcp_setoutput(Func_KCPOutput); _KCP.kcp_nodelay(1, 10, 2, 1); // set minrto to 10? if (!ep.Equals(EP)) { // check the ep changed? EP = ep; } // Feed the data. return(_KCP.kcp_input(data, cnt) == 0); } else { // this packet is for other connection. return(false); } } } else { // the normal connection. return(base.Feed(data, cnt, ep)); } }