context: // **********************************************************************
  //
  // Copyright (c) 2003-2017 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 IceInternal
  {
      using System;
      using System.Diagnostics;
      using System.Net;
      using System.Net.Sockets;
  
      public sealed class StreamSocket
      {
          public StreamSocket(ProtocolInstance instance, NetworkProxy proxy, EndPoint addr, EndPoint sourceAddr)
          {
              _instance = instance;
              _proxy = proxy;
              _addr = addr;
              _sourceAddr = sourceAddr;
              _fd = Network.createSocket(false, (_proxy != null ? _proxy.getAddress() : _addr).AddressFamily);
              _state = StateNeedConnect;
  
              init();
          }
  
          public StreamSocket(ProtocolInstance instance, Socket fd)
          {
              _instance = instance;
              _fd = fd;
              _state = StateConnected;
              try
              {
                  _desc = Network.fdToString(_fd);
              }
              catch(Exception)
              {
                  Network.closeSocketNoThrow(_fd);
                  throw;
              }
              init();
          }
  
          public void setBlock(bool block)
          {
              Network.setBlock(_fd, block);
          }
  
          public int connect(Buffer readBuffer, Buffer writeBuffer, ref bool moreData)
          {
              if(_state == StateNeedConnect)
              {
                  _state = StateConnectPending;
                  return SocketOperation.Connect;
              }
              else if(_state <= StateConnectPending)
              {
                  if(_writeEventArgs.SocketError != SocketError.Success)
                  {
                      SocketException ex = new SocketException((int)_writeEventArgs.SocketError);
                      if(Network.connectionRefused(ex))
                      {
                          throw new Ice.ConnectionRefusedException(ex);
                      }
                      else
                      {
                          throw new Ice.ConnectFailedException(ex);
                      }
                  }
                  _desc = Network.fdToString(_fd, _proxy, _addr);
                  _state = _proxy != null ? StateProxyWrite : StateConnected;
              }
  
              if(_state == StateProxyWrite)
              {
                  _proxy.beginWrite(_addr, writeBuffer);
                  return SocketOperation.Write;
              }
              else if(_state == StateProxyRead)
              {
                  _proxy.beginRead(readBuffer);
                  return SocketOperation.Read;
              }
              else if(_state == StateProxyConnected)
              {
                  _proxy.finish(readBuffer, writeBuffer);
  
                  readBuffer.clear();
                  writeBuffer.clear();
  
                  _state = StateConnected;
              }
  
              Debug.Assert(_state == StateConnected);
              return SocketOperation.None;
          }
  
          public bool isConnected()
          {
              return _state == StateConnected && _fd != null;
          }
  
          public Socket fd()
          {
              return _fd;
          }
  
          public int getSendPacketSize(int length)
          {
              return _maxSendPacketSize > 0 ? Math.Min(length, _maxSendPacketSize) : length;
          }
  
          public int getRecvPacketSize(int length)
          {
              return _maxRecvPacketSize > 0 ? Math.Min(length, _maxRecvPacketSize) : length;
          }
  
          public void setBufferSize(int rcvSize, int sndSize)
          {
              Network.setTcpBufSize(_fd, rcvSize, sndSize, _instance);
          }
  
          public int read(Buffer buf)
          {
              if(_state == StateProxyRead)
              {
                  while(true)
                  {
                      int ret = read(buf.b);
                      if(ret == 0)
                      {
                          return SocketOperation.Read;
                      }
  
                      _state = toState(_proxy.endRead(buf));
                      if(_state != StateProxyRead)
                      {
                          return SocketOperation.None;
                      }
                  }
              }
              read(buf.b);
              return buf.b.hasRemaining() ? SocketOperation.Read : SocketOperation.None;
          }
  
          public int write(Buffer buf)
          {
              if(_state == StateProxyWrite)
              {
                  while(true)
                  {
                      int ret = write(buf.b);
                      if(ret == 0)
                      {
                          return SocketOperation.Write;
                      }
                      _state = toState(_proxy.endWrite(buf));
                      if(_state != StateProxyWrite)
                      {
                          return SocketOperation.None;
                      }
                  }
              }
              write(buf.b);
              return buf.b.hasRemaining() ? SocketOperation.Write : SocketOperation.None;
          }
  
          public bool startRead(Buffer buf, AsyncCallback callback, object state)
          {
              Debug.Assert(_fd != null && _readEventArgs != null);
  
              int packetSize = getRecvPacketSize(buf.b.remaining());
              try
              {
                  _readCallback = callback;
                  _readEventArgs.UserToken = state;
                  _readEventArgs.SetBuffer(buf.b.rawBytes(), buf.b.position(), packetSize);
                  return !_fd.ReceiveAsync(_readEventArgs);
              }
              catch(SocketException ex)
              {
                  if(Network.connectionLost(ex))
                  {
                      throw new Ice.ConnectionLostException(ex);
                  }
                  throw new Ice.SocketException(ex);
              }
          }
  
          public void finishRead(Buffer buf)
          {
              if(_fd == null) // Transceiver was closed
              {
                  return;
              }
  
  
gt:             Debug.Assert(_fd != null && _readEventArgs != null);