public bool StartRead(Buffer buf, AsyncCallback callback, object state) { Debug.Assert(_fd != null); Debug.Assert(buf.B.Position() == 0); int packetSize = Math.Min(MaxPacketSize, _rcvSize - UdpOverhead); buf.Resize(packetSize, true); buf.B.Position(0); try { // TODO: Workaround for https://github.com/dotnet/corefx/issues/31182 if (_state == StateConnected || (AssemblyUtil.IsMacOS && _fd.AddressFamily == AddressFamily.InterNetworkV6 && _fd.DualMode)) { _readCallback = callback; _readEventArgs.UserToken = state; _readEventArgs.SetBuffer(buf.B.RawBytes(), buf.B.Position(), packetSize); return(!_fd.ReceiveAsync(_readEventArgs)); } else { Debug.Assert(_incoming); _readCallback = callback; _readEventArgs.UserToken = state; _readEventArgs.SetBuffer(buf.B.RawBytes(), 0, buf.B.Limit()); return(!_fd.ReceiveFromAsync(_readEventArgs)); } } catch (SocketException ex) { if (Network.RecvTruncated(ex)) { // Nothing todo return(true); } else { if (Network.ConnectionLost(ex)) { throw new Ice.ConnectionLostException(ex); } else { throw new Ice.SocketException(ex); } } } }
public bool StartRead(ref ArraySegment <byte> buffer, ref int offset, AsyncCallback callback, object state) { Debug.Assert(_fd != null); Debug.Assert(offset == 0, $"offset: {offset}\n{Environment.StackTrace}"); int packetSize = Math.Min(MaxPacketSize, _rcvSize - UdpOverhead); Debug.Assert(buffer.Count == 0); buffer = new byte[packetSize]; try { // TODO: Workaround for https://github.com/dotnet/corefx/issues/31182 _readCallback = callback; _readEventArgs.UserToken = state; _readEventArgs.SetBuffer(buffer.Array, 0, packetSize); if (_state == StateConnected || (AssemblyUtil.IsMacOS && _fd.AddressFamily == AddressFamily.InterNetworkV6 && _fd.DualMode)) { return(!_fd.ReceiveAsync(_readEventArgs)); } else { Debug.Assert(_incoming); return(!_fd.ReceiveFromAsync(_readEventArgs)); } } catch (System.Net.Sockets.SocketException ex) { if (Network.RecvTruncated(ex)) { // Nothing todo return(true); } else { if (Network.ConnectionLost(ex)) { throw new Ice.ConnectionLostException(ex); } else { throw new Ice.SocketException(ex); } } } }
public void FinishRead(Buffer buf) { if (_fd == null) { return; } int ret; try { if (_readEventArgs.SocketError != SocketError.Success) { throw new SocketException((int)_readEventArgs.SocketError); } ret = _readEventArgs.BytesTransferred; // TODO: Workaround for https://github.com/dotnet/corefx/issues/31182 if (_state != StateConnected && !(AssemblyUtil.IsMacOS && _fd.AddressFamily == AddressFamily.InterNetworkV6 && _fd.DualMode)) { _peerAddr = _readEventArgs.RemoteEndPoint; } } catch (SocketException ex) { if (Network.RecvTruncated(ex)) { // The message was truncated and the whole buffer is filled. We ignore // this error here, it will be detected at the connection level when // the Ice message size is checked against the buffer size. ret = buf.Size(); } else { if (Network.ConnectionLost(ex)) { throw new Ice.ConnectionLostException(ex); } if (Network.ConnectionRefused(ex)) { throw new Ice.ConnectionRefusedException(ex); } else { throw new Ice.SocketException(ex); } } } if (ret == 0) { throw new Ice.ConnectionLostException(); } Debug.Assert(ret > 0); if (_state == StateNeedConnect) { Debug.Assert(_incoming); // // If we must connect, then we connect to the first peer that // sends us a packet. // bool connected = !_fd.ConnectAsync(_readEventArgs); Debug.Assert(connected); _state = StateConnected; // We're connected now if (_instance.TraceLevel >= 1) { _instance.Logger.Trace(_instance.TraceCategory, $"connected {Transport()} socket\n{this}"); } } buf.Resize(ret, true); buf.B.Position(ret); }
public int Read(Buffer buf, ref bool hasMoreData) { if (!buf.B.HasRemaining()) { return(SocketOperation.None); } Debug.Assert(buf.B.Position() == 0); Debug.Assert(_fd != null); int packetSize = Math.Min(MaxPacketSize, _rcvSize - UdpOverhead); buf.Resize(packetSize, true); buf.B.Position(0); int ret; while (true) { try { EndPoint?peerAddr = _peerAddr; if (peerAddr == null) { if (_addr.AddressFamily == AddressFamily.InterNetwork) { peerAddr = new IPEndPoint(IPAddress.Any, 0); } else { Debug.Assert(_addr.AddressFamily == AddressFamily.InterNetworkV6); peerAddr = new IPEndPoint(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(buf.B.RawBytes(), 0, buf.B.Limit(), SocketFlags.None); } else { ret = _fd.ReceiveFrom(buf.B.RawBytes(), 0, buf.B.Limit(), SocketFlags.None, ref peerAddr); _peerAddr = (IPEndPoint)peerAddr; } break; } catch (SocketException e) { if (Network.RecvTruncated(e)) { // The message was truncated and the whole buffer is filled. We ignore // this error here, it will be detected at the connection level when // the Ice message size is checked against the buffer size. ret = buf.Size(); break; } if (Network.Interrupted(e)) { continue; } if (Network.WouldBlock(e)) { return(SocketOperation.Read); } if (Network.ConnectionLost(e)) { throw new Ice.ConnectionLostException(); } else { throw new Ice.SocketException(e); } } catch (Exception e) { throw new Ice.SyscallException(e); } } if (ret == 0) { throw new Ice.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 (_instance.TraceLevel >= 1) { _instance.Logger.Trace(_instance.TraceCategory, $"connected {Transport()} socket\n{this}"); } } buf.Resize(ret, true); buf.B.Position(ret); return(SocketOperation.None); }