internal void InvokeReceivedEvent(object sender, DatagramReceiveEventArgs e) { Interlocked.Add (ref _recvBytes, e.Size); Interlocked.Increment (ref _recvDgrams); if (Received != null) { try { Received (sender, e); } catch {} } }
void Socket_Received(object sender, DatagramReceiveEventArgs e) { if (!IsActive) return; MessageType type; object obj; int tmp; uint id = 0; try { byte[] msg = _key.Decrypt (e.Buffer, 0, e.Size); using (MemoryStream strm = new MemoryStream (msg, 0, msg.Length, false)) { if ((tmp = strm.ReadByte ()) < 0) goto MessageError; type = (MessageType)tmp; if (type != MessageType.OneWay) { for (int i = 0; i < 32; i += 8) { if ((tmp = strm.ReadByte ()) < 0) goto MessageError; id |= (uint)(tmp << i); } } obj = _formatter.Deserialize (strm); if (obj == null) goto MessageError; } } catch { goto MessageError; } if (_nullObject.Equals (obj)) obj = null; string strMsgType = (obj == null ? "null msg" : obj.GetType ().Name); switch (type) { case MessageType.Request: ThreadTracer.AppendThreadName (" (req: " + strMsgType + ")"); InquiredEventArgs args = new InquiredResponseState (obj, e.RemoteEndPoint, id); InvokeInquired (this, args); break; case MessageType.Response: InquiredAsyncResultBase ar = RemoveFromRetryList (id, e.RemoteEndPoint); if (ar == null) return; ThreadTracer.AppendThreadName (" (res: " + strMsgType + ", req: " + (ar.Request == null ? "null msg" : ar.Request.GetType ().Name) + ")"); ar.Complete (obj, this); InvokeInquirySuccess (this, new InquiredEventArgs (ar.Request, obj, e.RemoteEndPoint, DateTime.Now - ar.TransmitTime, ar.RetryCount)); break; case MessageType.OneWay: ThreadTracer.AppendThreadName (" (ow: " + strMsgType + ")"); InvokeReceived (this, new ReceivedEventArgs (obj, e.RemoteEndPoint)); break; default: goto MessageError; } return; MessageError: return; }
void Socket_Received(object sender, DatagramReceiveEventArgs e) { switch (e.Buffer[0]) { case 0: /* Packet */ byte[] buf = new byte[5]; buf[0] = 1; Buffer.BlockCopy (e.Buffer, 1, buf, 1, buf.Length - 1); // Copy sequence uint rseq = ((uint)buf[1] << 24) | ((uint)buf[2] << 16) | ((uint)buf[3] << 8) | ((uint)buf[4]); _sock.SendTo (buf, _remoteEP); lock (_recvBuffer) { _lastReceived = DateTime.Now; _recvBuffer.Add (new ReceiveSegment (rseq, e.Buffer.CopyRange (HeaderSize, e.Size - HeaderSize))); _recvWaitHandle.Set (); } break; case 1: /* ACK */ uint seq = ((uint)e.Buffer[1] << 24) | ((uint)e.Buffer[2] << 16) | ((uint)e.Buffer[3] << 8) | ((uint)e.Buffer[4]); lock (_lock) { uint lowest_sendidx = uint.MaxValue, acked_sendidx = 0; int lowest_idx = int.MaxValue, acked_idx = -1; for (int i = 0; i < _sendBuffer.Length; i ++) { if (_sendBuffer[i].State == PacketState.AckWaiting && _sendBuffer[i].Sequence < seq) { if (lowest_sendidx > _sendBuffer[i].RetransmitIndex) { lowest_sendidx = _sendBuffer[i].RetransmitIndex; lowest_idx = i; } } } for (int i = 0; i < _sendBuffer.Length; i ++) { if (_sendBuffer[i].State == PacketState.AckWaiting && _sendBuffer[i].Sequence == seq) { if (_sendBuffer[i].Retries == 0) Update_RTO ((float)(DateTime.Now - _sendBuffer[i].Start).TotalMilliseconds); acked_idx = i; acked_sendidx = _sendBuffer[i].RetransmitIndex; _sendBuffer[i].Reset (); _sendBufferFilled--; _sendWaitHandle.Set (); break; } } if (lowest_idx != int.MaxValue && acked_idx >= 0 && acked_sendidx - lowest_sendidx >= 3) { Packet p = _sendBuffer[lowest_idx]; if (p.RTO - p.RTO_Interval + TimeSpan.FromMilliseconds (_rto) <= DateTime.Now) { p.RTO = DateTime.Now; p.RetransmitIndex = acked_sendidx; } } } break; } }
void InvokeThread(object o) { int idx = (int)o; while (_active) { _invokeStartHandles[idx].WaitOne (); if (!_active) return; while (true) { int i = Interlocked.Increment (ref _dgramListIndex); if (i >= _dgramList.Count) break; DatagramInfo dgram = _dgramList[i]; if (IsLossPacket (dgram.SourceEndPoint, dgram.DestinationEndPoint)) continue; VirtualNetworkNode node; if (!_mapping.TryGetValue (dgram.DestinationEndPoint, out node)) { Interlocked.Increment (ref _noDestPackets); continue; } int jitter = (int)((DateTime.Now.Subtract (dgram.StartDateTime) - dgram.ExpectedDelay).TotalMilliseconds); lock (_jitterLock) { _jitterSD.AddSample (jitter); Interlocked.Increment (ref _packets); } if (dgram.Datagram != null) { DatagramReceiveEventArgs eventArgs = new DatagramReceiveEventArgs (dgram.Datagram, dgram.Datagram.Length, dgram.SourceEndPoint); node.DatagramSocket.InvokeReceivedEvent (node.DatagramSocket, eventArgs); Interlocked.Add (ref _totalTraffic, dgram.Datagram.Length); } else { node.MessagingSocket.Deliver (dgram.SourceEndPoint, dgram.Message); } } _invokeEndHandles[idx].Set (); } }
public InvokeHelper(UdpSocket sock, DatagramReceiveEventArgs e) { _sock = sock; _e = e; }
static void ReceiveThread() { List<Socket> list = new List<Socket> (); byte[] recvBuffer = new byte[MAX_DATAGRAM_SIZE]; while (true) { list.Clear (); lock (_sockets) { if (_sockets.Count == 0) { _receiveThread = null; return; } list.AddRange (_sockets); } Socket.Select (list, null, null, 1 * 1000000); lock (_sockets) { for (int i = 0; i < list.Count; i ++) { UdpSocket usock; if (!_socketMap.TryGetValue (list[i], out usock)) { continue; } if (usock.Received == null) { continue; } try { EndPoint remoteEP = new IPEndPoint (usock._receiveAdrs, 0); int receiveSize = usock._sock.ReceiveFrom (recvBuffer, 0, recvBuffer.Length, SocketFlags.None, ref remoteEP); IPEndPoint remoteIPEP = (IPEndPoint)remoteEP; #if !DEBUG if (remoteIPEP.Port == usock._bindPort && usock._loopbackAdrs.Equals (remoteIPEP.Address)) { IPAddress new_adrs = usock._pubIpVotingBox.CurrentPublicIPAddress; if (usock._noneAdrs.Equals (new_adrs)) continue; // パブリックIPが決定していないときはそのパケットを破棄 remoteEP = new IPEndPoint (new_adrs, remoteIPEP.Port); } else if (IPAddressUtility.IsPrivate (remoteIPEP.Address)) { // リリースビルド時はプライベートアドレスからのパケットを破棄 continue; } #endif usock._recvBytes += receiveSize; usock._recvDgrams ++; ushort ver = (ushort)((recvBuffer[0] << 8) | recvBuffer[1]); if (ver != ProtocolVersion.Version) continue; // drop byte[] recvData = new byte[receiveSize - usock._header_size]; Buffer.BlockCopy (recvBuffer, usock._header_size, recvData, 0, recvData.Length); IPAddress adrs = new IPAddress (recvBuffer.CopyRange (2, usock._header_size - 2)); usock._pubIpVotingBox.Vote ((IPEndPoint)remoteEP, adrs); DatagramReceiveEventArgs e = new DatagramReceiveEventArgs (recvData, recvData.Length, remoteEP); ThreadTracer.QueueToThreadPool (new InvokeHelper (usock, e).Invoke, "Handling Received UDP Datagram"); } catch {} } } } }