diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 3cc8a99dd1..90e494aa1f 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -58,7 +58,7 @@ namespace OpenMetaverse /// UDP socket, used in either client or server mode private Socket m_udpSocket; - public static Object m_udpBuffersPoolLock = new Object(); + public static Object m_udpBuffersPoolLock = new(); public static UDPPacketBuffer[] m_udpBuffersPool = new UDPPacketBuffer[1000]; public static int m_udpBuffersPoolPtr = -1; @@ -322,157 +322,119 @@ namespace OpenMetaverse private void AsyncBeginReceive() { - if (!IsRunningInbound) - return; - - UDPPacketBuffer buf = GetNewUDPBuffer(new IPEndPoint(IPAddress.Any, 0)); // we need a fresh one here, for now at least - try + while (IsRunningInbound) { - // kick off an async read - m_udpSocket.BeginReceiveFrom( - buf.Data, - 0, - buf.Data.Length, - SocketFlags.None, - ref buf.RemoteEndPoint, - AsyncEndReceive, - buf); - } - catch (SocketException e) - { - if (e.SocketErrorCode == SocketError.ConnectionReset) + UDPPacketBuffer buf = GetNewUDPBuffer(new IPEndPoint(IPAddress.Any, 0)); // we need a fresh one here, for now at least + try { - m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort); - bool salvaged = false; - while (!salvaged) - { - try - { - m_udpSocket.BeginReceiveFrom( - buf.Data, - 0, - buf.Data.Length, - SocketFlags.None, - ref buf.RemoteEndPoint, - AsyncEndReceive, - buf); - salvaged = true; - } - catch (SocketException) { } - catch (ObjectDisposedException) { return; } - } + // kick off an async read + IAsyncResult iar = m_udpSocket.BeginReceiveFrom( + buf.Data, + 0, + buf.Data.Length, + SocketFlags.None, + ref buf.RemoteEndPoint, + AsyncEndReceive, + buf); - m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); + if (!iar.CompletedSynchronously) + return; + } + catch (SocketException e) + { + if (e.SocketErrorCode == SocketError.ConnectionReset) + { + m_log.Warn("[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " + m_udpPort); + { + try + { + IAsyncResult iar = m_udpSocket.BeginReceiveFrom( + buf.Data, + 0, + buf.Data.Length, + SocketFlags.None, + ref buf.RemoteEndPoint, + AsyncEndReceive, + buf); + + if (!iar.CompletedSynchronously) + return; + } + catch (SocketException) { } + catch (ObjectDisposedException) { return; } + } + m_log.Warn("[UDPBASE]: Salvaged the UDP listener on port " + m_udpPort); + } + } + catch (Exception e) + { + m_log.Error( + string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e); } - } - catch (Exception e) - { - m_log.Error( - string.Format("[UDPBASE]: Error processing UDP begin receive {0}. Exception ", UdpReceives), e); } } private void AsyncEndReceive(IAsyncResult iar) { - // Asynchronous receive operations will complete here through the call - // to AsyncBeginReceive - if (IsRunningInbound) - { - UdpReceives++; - - try - { - // get the buffer that was created in AsyncBeginReceive - // this is the received data - UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; - - int startTick = Util.EnvironmentTickCount(); - - // get the length of data actually read from the socket, store it with the - // buffer - buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); - - // call the abstract method PacketReceived(), passing the buffer that - // has just been filled from the socket read. - PacketReceived(buffer); - - // If more than one thread can be calling AsyncEndReceive() at once (e.g. if m_asyncPacketHandler) - // then a particular stat may be inaccurate due to a race condition. We won't worry about this - // since this should be rare and won't cause a runtime problem. - if (m_currentReceiveTimeSamples >= s_receiveTimeSamples) - { - AverageReceiveTicksForLastSamplePeriod - = (float)m_receiveTicksInCurrentSamplePeriod / s_receiveTimeSamples; - - m_receiveTicksInCurrentSamplePeriod = 0; - m_currentReceiveTimeSamples = 0; - } - else - { - m_receiveTicksInCurrentSamplePeriod += Util.EnvironmentTickCountSubtract(startTick); - m_currentReceiveTimeSamples++; - } - } - catch (SocketException se) - { - m_log.Error( - string.Format( - "[UDPBASE]: Error processing UDP end receive {0}, socket error code {1}. Exception ", - UdpReceives, se.ErrorCode), - se); - } - catch (Exception e) - { - m_log.Error( - string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e); - } - finally - { - AsyncBeginReceive(); - } - } - } - -/* not in use - public void AsyncBeginSend(UDPPacketBuffer buf) - { -// if (IsRunningOutbound) -// { - - // This is strictly for debugging purposes to simulate dropped - // packets when testing throttles & retransmission code - // if (DropOutgoingPacket()) - // return; - - try - { - m_udpSocket.BeginSendTo( - buf.Data, - 0, - buf.DataLength, - SocketFlags.None, - buf.RemoteEndPoint, - AsyncEndSend, - buf); - } - catch (SocketException) { } - catch (ObjectDisposedException) { } - // } - } - - void AsyncEndSend(IAsyncResult result) - { + bool sync = iar.CompletedSynchronously; try { -// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; - m_udpSocket.EndSendTo(result); + // get the buffer that was created in AsyncBeginReceive + // this is the received data + UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; - UdpSends++; + int startTick = Util.EnvironmentTickCount(); + + // get the length of data actually read from the socket, store it with the + // buffer + buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint); + + if (!IsRunningInbound) + return; + + UdpReceives++; + + // call the abstract method PacketReceived(), passing the buffer that + // has just been filled from the socket read. + PacketReceived(buffer); + + // If more than one thread can be calling AsyncEndReceive() at once (e.g. if m_asyncPacketHandler) + // then a particular stat may be inaccurate due to a race condition. We won't worry about this + // since this should be rare and won't cause a runtime problem. + if (m_currentReceiveTimeSamples >= s_receiveTimeSamples) + { + AverageReceiveTicksForLastSamplePeriod + = (float)m_receiveTicksInCurrentSamplePeriod / s_receiveTimeSamples; + + m_receiveTicksInCurrentSamplePeriod = 0; + m_currentReceiveTimeSamples = 0; + } + else + { + m_receiveTicksInCurrentSamplePeriod += Util.EnvironmentTickCountSubtract(startTick); + m_currentReceiveTimeSamples++; + } + } + catch (SocketException se) + { + m_log.Error( + string.Format( + "[UDPBASE]: Error processing UDP end receive {0}, socket error code {1}. Exception ", + UdpReceives, se.ErrorCode), + se); + } + catch (Exception e) + { + m_log.Error( + string.Format("[UDPBASE]: Error processing UDP end receive {0}. Exception ", UdpReceives), e); + } + finally + { + if (IsRunningInbound && !sync) + AsyncBeginReceive(); } - catch (SocketException) { } - catch (ObjectDisposedException) { } } -*/ + public void SyncSend(UDPPacketBuffer buf) { if(buf.RemoteEndPoint == null)