30 using System.Net.Sockets;
31 using System.Threading;
33 using OpenSim.Framework;
34 using OpenSim.Framework.Monitoring;
36 namespace OpenMetaverse
43 private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
58 private Socket m_udpSocket;
61 private bool m_asyncPacketHandling;
71 protected OpenSim.Framework.Pool<UDPPacketBuffer>
Pool {
get;
private set; }
93 private readonly
static int s_receiveTimeSamples = 500;
98 private int m_currentReceiveTimeSamples;
103 private int m_receiveTicksInCurrentSamplePeriod;
110 #region PacketDropDebugging
111 private Random m_dropRandomGenerator =
new Random();
123 private double m_dropProbability = 0.0030;
124 private double m_dropLengthProbability = 0.15;
125 private bool m_dropState =
false;
133 private int m_dropLastTick = 0;
134 private int m_dropResetTicks = 500;
139 private bool DropOutgoingPacket()
141 double rnum = m_dropRandomGenerator.NextDouble();
145 int curtick = Util.EnvironmentTickCount();
146 if (Util.EnvironmentTickCountSubtract(curtick, m_dropLastTick) > m_dropResetTicks)
149 m_dropLastTick = curtick;
155 m_dropState = (rnum < (1.0 - m_dropLengthProbability)) ?
true :
false;
159 m_dropState = (rnum < m_dropProbability) ?
true :
false;
164 #endregion PacketDropDebugging
198 public virtual void StartInbound(
int recvBufferSize,
bool asyncPacketHandling)
200 m_asyncPacketHandling = asyncPacketHandling;
204 m_log.DebugFormat(
"[UDPBASE]: Starting inbound UDP loop");
206 const int SIO_UDP_CONNRESET = -1744830452;
210 m_udpSocket =
new Socket(
211 AddressFamily.InterNetwork,
221 if (m_udpSocket.Ttl < 128)
223 m_udpSocket.Ttl = 128;
226 catch (SocketException)
228 m_log.Debug(
"[UDPBASE]: Failed to increase default TTL");
234 m_udpSocket.IOControl(SIO_UDP_CONNRESET,
new byte[] { 0 }, null);
235 m_log.Debug(
"[UDPBASE]: SIO_UDP_CONNRESET flag set");
237 catch (SocketException)
239 m_log.Debug(
"[UDPBASE]: SIO_UDP_CONNRESET flag not supported on this platform, ignoring");
246 m_udpSocket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress,
false);
248 if (recvBufferSize != 0)
249 m_udpSocket.ReceiveBufferSize = recvBufferSize;
251 m_udpSocket.Bind(ipep);
267 m_log.DebugFormat(
"[UDPBASE]: Starting outbound UDP loop");
276 m_log.DebugFormat(
"[UDPBASE]: Stopping inbound UDP loop");
285 m_log.DebugFormat(
"[UDPBASE]: Stopping outbound UDP loop");
294 Pool =
new Pool<UDPPacketBuffer>(() =>
new UDPPacketBuffer(), 500);
318 private void AsyncBeginReceive()
328 buf =
new UDPPacketBuffer();
335 m_udpSocket.BeginReceiveFrom(
339 UDPPacketBuffer.BUFFER_SIZE,
341 ref buf.RemoteEndPoint,
346 catch (SocketException e)
348 if (e.SocketErrorCode == SocketError.ConnectionReset)
350 m_log.Warn(
"[UDPBASE]: SIO_UDP_CONNRESET was ignored, attempting to salvage the UDP listener on port " +
m_udpPort);
351 bool salvaged =
false;
356 m_udpSocket.BeginReceiveFrom(
360 UDPPacketBuffer.BUFFER_SIZE,
362 ref buf.RemoteEndPoint,
368 catch (SocketException) { }
369 catch (ObjectDisposedException) {
return; }
372 m_log.Warn(
"[UDPBASE]: Salvaged the UDP listener on port " +
m_udpPort);
375 catch (ObjectDisposedException e)
378 string.Format(
"[UDPBASE]: Error processing UDP begin receive {0}. Exception ",
UdpReceives), e);
383 string.Format(
"[UDPBASE]: Error processing UDP begin receive {0}. Exception ",
UdpReceives), e);
388 private void AsyncEndReceive(IAsyncResult iar)
398 if (m_asyncPacketHandling)
405 UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState;
407 int startTick = Util.EnvironmentTickCount();
411 buffer.DataLength = m_udpSocket.EndReceiveFrom(iar, ref buffer.RemoteEndPoint);
420 if (m_currentReceiveTimeSamples >= s_receiveTimeSamples)
423 = (float)m_receiveTicksInCurrentSamplePeriod / s_receiveTimeSamples;
425 m_receiveTicksInCurrentSamplePeriod = 0;
426 m_currentReceiveTimeSamples = 0;
430 m_receiveTicksInCurrentSamplePeriod += Util.EnvironmentTickCountSubtract(startTick);
431 m_currentReceiveTimeSamples++;
434 catch (SocketException se)
438 "[UDPBASE]: Error processing UDP end receive {0}, socket error code {1}. Exception ",
442 catch (ObjectDisposedException e)
445 string.Format(
"[UDPBASE]: Error processing UDP end receive {0}. Exception ",
UdpReceives), e);
450 string.Format(
"[UDPBASE]: Error processing UDP end receive {0}. Exception ",
UdpReceives), e);
459 if (!m_asyncPacketHandling)
477 m_udpSocket.BeginSendTo(
486 catch (SocketException) { }
487 catch (ObjectDisposedException) { }
491 void AsyncEndSend(IAsyncResult result)
496 m_udpSocket.EndSendTo(result);
500 catch (SocketException) { }
501 catch (ObjectDisposedException) { }