context: // **********************************************************************
  //
  // Copyright (c) 2003-2013 ZeroC, Inc. All rights reserved.
  //
  // This copy of Ice is licensed to you under the terms described in the
  // ICE_LICENSE file included in this distribution.
  //
  // **********************************************************************
  
  namespace IceSSL
  {
      using System;
      using System.ComponentModel;
      using System.Diagnostics;
      using System.Collections.Generic;
      using System.IO;
      using System.Net;
      using System.Net.Security;
      using System.Net.Sockets;
      using System.Security.Authentication;
      using System.Security.Cryptography.X509Certificates;
      using System.Threading;
      using System.Text;
  
      sealed class TransceiverI : IceInternal.Transceiver
      {
          public int initialize()
          {
              try
              {
                  if(_state == StateNeedConnect)
                  {
                      Debug.Assert(_addr != null);
                      _state = StateConnectPending;
                      return IceInternal.SocketOperation.Connect;
                  }
                  else if(_state == StateConnectPending)
                  {
                      IceInternal.Network.doFinishConnectAsync(_fd, _writeResult);
                      _writeResult = null;
                      _state = StateAuthenticatePending;
                      _desc = IceInternal.Network.fdToString(_fd);
                      return IceInternal.SocketOperation.Connect;
                  }
                  if(_state == StateNeedAuthenticate)
                  {
                      _state = StateAuthenticatePending;
                      return IceInternal.SocketOperation.Connect;
                  }
                  else if(_state <= StateAuthenticatePending)
                  {
                      endAuthenticate();
                      _writeResult = null;
                      _state = StateConnected;
                  }
                  return IceInternal.SocketOperation.None;
              }
              catch(Ice.LocalException e)
              {
                  if(_instance.networkTraceLevel() >= 2)
                  {
                      System.Text.StringBuilder s = new System.Text.StringBuilder();
                      s.Append("failed to establish ssl connection\n");
                      if(_incoming)
                      {
                          s.Append(IceInternal.Network.addressesToString(IceInternal.Network.getLocalAddress(_fd),
                                                                         IceInternal.Network.getRemoteAddress(_fd)));
                      }
                      else
                      {
                          Debug.Assert(_addr != null);
                          s.Append(IceInternal.Network.addressesToString(IceInternal.Network.getLocalAddress(_fd),
                                                                         _addr));
                      }
                      s.Append("\n");
                      s.Append(e.ToString());
                      _logger.trace(_instance.networkTraceCategory(), s.ToString());
                  }
                  throw;
              }
          }
  
          public void close()
          {
              if(_state == StateConnected && _instance.networkTraceLevel() >= 1)
              {
                  string s = "closing ssl connection\n" + ToString();
                  _logger.trace(_instance.networkTraceCategory(), s);
              }
  
              Debug.Assert(_fd != null);
              try
              {
                  if(_stream != null)
                  {
                      //
                      // Closing the stream also closes the socket.
                      //
                      _stream.Close();
                  }
                  else
                  {
                      _fd.Close();
                  }
              }
              catch(IOException ex)
              {
                  throw new Ice.SocketException(ex);
              }
              finally
              {
                  _fd = null;
                  _stream = null;
              }
          }
  
          public bool write(IceInternal.Buffer buf)
          {
              Debug.Assert(_fd != null);
              return false; // Caller will use async write.
          }
  
          public bool read(IceInternal.Buffer buf)
          {
              Debug.Assert(_fd != null);
              return false; // Caller will use async read.
          }
  
          public bool startRead(IceInternal.Buffer buf, IceInternal.AsyncCallback callback, object state)
          {
              Debug.Assert(_fd != null);
  
              int packetSize = buf.b.remaining();
              if(_maxReceivePacketSize > 0 && packetSize > _maxReceivePacketSize)
              {
                  packetSize = _maxReceivePacketSize;
              }
  
              try
              {
                  _readCallback = callback;
                  _readResult = _stream.BeginRead(buf.b.rawBytes(), buf.b.position(), packetSize, readCompleted, state);
                  return _readResult.CompletedSynchronously;
              }
              catch(IOException ex)
              {
                  if(IceInternal.Network.connectionLost(ex))
                  {
                      throw new Ice.ConnectionLostException(ex);
                  }
                  if(IceInternal.Network.timeout(ex))
                  {
                      throw new Ice.TimeoutException();
                  }
                  throw new Ice.SocketException(ex);
              }
              catch(Ice.LocalException)
              {
                  throw;
              }
              catch(ObjectDisposedException ex)
              {
                  throw new Ice.ConnectionLostException(ex);
              }
              catch(Exception ex)
              {
                  throw new Ice.SyscallException(ex);
              }
          }
  
          public void finishRead(IceInternal.Buffer buf)
          {
              if(_fd == null) // Transceiver was closed
              {
                  _readResult = null;
                  return;
              }
  
              Debug.Assert(_fd != null && _readResult != null);
  
              try
              {
                  int ret = _stream.EndRead(_readResult);
                  _readResult = null;
                  if(ret == 0)
                  {
                      throw new Ice.ConnectionLostException();
                  }
  
                  Debug.Assert(ret > 0);
  
                  if(_instance.networkTraceLevel() >= 3)
                  {
                      int packetSize = buf.b.remaining();
                      if(_maxReceivePacketSize > 0 && packetSize > _maxReceivePacketSize)
                      {
                          packetSize = _maxReceivePacketSize;
                      }
                      string s = "received " + ret + " of " + packetSize + " bytes via ssl\n" + ToString();
                      _logger.trace(_instance.networkTraceCategory(), s);
                  }
  
                  if(_stats != null)
                  {
  #pragma warning disable 618
                      _stats.bytesReceived(type(), ret);
  #pragma warning restore 618
                  }
  
                  buf.b.position(buf.b.position() + ret);
              }
              catch(IOException ex)
              {
                  if(IceInternal.Network.connectionLost(ex))
                  {
                      throw new Ice.ConnectionLostException(ex);
                  }
                  if(IceInternal.Network.timeout(ex))
                  {
                      throw new Ice.TimeoutException();
                  }
                  throw new Ice.SocketException(ex);
              }
              catch(Ice.LocalException)
              {
                  throw;
              }
              catch(ObjectDisposedException ex)
              {
                  throw new Ice.ConnectionLostException(ex);
              }
              catch(Exception ex)
              {
                  throw new Ice.SyscallException(ex);
              }
          }
  
          public bool startWrite(IceInternal.Buffer buf, IceInternal.AsyncCallback callback, object state, 
                                 out bool completed)
          {
              Debug.Assert(_fd != null);
              
              if(_state < StateConnected)
              {
                  if(_state == StateConnectPending)
                  {
                      _writeResult = IceInternal.Network.doConnectAsync(_fd, _addr, callback, state);
                      completed = false;
                      return _writeResult.CompletedSynchronously;
                  }
                  else if(_state == StateAuthenticatePending)
                  {
                      completed = false;
                      return beginAuthenticate(callback, state);
                  }
              }
  
              //
              // We limit the packet size for beingWrite to ensure connection timeouts are based
              // on a fixed packet size.
              //
              int packetSize = buf.b.remaining();
              if(_maxSendPacketSize > 0 && packetSize > _maxSendPacketSize)
              {
                  packetSize = _maxSendPacketSize;
              }
  
              try
              {
                  _writeCallback = callback;
                  _writeResult = _stream.BeginWrite(buf.b.rawBytes(), buf.b.position(), packetSize, writeCompleted, state);
  
gt:                 completed = packetSize == buf.b.remaining();