context: /* --------------------------------------------------------------------------
   * Copyrights
   *
   * Portions created by or assigned to Cursive Systems, Inc. are
   * Copyright (c) 2002-2008 Cursive Systems, Inc.  All Rights Reserved.  Contact
   * information for Cursive Systems, Inc. is available at
   * http://www.cursive.net/.
   *
   * License
   *
   * Jabber-Net is licensed under the LGPL.
   * See LICENSE.txt for details.
   * --------------------------------------------------------------------------*/
  using System;
  using System.Diagnostics;
  using System.Threading;
  using System.Xml;
  
  using bedrock.net;
  using bedrock.util;
  using jabber.protocol;
  
  namespace jabber.connection
  {
      /// <summary>
      /// Contains the types of proxies Jabber-Net supports.  This is only for socket connections.
      /// </summary>
      [SVN(@"$Id: SocketStanzaStream.cs 724 2008-08-06 18:09:25Z hildjj $")]
      public enum ProxyType
      {
          /// <summary>
          /// no proxy
          /// </summary>
          None,
          /// <summary>
          /// SOCKS4 as in http://archive.socks.permeo.com/protocol/socks4.protocol
          /// </summary>
          Socks4,
          /// <summary>
          /// SOCKS5 as in http://archive.socks.permeo.com/rfc/rfc1928.txt
          /// </summary>
          Socks5,
          /// <summary>
          /// HTTP CONNECT
          /// </summary>
          HTTP,
      }
  
  
      /// <summary>
      /// "Standard" XMPP socket for outbound connections.
      /// </summary>
      [SVN(@"$Id: SocketStanzaStream.cs 724 2008-08-06 18:09:25Z hildjj $")]
      public class SocketStanzaStream : StanzaStream, ISocketEventListener
      {
          private AsynchElementStream m_elements = null;
          private BaseSocket          m_sock     = null;
          private BaseSocket          m_accept   = null;
          private Timer               m_timer    = null;
  
          /// <summary>
          /// Create a new one.
          /// </summary>
          /// <param name="listener"></param>
          internal SocketStanzaStream(IStanzaEventListener listener) : base(listener)
          {
              m_timer = new Timer(new TimerCallback(DoKeepAlive), null, Timeout.Infinite, Timeout.Infinite);
          }
  
          /// <summary>
          /// Determines if the socket is connected.
          /// </summary>
          public override bool Connected
          {
              get { return ASock.Connected;  }
          }
  
          /// <summary>
          /// Determines whether or not Jabber-Net supports StartTLS.
          /// </summary>
          public override bool SupportsTLS
          {
              get
              {
  #if NO_SSL
                  return false;
  #else
                  return true;
  #endif
              }
          }
  
          /// <summary>
          /// Determines whether or not Jabber-Net supports compression.
          /// </summary>
          public override bool SupportsCompression
          {
              get
              {
                  try
                  {
                      return bedrock.io.ZlibStream.Supported;
                  }
                  catch
                  {
                      Debug.WriteLine("WARNING: zlib.net.dll missing!");
                      return false;
                  }
              }
          }
  
          private AsyncSocket ASock
          {
              get
              {
                  if (m_sock is ProxySocket)
                      return ((ProxySocket)m_sock).Socket as AsyncSocket;
                  else
                      return m_sock as AsyncSocket;
              }
          }
  
          /// <summary>
          /// Initializes the element stream.  This is the place to add factories.
          /// </summary>
          public override void InitializeStream()
          {
              bool first = (m_elements == null);
              m_elements = new AsynchElementStream();
              m_elements.OnDocumentStart += new ProtocolHandler(m_elements_OnDocumentStart);
              m_elements.OnDocumentEnd += new bedrock.ObjectHandler(m_elements_OnDocumentEnd);
              m_elements.OnElement += new ProtocolHandler(m_elements_OnElement);
              m_elements.OnError += new bedrock.ExceptionHandler(m_elements_OnError);
  
              m_listener.StreamInit(m_elements);
  
              Debug.Assert(this.Connected);
              if (first)
                  m_sock.RequestRead();
  
          }
  
          /// <summary>
          /// Connects to the XMPP server.
          /// </summary>
          public override void Connect()
          {
              m_elements = null;
              int port = (int)m_listener[Options.PORT];
              Debug.Assert(port > 0);
              //m_sslOn = m_ssl;
  
              ProxySocket proxy = null;
              ProxyType pt = (ProxyType)m_listener[Options.PROXY_TYPE];
              switch (pt)
              {
              case ProxyType.Socks4:
                  proxy = new Socks4Proxy(this);
                  break;
  
              case ProxyType.Socks5:
                  proxy = new Socks5Proxy(this);
                  break;
  
              case ProxyType.HTTP:
                  proxy = new ShttpProxy(this);
                  break;
  
                  /*
              case ProxyType.HTTP_Polling:
                  XEP25Socket j25s = new XEP25Socket(this);
                  if (m_ProxyHost != null)
                  {
                      System.Net.WebProxy wp = new System.Net.WebProxy();
                      wp.Address = new Uri("http://" + m_ProxyHost + ":" + m_ProxyPort);
                      if (m_ProxyUsername != null)
                      {
                          wp.Credentials = new System.Net.NetworkCredential(m_ProxyUsername, m_ProxyPassword);
                      }
                      j25s.Proxy = wp;
                  }
                  j25s.URL = m_server;
                  m_sock = j25s;
                  break;
                  */
              case ProxyType.None:
                  m_sock = new AsyncSocket(null, this, (bool)m_listener[Options.SSL], false);
  
                  ((AsyncSocket)m_sock).LocalCertificate = m_listener[Options.LOCAL_CERTIFICATE] as
                      System.Security.Cryptography.X509Certificates.X509Certificate2;
  
                  ((AsyncSocket)m_sock).CertificateGui = (bool)m_listener[Options.CERTIFICATE_GUI];
                  break;
  
              default:
                  throw new ArgumentException("no handler for proxy type: " + pt, "ProxyType");
              }
  
              if (proxy != null)
              {
                  proxy.Socket = new AsyncSocket(null, proxy, (bool)m_listener[Options.SSL], false);
                  ((AsyncSocket)proxy.Socket).LocalCertificate = m_listener[Options.LOCAL_CERTIFICATE] as
                      System.Security.Cryptography.X509Certificates.X509Certificate2;
  
                  proxy.Host = m_listener[Options.PROXY_HOST] as string;
                  proxy.Port = (int)m_listener[Options.PROXY_PORT];
                  proxy.Username = m_listener[Options.PROXY_USER] as string;
                  proxy.Password = m_listener[Options.PROXY_PW] as string;
                  m_sock = proxy;
              }
  
              string to = (string)m_listener[Options.TO];
              Debug.Assert(to != null);
  
              string host = (string)m_listener[Options.NETWORK_HOST];
              if ((host == null) || (host == ""))
              {
  #if __MonoCS__
                  host = to;
  #else
                  try
                  {
                      Address.LookupSRV((string)m_listener[Options.SRV_PREFIX], to, ref host, ref port);
                  }
                  catch
                  {
  
gt:                     Debug.WriteLine("WARNING: netlib.Dns.dll missing");