private protected override void OnDatagram(Datagram datagram, UdpNetEndpoint remoteEndpoint) { if (this.connections.TryGetValue(remoteEndpoint, out UdpConnection connection)) { connection.OnDatagram(datagram); return; } UdpConnection newConnection = this.CreateConnection(); try { newConnection.Init(remoteEndpoint, false); newConnection.OnDatagram(datagram); } catch (Exception ex) { logger.Warn($"Couldn't init connection {newConnection}. {ex}"); return; } if (!connections.TryAdd(remoteEndpoint, newConnection)) { newConnection.CloseImmidiately(DisconnectReason.Error); Logger.Error($"Couldn't add connection {newConnection}"); } }
internal void Init(UdpNetEndpoint udpNetEndpoint, bool isClientConnection) { this.IsClientConnection = isClientConnection; this.EndPoint = udpNetEndpoint; UpdateTimeoutDeadline(); logger.Debug($"{this} initialized"); }
private protected override void OnDatagram(Datagram datagram, UdpNetEndpoint remoteEndpoint) { Connection?.OnDatagram(datagram); }
private protected abstract void OnDatagram(Datagram datagram, UdpNetEndpoint remoteEndpoint);
void ActuallyOnDatagram(Datagram datagram, UdpNetEndpoint remoteEndpoint) { Logger.Debug($"Received {datagram} from {remoteEndpoint}"); OnDatagram(datagram, remoteEndpoint); }
void EndReceive(SocketAsyncEventArgs e) { try { if (e.SocketError != SocketError.Success) { switch (e.SocketError) { case SocketError.ConnectionReset: // connection reset by peer, aka connection forcibly closed aka "ICMP port unreachable" // we should shut down the connection; but m_senderRemote seemingly cannot be trusted, so which connection should we shut down?! // So, what to do? return; case SocketError.NotConnected: Logger.Debug($"Socket has been unbound. Rebinding"); // socket is unbound; try to rebind it (happens on mobile when process goes to sleep) Rebind(); return; case SocketError.OperationAborted: //Socket was closed return; default: Logger.Error("Socket error on receive: " + e.SocketError); return; } } if (configuration.ConnectionSimulation != null && random.NextDouble() < configuration.ConnectionSimulation.PacketLoss) { Logger.Debug($"We got a datagram from {e.RemoteEndPoint}, but according to connection simulation rules we dropped it"); return; } ArraySegment <byte> segment = new ArraySegment <byte>(e.Buffer, 0, e.BytesTransferred); Datagram datagram = Datagram.CreateFromRaw(configuration.MemoryStreamPool, segment); var ep = new UdpNetEndpoint(e.RemoteEndPoint, datagram.ConnectionKey); if (configuration.ConnectionSimulation != null) { int delay = configuration.ConnectionSimulation.GetHalfDelay(); if (delay > 0) { latencySimulationRecvBag.Enqueue(new DelayedDatagram() { releaseTimestamp = DateTime.UtcNow.AddMilliseconds(delay), datagram = datagram, endpoint = ep }); } else { ActuallyOnDatagram(datagram, ep); } } else { ActuallyOnDatagram(datagram, ep); } } catch (Exception ex) { Logger.Error($"Unhandled exception in EndReceive: {ex}"); } finally { StartReceive(); } }