StartWrite(IList <ArraySegment <byte> > buffer, int offset, AsyncCallback callback, object state, out bool completed) { Debug.Assert(_fd != null); Debug.Assert(_writeEventArgs != null); Debug.Assert(offset == 0); bool completedSynchronously; if (!_incoming && _state < StateConnected) { Debug.Assert(_addr != null); completed = false; if (_sourceAddr != null) { _fd.Bind(_sourceAddr); } _writeEventArgs.UserToken = state; return(!_fd.ConnectAsync(_writeEventArgs)); } // The caller is supposed to check the send size before by calling checkSendSize Debug.Assert(Math.Min(MaxPacketSize, _sndSize - UdpOverhead) >= buffer.GetByteCount()); try { _writeCallback = callback; if (_state == StateConnected) { _writeEventArgs.UserToken = state; _writeEventArgs.BufferList = buffer; completedSynchronously = !_fd.SendAsync(_writeEventArgs); } else { if (_peerAddr == null) { throw new TransportException("cannot send datagram to undefined peer"); } _writeEventArgs.RemoteEndPoint = _peerAddr; _writeEventArgs.UserToken = state; ArraySegment <byte> data = buffer.GetSegment(0, buffer.GetByteCount()); _writeEventArgs.SetBuffer(data.Array, 0, data.Count); completedSynchronously = !_fd.SendToAsync(_writeEventArgs); } } catch (System.Net.Sockets.SocketException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } else { throw new TransportException(ex); } } completed = true; return(completedSynchronously); }
private bool StartAuthenticate(AsyncCallback callback, object state) { Debug.Assert(_sslStream != null); try { _writeCallback = callback; if (!_incoming) { // // Client authentication. // _writeResult = _sslStream.BeginAuthenticateAsClient(_host, _engine.Certs, _engine.SslProtocols, _engine.CheckCRL > 0, WriteCompleted, state); } else { // // Server authentication. // // Get the certificate collection and select the first one. // X509Certificate2Collection?certs = _engine.Certs; X509Certificate2? cert = null; if (certs != null && certs.Count > 0) { cert = certs[0]; } _writeResult = _sslStream.BeginAuthenticateAsServer(cert, _verifyPeer > 0, _engine.SslProtocols, _engine.CheckCRL > 0, WriteCompleted, state); } } catch (IOException ex) { if (Network.ConnectionLost(ex)) { // // This situation occurs when connectToSelf is called; the "remote" end // closes the socket immediately. // throw new ConnectionLostException(); } throw new TransportException(ex); } catch (AuthenticationException ex) { throw new TransportException(ex); } Debug.Assert(_writeResult != null); return(_writeResult.CompletedSynchronously); }
private void FinishAuthenticate() { Debug.Assert(_writeResult != null); Debug.Assert(_sslStream != null); try { if (!_incoming) { _sslStream.EndAuthenticateAsClient(_writeResult); } else { _sslStream.EndAuthenticateAsServer(_writeResult); } } catch (IOException ex) { if (Network.ConnectionLost(ex)) { // // This situation occurs when connectToSelf is called; the "remote" end // closes the socket immediately. // throw new ConnectionLostException(); } throw new TransportException(ex); } catch (AuthenticationException ex) { throw new TransportException(ex); } }
/// <summary>Finish an asynchronous write operation, the offset is increase with the /// number of bytes actually wrote to the socket.</summary> /// <param name="buffer">The buffer of data to write to the socket.</param> /// <param name="offset">The offset at what the write operation starts, the offset is increase /// with the number of bytes successfully wrote to the socket.</param> public void FinishWrite(IList <ArraySegment <byte> > buffer, ref int offset) { if (_writeEventArgs.BufferList != null) { _writeEventArgs.BufferList.Clear(); _writeEventArgs.BufferList = null; } if (_fd == null) // Transceiver was closed { int remaining = buffer.GetByteCount() - offset; if (remaining <= _maxSendPacketSize) { offset += remaining; // Assume all the data was sent for at-most-once semantics. } return; } Debug.Assert(_fd != null && _writeEventArgs != null); if (_state < StateConnected && _state != StateProxyWrite) { return; } try { if (_writeEventArgs.SocketError != SocketError.Success) { throw new SocketException((int)_writeEventArgs.SocketError); } int ret = _writeEventArgs.BytesTransferred; if (ret == 0) { throw new ConnectionLostException(); } Debug.Assert(ret > 0); if (_state == StateProxyWrite) { Debug.Assert(_proxy != null); _state = ToState(_proxy.EndWrite(buffer, ret)); } offset += ret; } catch (SocketException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } throw new TransportException(ex); } catch (ObjectDisposedException ex) { throw new ConnectionLostException(ex); } }
public int Initialize(ref ArraySegment <byte> readBuffer, IList <ArraySegment <byte> > writeBuffer) { if (!_isConnected) { int status = _delegate.Initialize(ref readBuffer, writeBuffer); if (status != SocketOperation.None) { return(status); } _isConnected = true; } if (SslStream == null) { try { Socket?fd = _delegate.Fd(); Debug.Assert(fd != null); Network.SetBlock(fd, true); // SSL requires a blocking socket // For timeouts to work properly, we need to receive/send the data in several chunks. Otherwise, // we would only be notified when all the data is received/written. The connection timeout could // easily be triggered when receiving/sending large frames. _maxSendPacketSize = Math.Max(512, Network.GetSendBufferSize(fd)); _maxRecvPacketSize = Math.Max(512, Network.GetRecvBufferSize(fd)); if (_incoming) { SslStream = new SslStream( new NetworkStream(fd, false), false, _engine.TlsServerOptions.ClientCertificateValidationCallback ?? RemoteCertificateValidationCallback); } else { SslStream = new SslStream( new NetworkStream(fd, false), false, _engine.TlsClientOptions.ServerCertificateValidationCallback ?? RemoteCertificateValidationCallback, _engine.TlsClientOptions.ClientCertificateSelectionCallback ?? CertificateSelectionCallback); } } catch (Exception ex) { if (ex is IOException ioException && Network.ConnectionLost(ioException)) { throw new ConnectionLostException(ex); } else { throw new TransportException(ex); } }
private int WriteData(IList <ArraySegment <byte> > buffer, int offset, int count) { Debug.Assert(_fd != null); if (AssemblyUtil.IsMono) { // // Mono on Android and iOS don't support the use of synchronous socket // operations on a non-blocking socket. Returning 0 here forces the caller to schedule // an asynchronous operation. // return(0); } int packetSize = _maxSendPacketSize; if (AssemblyUtil.IsWindows) { // // On Windows, limiting the buffer size is important to prevent // poor throughput performances when transferring large amount of // data. See Microsoft KB article KB823764. // if (_maxSendPacketSize > 0 && packetSize > _maxSendPacketSize / 2) { packetSize = _maxSendPacketSize / 2; } } int remaining = count - offset; int sent = 0; while (remaining - sent > 0) { try { buffer.FillSegments(offset + sent, _sendSegments, Math.Min(remaining - sent, packetSize)); int ret = _fd.Send(_sendSegments, SocketFlags.None); _sendSegments.Clear(); Debug.Assert(ret > 0); sent += ret; } catch (SocketException ex) { if (Network.WouldBlock(ex)) { return(sent); } else if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } throw new TransportException(ex); } } return(sent); }
public bool StartWrite( IList <ArraySegment <byte> > buffer, int offset, AsyncCallback cb, object state, out bool completed) { if (!_isConnected) { return(_delegate.StartWrite(buffer, offset, cb, state, out completed)); } else if (SslStream == null) { throw new ConnectionLostException(); } Debug.Assert(SslStream != null); if (!_authenticated) { completed = false; return(StartAuthenticate(cb, state)); } // // We limit the packet size for beingWrite to ensure connection timeouts are based // on a fixed packet size. // int remaining = buffer.GetByteCount() - offset; int packetSize = GetSendPacketSize(remaining); try { _writeCallback = cb; ArraySegment <byte> data = buffer.GetSegment(offset, packetSize); _writeResult = SslStream.BeginWrite(data.Array, 0, data.Count, WriteCompleted, state); completed = packetSize == remaining; return(_writeResult.CompletedSynchronously); } catch (IOException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } if (Network.Timeout(ex)) { throw new ConnectionTimeoutException(); } throw new TransportException(ex); } catch (ObjectDisposedException ex) { throw new ConnectionLostException(ex); } }
/// <summary>Starts an asynchronous write operation of the buffer data to the socket /// starting at the given offset, completed is set to true if the write operation /// account for the remaining of the buffer data or false otherwise, returns whenever /// the asynchronous operation completed synchronously or not.</summary> /// <param name="buffer">The data to write to the socket as a list of byte array segments.</param> /// <param name="offset">The zero based byte offset into the buffer at what start writing.</param> /// <param name="callback">The asynchronous completion callback.</param> /// <param name="state">A state object that is associated with the asynchronous operation.</param> /// <param name="completed">True if the write operation accounts for the buffer remaining data, from /// offset to the end of the buffer.</param> /// <returns>True if the asynchronous operation completed synchronously otherwise false.</returns> public bool StartWrite(IList <ArraySegment <byte> > buffer, int offset, AsyncCallback callback, object state, out bool completed) { Debug.Assert(_fd != null && _writeEventArgs != null); if (_state == StateConnectPending) { completed = false; _writeCallback = callback; try { if (_sourceAddr != null) { Network.DoBind(_fd, new IPEndPoint(_sourceAddr, 0)); } EndPoint?addr = _proxy != null?_proxy.GetAddress() : _addr; Debug.Assert(addr != null); _writeEventArgs.RemoteEndPoint = addr; _writeEventArgs.UserToken = state; return(!_fd.ConnectAsync(_writeEventArgs)); } catch (Exception ex) { throw new TransportException(ex); } } try { int count = buffer.GetByteCount(); int remaining = count - offset; buffer.FillSegments(offset, _sendSegments, Math.Min(remaining, _maxSendPacketSize)); _writeCallback = callback; _writeEventArgs.UserToken = state; _writeEventArgs.BufferList = _sendSegments; bool completedSynchronously = !_fd.SendAsync(_writeEventArgs); completed = _maxSendPacketSize >= remaining; return(completedSynchronously); } catch (SocketException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } throw new TransportException(ex); } catch (ObjectDisposedException ex) { throw new ConnectionLostException(ex); } }
private int ReadData(ArraySegment <byte> buffer, int offset) { Debug.Assert(_fd != null); if (AssemblyUtil.IsMono) { // // Mono on Android and iOS don't support the use of synchronous socket // operations on a non-blocking socket. Returning 0 here forces the caller to schedule // an asynchronous operation. // return(0); } int bytesTransferred = 0; int bufferOffset = buffer.Offset + offset; while (buffer.Count - (offset + bytesTransferred) > 0) { try { int ret = _fd.Receive(buffer.Array, bufferOffset + bytesTransferred, GetRecvPacketSize(buffer.Count - (offset + bytesTransferred)), SocketFlags.None); if (ret == 0) { throw new ConnectionLostException(); } bytesTransferred += ret; } catch (SocketException ex) { if (Network.WouldBlock(ex)) { return(bytesTransferred); } else if (Network.Interrupted(ex)) { continue; } else if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } throw new TransportException(ex); } } return(bytesTransferred); }
public void FinishWrite(IList <ArraySegment <byte> > buffer, ref int offset) { if (!_isConnected) { _delegate.FinishWrite(buffer, ref offset); return; } else if (_sslStream == null) // Transceiver was closed { int remaining = buffer.GetByteCount() - offset; if (GetSendPacketSize(remaining) == remaining) // Sent last packet { offset = remaining; // Assume all the data was sent for at-most-once semantics. } _writeResult = null; return; } else if (!_authenticated) { FinishAuthenticate(); return; } Debug.Assert(_writeResult != null); int bytesTransferred = GetSendPacketSize(buffer.GetByteCount() - offset); try { _sslStream.EndWrite(_writeResult); offset += bytesTransferred; } catch (IOException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } if (Network.Timeout(ex)) { throw new ConnectionTimeoutException(); } throw new TransportException(ex); } catch (ObjectDisposedException ex) { throw new ConnectionLostException(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 to do return(true); } else { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } else { throw new TransportException(ex); } } } }
public void FinishRead(ref ArraySegment <byte> buffer, ref int offset) { if (!_isConnected) { _delegate.FinishRead(ref buffer, ref offset); return; } else if (_sslStream == null) // Transceiver was closed { _readResult = null; return; } Debug.Assert(_readResult != null); try { int ret = _sslStream.EndRead(_readResult); _readResult = null; if (ret == 0) { throw new ConnectionLostException(); } Debug.Assert(ret > 0); offset += ret; } catch (IOException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } if (Network.Timeout(ex)) { throw new ConnectionTimeoutException(); } throw new TransportException(ex); } catch (ObjectDisposedException ex) { throw new ConnectionLostException(ex); } }
public void FinishRead(ref ArraySegment <byte> buffer, ref int offset) { if (_fd == null) // Transceiver was closed { return; } Debug.Assert(_fd != null && _readEventArgs != null); try { if (_readEventArgs.SocketError != SocketError.Success) { throw new SocketException((int)_readEventArgs.SocketError); } int ret = _readEventArgs.BytesTransferred; _readEventArgs.SetBuffer(null, 0, 0); if (ret == 0) { throw new ConnectionLostException(); } Debug.Assert(ret > 0); offset += ret; if (_state == StateProxyRead) { Debug.Assert(_proxy != null); _state = ToState(_proxy.EndRead(ref buffer, offset)); } } catch (SocketException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } throw new TransportException(ex); } catch (ObjectDisposedException ex) { throw new ConnectionLostException(ex); } }
public bool StartRead(ArraySegment <byte> buffer, int offset, AsyncCallback callback, object state) { Debug.Assert(_fd != null && _readEventArgs != null); int packetSize = GetRecvPacketSize(buffer.Count - offset); try { _readCallback = callback; _readEventArgs.UserToken = state; _readEventArgs.SetBuffer(buffer.Array, buffer.Offset + offset, packetSize); return(!_fd.ReceiveAsync(_readEventArgs)); } catch (SocketException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } throw new TransportException(ex); } }
public bool StartRead(ref ArraySegment <byte> buffer, ref int offset, AsyncCallback callback, object state) { if (!_isConnected) { return(_delegate.StartRead(ref buffer, ref offset, callback, state)); } else if (_sslStream == null) { throw new ConnectionLostException(); } Debug.Assert(_sslStream.IsAuthenticated); int packetSize = GetRecvPacketSize(buffer.Count - offset); try { _readCallback = callback; _readResult = _sslStream.BeginRead(buffer.Array, buffer.Offset + offset, packetSize, ReadCompleted, state); return(_readResult.CompletedSynchronously); } catch (IOException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } if (Network.Timeout(ex)) { throw new ConnectionTimeoutException(); } throw new TransportException(ex); } catch (ObjectDisposedException ex) { throw new ConnectionLostException(ex); } }
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 { 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(buffer.Array, 0, packetSize, SocketFlags.None); } else { ret = _fd.ReceiveFrom(buffer.Array, 0, packetSize, SocketFlags.None, ref peerAddr); _peerAddr = (IPEndPoint)peerAddr; } break; } catch (System.Net.Sockets.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 = 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.NetworkCat, $"connected {Transport} socket\n{this}"); } } buffer = buffer.Slice(0, ret); offset = ret; return(SocketOperation.None); }
public int Initialize(ref ArraySegment <byte> readBuffer, IList <ArraySegment <byte> > writeBuffer) { if (!_isConnected) { int status = _delegate.Initialize(ref readBuffer, writeBuffer); if (status != SocketOperation.None) { return(status); } _isConnected = true; } Socket?fd = _delegate.Fd(); Debug.Assert(fd != null); Network.SetBlock(fd, true); // SSL requires a blocking socket // // For timeouts to work properly, we need to receive/send // the data in several chunks. Otherwise, we would only be // notified when all the data is received/written. The // connection timeout could easily be triggered when // receiving/sending large messages. // _maxSendPacketSize = Math.Max(512, Network.GetSendBufferSize(fd)); _maxRecvPacketSize = Math.Max(512, Network.GetRecvBufferSize(fd)); if (_sslStream == null) { try { _sslStream = new SslStream(new NetworkStream(fd, false), false, new RemoteCertificateValidationCallback(ValidationCallback), new LocalCertificateSelectionCallback(SelectCertificate)); } catch (IOException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } else { throw new TransportException(ex); } } return(SocketOperation.Connect); } Debug.Assert(_sslStream.IsAuthenticated); _authenticated = true; _cipher = _sslStream.CipherAlgorithm.ToString(); _engine.VerifyPeer((SslConnectionInfo)GetInfo(), ToString()); if (_engine.SecurityTraceLevel >= 1) { _engine.TraceStream(_sslStream, ToString()); } return(SocketOperation.None); }
public void FinishWrite(IList <ArraySegment <byte> > buffer, ref int offset) { Debug.Assert(_writeEventArgs != null); Debug.Assert(offset == 0); if (_fd == null) { int count = buffer.GetByteCount(); // Assume all the data was sent for at-most-once semantics. _writeEventArgs = null; offset = count; return; } if (!_incoming && _state < StateConnected) { if (_writeEventArgs.SocketError != SocketError.Success) { var ex = new System.Net.Sockets.SocketException((int)_writeEventArgs.SocketError); if (Network.ConnectionRefused(ex)) { throw new ConnectionRefusedException(ex); } else { throw new ConnectFailedException(ex); } } return; } int ret; try { if (_writeEventArgs.SocketError != SocketError.Success) { throw new System.Net.Sockets.SocketException((int)_writeEventArgs.SocketError); } ret = _writeEventArgs.BytesTransferred; _writeEventArgs.SetBuffer(null, 0, 0); if (_writeEventArgs.BufferList != null && _writeEventArgs.BufferList != buffer) { _writeEventArgs.BufferList.Clear(); } _writeEventArgs.BufferList = null; } catch (System.Net.Sockets.SocketException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } else { throw new TransportException(ex); } } if (ret == 0) { throw new ConnectionLostException(); } Debug.Assert(ret > 0); Debug.Assert(ret == buffer.GetByteCount()); offset = ret; return; }
public void FinishRead(ref ArraySegment <byte> buffer, ref int offset) { if (_fd == null) { return; } int ret; try { if (_readEventArgs.SocketError != SocketError.Success) { throw new System.Net.Sockets.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 (System.Net.Sockets.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 = buffer.Count; } else { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } else if (Network.ConnectionRefused(ex)) { throw new ConnectionRefusedException(ex); } else { throw new TransportException(ex); } } } if (ret == 0) { throw new 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 (_communicator.TraceLevels.Network >= 1) { _communicator.Logger.Trace(_communicator.TraceLevels.NetworkCat, $"connected {Transport} socket\n{this}"); } } buffer = buffer.Slice(0, ret); offset = ret; }
public int Write(IList <ArraySegment <byte> > buffer, ref int offset) { int count = buffer.GetByteCount(); int remaining = count - offset; if (remaining == 0) { return(SocketOperation.None); } Debug.Assert(_fd != null && _state >= StateConnected); // The caller is supposed to check the send size before by calling checkSendSize Debug.Assert(Math.Min(MaxPacketSize, _sndSize - UdpOverhead) >= count); int ret; while (true) { try { if (_state == StateConnected) { ret = _fd.Send(buffer, SocketFlags.None); } else { if (_peerAddr == null) { throw new TransportException("cannot send datagram to undefined peer"); } ArraySegment <byte> data = buffer.GetSegment(0, count); ret = _fd.SendTo(data.Array, 0, data.Count, SocketFlags.None, _peerAddr); } Debug.Assert(ret == count); offset += ret; break; } catch (System.Net.Sockets.SocketException ex) { if (Network.Interrupted(ex)) { continue; } if (Network.WouldBlock(ex)) { return(SocketOperation.Write); } if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } else { throw new TransportException(ex); } } } return(SocketOperation.None); }
public int Initialize(ref ArraySegment <byte> readBuffer, IList <ArraySegment <byte> > writeBuffer) { if (!_isConnected) { int status = _delegate.Initialize(ref readBuffer, writeBuffer); if (status != SocketOperation.None) { return(status); } _isConnected = true; } Socket?fd = _delegate.Fd(); Debug.Assert(fd != null); Network.SetBlock(fd, true); // SSL requires a blocking socket // // For timeouts to work properly, we need to receive/send // the data in several chunks. Otherwise, we would only be // notified when all the data is received/written. The // connection timeout could easily be triggered when // receiving/sending large frames. // _maxSendPacketSize = Math.Max(512, Network.GetSendBufferSize(fd)); _maxRecvPacketSize = Math.Max(512, Network.GetRecvBufferSize(fd)); if (SslStream == null) { try { SslStream = new SslStream( new NetworkStream(fd, false), false, _engine.RemoteCertificateValidationCallback ?? RemoteCertificateValidationCallback, _engine.CertificateSelectionCallback ?? CertificateSelectionCallback); } catch (IOException ex) { if (Network.ConnectionLost(ex)) { throw new ConnectionLostException(ex); } else { throw new TransportException(ex); } } return(SocketOperation.Connect); } Debug.Assert(SslStream.IsAuthenticated); _authenticated = true; string description = ToString(); if (!_engine.TrustManager.Verify(_incoming, SslStream.RemoteCertificate as X509Certificate2, _adapterName ?? "", description)) { string msg = string.Format("{0} connection rejected by trust manager\n{1}", _incoming ? "incoming" : "outgoing", description); if (_engine.SecurityTraceLevel >= 1) { _communicator.Logger.Trace(_engine.SecurityTraceCategory, msg); } throw new TransportException(msg); } if (_engine.SecurityTraceLevel >= 1) { _engine.TraceStream(SslStream, ToString()); } return(SocketOperation.None); }