void OnTimer(object argstate) { if (_closed) { _timer.Dispose(); return; } if (_postmap.Count == 0) { return; } if (DateTime.Now - _timerlastitem.SendTime < TimeSpan.FromMilliseconds(GetPackageLostMS())) { return; } if (_timerlastitem.PingCount > 10) { return; } _timerlastitem.PingCount++; SendToPeer(UDPMeta.CreateDataPing(SessionId, _readminindex, _timerlastitem.DataIndex)); }
async Task ReadLoopAsync() { await Task.Yield(); while (true) { //TODO: if not cached , and all stream closed , shutdown directly var data = await ReceiveAsync(); if (data == null) { Console.WriteLine("_udp.ReceiveAsync() return null ,Close()"); Close(); return; } long sid = BitConverter.ToInt64(data, 8); if (sid == -1) { Console.WriteLine("_udp.ReceiveAsync() return " + sid + ", " + UDPMeta.GetPackageType(data)); } UDPBufferReader reader = GetBufferReader(sid); reader.OnPost(data); } }
public override void Close() { _closed = true; if (_timer != null) { _timer.Dispose(); } base.Close(); if (!_closesend) { _closesend = true; SendToPeer(UDPMeta.CreateSessionError(SessionId, "Close")); } }
public void Process(UDPPackageType pt, byte[] data) { if (_waitfor == pt) { TcpMapService.LogMessage("UDPServer:" + pt); if (pt == UDPPackageType.SessionConnect) { UDPConnectJson udpc = UDPConnectJson.Deserialize(Encoding.UTF8.GetString(data, 16, data.Length - 16)); if (udpc.token != this.ConnectToken) { _sl.RejectConnect(this); return; } byte[] buffprepair = UDPMeta.CreateSessionPrepair(SessionId, ConnectToken); SendToPeer(buffprepair); SendToPeer(buffprepair); _waitfor = UDPPackageType.SessionConfirm; return; } if (pt == UDPPackageType.SessionConfirm) { UDPConnectJson udpc = UDPConnectJson.Deserialize(Encoding.UTF8.GetString(data, 16, data.Length - 16)); if (udpc.token != this.ConnectToken) { _sl.RejectConnect(this); return; } byte[] buffready = UDPMeta.CreateSessionReady(SessionId, ConnectToken); SendToPeer(buffready); SendToPeer(buffready); _waitfor = UDPPackageType.SessionIdle; _reader = new BufferedReader(cts.Token); ThreadPool.QueueUserWorkItem(delegate { _sl._onstream(this, RemoteEndPoint); }); return; } if (pt == UDPPackageType.SessionIdle) { SendToPeer(UDPMeta.CreateSessionIdle(SessionId)); return; } } else { ProcessUDPPackage(pt, data); } }
private void RejectConnect(ServerStream stream) { long sid = stream.SessionId; bool removed = false; lock (this.strmap) { if (this.strmap.TryGetValue(sid, out ServerStream ss)) { if (ss == stream) { this.strmap.Remove(sid); removed = true; } } } if (removed) { this.udp.SendToClient(stream.RemoteEndPoint, UDPMeta.CreateSessionError(sid, "Reject")); } }
protected void ProcessUDPPackage(UDPPackageType pt, byte[] data) { //UDPPackageType pt = UDPMeta.GetPackageType(data); long sid = BitConverter.ToInt64(data, 8); //Console.WriteLine("ProcessUDPPackage:" + sid + ":" + pt); if (pt == UDPPackageType.SessionError) { this.Close(); } else if (pt == UDPPackageType.SessionClose) { this.Close(); } if (pt == UDPPackageType.DataPost) { if (this.closed) { this.SendToPeer(UDPMeta.CreateSessionError(this.SessionId, "closed")); return; } long peerminreadindex = BitConverter.ToInt64(data, 16); lock (this.postmap) { this.OnGetPeerMinRead(peerminreadindex); } long dataindex = BitConverter.ToInt64(data, 24); //Console.WriteLine("DataPost:" + dataindex); if (dataindex == this.readminindex + 1) { this.OnPost(data, 32, data.Length - 32); this.readminindex = dataindex; while (this.buffmap.TryGetValue(this.readminindex + 1, out byte[] buff))
void ClientWorkThread() { try { while (true) { //TODO:when timeout , try to send idle message byte[] data = _udp.Receive(SessionId, TimeSpan.FromSeconds(40)); if (data == null) { if (!_reader._removed) { Console.WriteLine("UDPClientStream.ClientWorkThread.Timeout-40"); } _reader.OnRemoved(); base.OnWorkerThreadExit(); return; } try { UDPPackageType pt = UDPMeta.GetPackageType(data); ProcessUDPPackage(pt, data); } catch (Exception x) { TcpMapService.OnError(x); } } } catch (Exception x) { TcpMapService.OnError(x); } }
//public override ValueTask WriteAsync(ReadOnlyMemory<byte> buffer, CancellationToken cancellationToken = default) //{ // return base.WriteAsync(buffer, cancellationToken); //} public override void Write(byte[] buffer, int offset, int count) { if (_closed) { throw (new Exception("stream closed")); } //Console.WriteLine("UDPBaseStream write " + count); while (count > UDPMeta.BestUDPSize) { Write(buffer, offset, UDPMeta.BestUDPSize); offset += UDPMeta.BestUDPSize; count -= UDPMeta.BestUDPSize; } DataItem item = new DataItem(); item.DataIndex = ++nextdataindex; item.UDPData = UDPMeta.CreateDataPost(SessionId, _readminindex, item.DataIndex, buffer, offset, count); lock (_postmap) { _postmap[item.DataIndex] = item; } item.SendTime = DateTime.Now; SendToPeer(item.UDPData); _timerlastitem = item; if (_timer == null) { _timer = new Timer(OnTimer, null, 100, 100); } }
protected void ProcessUDPPackage(UDPPackageType pt, byte[] data) { //UDPPackageType pt = UDPMeta.GetPackageType(data); long sid = BitConverter.ToInt64(data, 8); //Console.WriteLine("ProcessUDPPackage:" + sid + ":" + pt); if (pt == UDPPackageType.SessionError) { Close(); } else if (pt == UDPPackageType.SessionClose) { Close(); } if (pt == UDPPackageType.DataPost) { if (_closed) { SendToPeer(UDPMeta.CreateSessionError(SessionId, "closed")); return; } long peerminreadindex = BitConverter.ToInt64(data, 16); lock (_postmap) { OnGetPeerMinRead(peerminreadindex); } long dataindex = BitConverter.ToInt64(data, 24); //Console.WriteLine("DataPost:" + dataindex); if (dataindex == _readminindex + 1) { OnPost(data, 32, data.Length - 32); _readminindex = dataindex; byte[] buff; while (_buffmap.TryGetValue(_readminindex + 1, out buff)) { _readminindex++; _buffmap.Remove(_readminindex); OnPost(buff); } SendToPeer(UDPMeta.CreateDataRead(SessionId, _readminindex, dataindex)); } else { if (dataindex > _readmaxindex) { _readmaxindex = dataindex; } byte[] buff = new byte[data.Length - 32]; Buffer.BlockCopy(data, 32, buff, 0, buff.Length); _buffmap[dataindex] = buff; } } if (pt == UDPPackageType.DataRead) { long peerminreadindex = BitConverter.ToInt64(data, 16); long dataindex = BitConverter.ToInt64(data, 24); lock (_postmap) { PostMapRemove(dataindex); OnGetPeerMinRead(peerminreadindex); } } if (pt == UDPPackageType.DataMiss) { long peerminreadindex = BitConverter.ToInt64(data, 16); lock (_postmap) { OnGetPeerMinRead(peerminreadindex); } int misscount = (data.Length - 24) / 8; List <DataItem> list = null; for (int missid = 0; missid < misscount; missid++) { long dataindex = BitConverter.ToInt64(data, 24 + missid * 8); DataItem item = null; lock (_postmap) { _postmap.TryGetValue(dataindex, out item); } if (item != null) { if (list == null) { list = new List <DataItem>(); } list.Add(item); } } if (list != null) { list.Sort(delegate(DataItem d1, DataItem d2) { return(d1.SendTime.CompareTo(d2.SendTime)); }); int maxsendagain = 65536; foreach (DataItem item in list) { if (DateTime.Now - item.SendTime < TimeSpan.FromMilliseconds(GetPackageLostMS())) { break; } if (maxsendagain < item.UDPData.Length) { break; } maxsendagain -= item.UDPData.Length; UDPMeta.UpdateDataRead(item.UDPData, _readminindex); item.SendTime = DateTime.Now; item.RetryCount++; SendToPeer(item.UDPData); } } } if (pt == UDPPackageType.DataPing) { long peerminreadindex = BitConverter.ToInt64(data, 16); lock (_postmap) { OnGetPeerMinRead(peerminreadindex); } long maxdataindex = BitConverter.ToInt64(data, 24); List <long> misslist = null; for (long index = _readminindex + 1; index <= maxdataindex; index++) { if (_buffmap.ContainsKey(index)) { continue; } if (misslist == null) { misslist = new List <long>(); } misslist.Add(index); if (misslist.Count * 8 + 40 > UDPMeta.BestUDPSize) { break; } } if (misslist != null) { SendToPeer(UDPMeta.CreateDataMiss(SessionId, _readminindex, misslist.ToArray())); } else { SendToPeer(UDPMeta.CreateDataRead(SessionId, _readminindex, _readminindex)); } } }
void ListenerWorkThread() { while (this._workthread != null) { try { //TODO: if not cached , and all stream closed , shutdown directly IPEndPoint ep; byte[] data = _udp.Receive(TimeSpan.FromSeconds(90), out ep); if (data == null) { Console.WriteLine("_udp.Receive return null for a long time...; Shutdown..." + this._udp.LocalEndPoint); this.Close(); return; } UDPPackageType pt = UDPMeta.GetPackageType(data); if (pt == UDPPackageType.Unknown) { //Console.WriteLine("_udp.Receive return Unknown;"); return; } long sid = BitConverter.ToInt64(data, 8); ServerStream ss; //Console.WriteLine("_udp.Receive " + sid + ":" + pt); if (pt == UDPPackageType.SessionConnect) { UDPConnectJson udpc = UDPConnectJson.Deserialize(Encoding.UTF8.GetString(data, 16, data.Length - 16)); lock (strmap) { if (!strmap.TryGetValue(sid, out ss)) { ss = new ServerStream(this, sid, ep, udpc); strmap[sid] = ss; } } if (ss.ConnectToken != udpc.token) { ss.ForceClose(); lock (strmap) { ss = new ServerStream(this, sid, ep, udpc); strmap[sid] = ss; } } else { ss.Process(pt, data); } } else { lock (strmap) { strmap.TryGetValue(sid, out ss); } if (ss != null) { ss.Process(pt, data); } else { _udp.SendToClient(ep, UDPMeta.CreateSessionError(sid, "NotFound")); } } } catch (ThreadAbortException) { break; } catch (Exception x) { TcpMapService.OnError(x); } } }
void _Connect(UDPClientListener udp, string ip, int port, TimeSpan timeout) { _udp = udp; StartConnect: SessionId = Interlocked.Increment(ref _nextsessionid); string guid = Guid.NewGuid().ToString(); byte[] buffconnect = UDPMeta.CreateSessionConnect(SessionId, guid); SendToPeer(buffconnect); SendToPeer(buffconnect); while (true) { byte[] buffprepair = _udp.Receive(SessionId, TimeSpan.FromMilliseconds(500)); if (buffprepair == null) { CheckTimeout(timeout); Console.WriteLine("Client StartConnect Again"); //SendToPeer(buffconnect); SendToPeer(buffconnect); //continue; goto StartConnect; } UDPPackageType ptprepair = UDPMeta.GetPackageType(buffprepair); if (ptprepair != UDPPackageType.SessionPrepair) { if (ptprepair > UDPPackageType.SessionPrepair) { goto StartConnect; } continue; } long sidprepair = BitConverter.ToInt64(buffprepair, 8); if (sidprepair != SessionId) { goto StartConnect; } UDPConnectJson udpc = UDPConnectJson.Deserialize(Encoding.UTF8.GetString(buffprepair, 16, buffprepair.Length - 16)); if (udpc.token != guid) { goto StartConnect; } break; } byte[] buffconfirm = UDPMeta.CreateSessionConfirm(SessionId, guid); SendToPeer(buffconfirm); SendToPeer(buffconfirm); while (true) { byte[] buffready = _udp.Receive(SessionId, TimeSpan.FromMilliseconds(500)); if (buffready == null) { CheckTimeout(timeout); SendToPeer(buffconfirm); SendToPeer(buffconfirm); continue; } UDPPackageType ptprepair = UDPMeta.GetPackageType(buffready); if (ptprepair != UDPPackageType.SessionReady) { if (ptprepair > UDPPackageType.SessionReady) { goto StartConnect; } continue; } long sidprepair = BitConverter.ToInt64(buffready, 8); if (sidprepair != SessionId) { goto StartConnect; } UDPConnectJson udpc = UDPConnectJson.Deserialize(Encoding.UTF8.GetString(buffready, 16, buffready.Length - 16)); if (udpc.token != guid) { goto StartConnect; } break; } _reader = new ClientBufferReader(); Thread t = new Thread(ClientWorkThread); //TODO:Convert to async t.IsBackground = true; t.Start(); }