public int Read(ref ArraySegment <byte> buffer, ref int offset) { if (buffer.Count - offset == 0) { return(SocketOperation.None); } Debug.Assert(offset == 0); Debug.Assert(_fd != null); int packetSize = Math.Min(MaxPacketSize, _rcvSize - UdpOverhead); Debug.Assert(buffer.Count == 0); buffer = new byte[packetSize]; int ret; while (true) { try { System.Net.EndPoint?peerAddr = _peerAddr; if (peerAddr == null) { if (_addr.AddressFamily == AddressFamily.InterNetwork) { peerAddr = new System.Net.IPEndPoint(System.Net.IPAddress.Any, 0); } else { Debug.Assert(_addr.AddressFamily == AddressFamily.InterNetworkV6); peerAddr = new System.Net.IPEndPoint(System.Net.IPAddress.IPv6Any, 0); } } // TODO: Workaround for https://github.com/dotnet/corefx/issues/31182 if (_state == StateConnected || (AssemblyUtil.IsMacOS && _fd.AddressFamily == AddressFamily.InterNetworkV6 && _fd.DualMode)) { ret = _fd.Receive(buffer.Array, 0, packetSize, SocketFlags.None); } else { ret = _fd.ReceiveFrom(buffer.Array, 0, packetSize, SocketFlags.None, ref peerAddr); _peerAddr = (System.Net.IPEndPoint)peerAddr; } break; } catch (SocketException e) { if (Network.RecvTruncated(e)) { // The frame was truncated and the whole buffer is filled. We ignore // this error here, it will be detected at the connection level when // the Ice frame size is checked against the buffer size. ret = buffer.Count; break; } if (Network.Interrupted(e)) { continue; } if (Network.WouldBlock(e)) { return(SocketOperation.Read); } if (Network.ConnectionLost(e)) { throw new ConnectionLostException(); } else { throw new TransportException(e); } } } if (ret == 0) { throw new ConnectionLostException(); } if (_state == StateNeedConnect) { Debug.Assert(_incoming); // // If we must connect, then we connect to the first peer that sends us a packet. // Debug.Assert(_peerAddr != null); bool connected = Network.DoConnect(_fd, _peerAddr, null); Debug.Assert(connected); _state = StateConnected; // We're connected now if (_communicator.TraceLevels.Network >= 1) { _communicator.Logger.Trace(_communicator.TraceLevels.NetworkCategory, $"connected udp socket\n{this}"); } } buffer = buffer.Slice(0, ret); offset = ret; return(SocketOperation.None); }