Index: ChangeLog
===================================================================
--- ChangeLog	(.../0.8.1)	(revision 1434)
+++ ChangeLog	(.../0.8.2)	(revision 1434)
@@ -1,3 +1,12 @@
+v0.8.2 -- 11 Sep 2006
+---------------------
+- find dn_skipname on Mac OS X (thanks to Geoff Schmidt)
+- look for libgnutls-config in specified path, if given
+- fixed compilation on SkyOS
+- maybe-fixed resolver on HPUX
+- **experimental** native TLS support on win32
+
+
 v0.8.1 -- 28 Jul 2006
 ---------------------
 - async inbandbytestreams ack
Index: config.h.win
===================================================================
--- config.h.win	(.../0.8.1)	(revision 1434)
+++ config.h.win	(.../0.8.2)	(revision 1434)
@@ -1,5 +1,6 @@
 /**
  * Uncomment whichever lib you have installed.
+ * Do not try to use (uncomment) more than one SSL/TLS implementation at a time
  */
 
 /* Uncomment if you have zlib available and want to use it */
@@ -11,5 +12,8 @@
 /* Uncomment if you have OpenSSL available and want to use it */
 // #define HAVE_OPENSSL 1
 
+/* Uncomment if you want to use native win32 TLS support (SChannel) */
+// #define HAVE_WINTLS 1
+
 /* Uncomment if you have LibIDN available and want to use it */
 // #define HAVE_LIBIDN 1

Index: src/connection.cpp
===================================================================
--- src/connection.cpp	(.../0.8.1)	(revision 1434)
+++ src/connection.cpp	(.../0.8.2)	(revision 1434)
@@ -34,19 +34,20 @@
 #include <winsock.h>
 #endif
 
-#if defined( _MSC_VER ) && ( _MSC_VER >= 1300 )
-#define strcasecmp stricmp
+#ifdef USE_WINTLS
+# include <schannel.h>
 #endif
 
 #include <time.h>
 
 #include <string>
+#include <sstream>
 
 namespace gloox
 {
 
   Connection::Connection( Parser *parser, const LogSink& logInstance, const std::string& server,
-                          int port )
+                          unsigned short port )
     : m_parser( parser ), m_state ( StateDisconnected ), m_disconnect ( ConnNoError ),
       m_logInstance( logInstance ), m_compression( 0 ), m_buf( 0 ),
       m_server( Prep::idna( server ) ), m_port( port ), m_socket( -1 ), m_bufsize( 17000 ),
@@ -63,6 +64,7 @@
     cleanup();
     free( m_buf );
     m_buf = 0;
+    m_parser = 0;
   }
 
 #ifdef HAVE_TLS
@@ -124,7 +126,11 @@
       m_certInfo.issuer = peer_CN;
       X509_NAME_get_text_by_NID( X509_get_subject_name( peer ), NID_commonName, peer_CN, sizeof( peer_CN ) );
       m_certInfo.server = peer_CN;
-      if( strcasecmp( peer_CN, m_server.c_str() ) )
+      std::string p;
+      p.assign( peer_CN );
+      int (*pf)( int ) = tolower;
+      transform( p.begin(), p.end(), p.begin(), pf );
+      if( p != m_server )
         m_certInfo.status |= CertWrongPeer;
     }
     else
@@ -144,6 +150,29 @@
     return true;
   }
 
+  inline bool Connection::tls_send( const void *data, size_t len )
+  {
+    int ret;
+    ret = SSL_write( m_ssl, data, len );
+    return true;
+  }
+
+  inline int Connection::tls_recv( void *data, size_t len )
+  {
+    return SSL_read( m_ssl, data, len );
+  }
+
+  inline bool Connection::tls_dataAvailable()
+  {
+    return false; // SSL_pending( m_ssl ); // FIXME: crashes
+  }
+
+  inline void Connection::tls_cleanup()
+  {
+    SSL_shutdown( m_ssl );
+    SSL_free( m_ssl );
+  }
+
 #elif defined( USE_GNUTLS )
   bool Connection::tlsHandshake()
   {
@@ -320,8 +349,537 @@
 
     return true;
   }
+
+  inline bool Connection::tls_send( const void *data, size_t len )
+  {
+    int ret;
+    do
+    {
+      ret = gnutls_record_send( m_session, data, len );
+    }
+    while( ( ret == GNUTLS_E_AGAIN ) || ( ret == GNUTLS_E_INTERRUPTED ) );
+    return true;
+  }
+
+  inline int Connection::tls_recv( void *data, size_t len )
+  {
+    return gnutls_record_recv( m_session, data, len );
+  }
+
+  inline bool Connection::tls_dataAvailable()
+  {
+    return false; // gnutls_check_pending( m_session ); // FIXME: crashes
+  }
+
+  inline void Connection::tls_cleanup()
+  {
+    gnutls_bye( m_session, GNUTLS_SHUT_RDWR );
+    gnutls_deinit( m_session );
+    gnutls_certificate_free_credentials( m_credentials );
+    gnutls_global_deinit();
+  }
+
+#elif defined( USE_WINTLS )
+  bool Connection::tlsHandshake()
+  {
+    INIT_SECURITY_INTERFACE pInitSecurityInterface;
+
+    m_lib = LoadLibrary( "secur32.dll" );
+    if( m_lib == NULL )
+      return false;
+
+    pInitSecurityInterface = (INIT_SECURITY_INTERFACE)GetProcAddress( m_lib, "InitSecurityInterfaceA" );
+    if( pInitSecurityInterface == NULL )
+    {
+      FreeLibrary( m_lib );
+      m_lib = 0;
+      return false;
+    }
+
+    m_securityFunc = pInitSecurityInterface();
+    if( !m_securityFunc )
+    {
+      FreeLibrary( m_lib );
+      m_lib = 0;
+      return false;
+    }
+
+    SCHANNEL_CRED schannelCred;
+    memset( &schannelCred, 0, sizeof( schannelCred ) );
+    memset( &m_credentials, 0, sizeof( m_credentials ) );
+    memset( &m_context, 0, sizeof( m_context ) );
+
+    schannelCred.dwVersion = SCHANNEL_CRED_VERSION;
+    schannelCred.grbitEnabledProtocols = SP_PROT_TLS1_CLIENT;
+    schannelCred.cSupportedAlgs = 0; // FIXME
+#ifdef MSVC
+    schannelCred.dwMinimumCipherStrength = 0; // FIXME
+    schannelCred.dwMaximumCipherStrength = 0; // FIXME
+#else
+    schannelCred.dwMinimumCypherStrength = 0; // FIXME
+    schannelCred.dwMaximumCypherStrength = 0; // FIXME
 #endif
+    schannelCred.dwSessionLifespan = 0;
+    schannelCred.dwFlags = SCH_CRED_NO_SERVERNAME_CHECK | SCH_CRED_NO_DEFAULT_CREDS |
+                           SCH_CRED_MANUAL_CRED_VALIDATION; // FIXME check
 
+    TimeStamp timeStamp;
+    SECURITY_STATUS ret;
+    ret = m_securityFunc->AcquireCredentialsHandleA( NULL, UNISP_NAME_A, SECPKG_CRED_OUTBOUND,
+                                     NULL, &schannelCred, NULL,
+                                     NULL, &m_credentials, &timeStamp );
+    if( ret != SEC_E_OK )
+    {
+      printf( "AcquireCredentialsHandleA failed\n" );
+      return false;
+    }
+
+    m_sspiFlags = ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_EXTENDED_ERROR
+                      | ISC_REQ_MUTUAL_AUTH | ISC_REQ_REPLAY_DETECT | ISC_REQ_SEQUENCE_DETECT
+                      | ISC_REQ_STREAM;
+
+    SecBufferDesc outBufferDesc;
+    SecBuffer outBuffers[1];
+
+    outBuffers[0].BufferType = SECBUFFER_TOKEN;
+    outBuffers[0].pvBuffer = NULL;
+    outBuffers[0].cbBuffer = 0;
+
+    outBufferDesc.ulVersion = SECBUFFER_VERSION;
+    outBufferDesc.cBuffers = 1;
+    outBufferDesc.pBuffers = outBuffers;
+
+    long unsigned int sspiFlagsOut;
+    ret = m_securityFunc->InitializeSecurityContextA( &m_credentials, NULL, NULL, m_sspiFlags, 0,
+        SECURITY_NATIVE_DREP, NULL, 0, &m_context,
+        &outBufferDesc, &sspiFlagsOut, &timeStamp );
+    if( ret == SEC_I_CONTINUE_NEEDED && outBuffers[0].cbBuffer != 0 && outBuffers[0].pvBuffer != NULL )
+    {
+      printf( "OK: Continue needed: " );
+
+      int ret = ::send( m_socket, (const char*)outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0 );
+      if( ret == SOCKET_ERROR || ret == 0 )
+      {
+        m_securityFunc->FreeContextBuffer( outBuffers[0].pvBuffer );
+        m_securityFunc->DeleteSecurityContext( &m_context );
+        return false;
+      }
+
+      m_securityFunc->FreeContextBuffer( outBuffers[0].pvBuffer );
+      outBuffers[0].pvBuffer = NULL;
+    }
+
+    if( !handshakeLoop() )
+    {
+      printf( "handshakeLoop failed\n" );
+      return false;
+    }
+
+    ret = m_securityFunc->QueryContextAttributes( &m_context, SECPKG_ATTR_STREAM_SIZES, &m_streamSizes );
+    if( ret != SEC_E_OK )
+    {
+      printf( "could not read stream attribs (sizes)\n" );
+      return false;
+    }
+printf( "maximumMessage: %ld\n", m_streamSizes.cbMaximumMessage );
+    int maxSize = m_streamSizes.cbHeader + m_streamSizes.cbMaximumMessage + m_streamSizes.cbTrailer;
+    m_iBuffer = (char*)malloc( maxSize );
+    if( !m_iBuffer )
+      return false;
+
+    m_oBuffer = (char*)malloc( maxSize );
+    if( !m_oBuffer )
+      return false;
+
+    m_bufferOffset = 0;
+    m_messageOffset = m_oBuffer + m_streamSizes.cbHeader;
+
+    SecPkgContext_Authority streamAuthority;
+    ret = m_securityFunc->QueryContextAttributes( &m_context, SECPKG_ATTR_AUTHORITY, &streamAuthority );
+    if( ret != SEC_E_OK )
+    {
+      printf( "could not read stream attribs (sizes)\n" );
+      return false;
+    }
+    else
+    {
+      m_certInfo.issuer.assign( streamAuthority.sAuthorityName );
+    }
+
+    SecPkgContext_ConnectionInfo streamInfo;
+    ret = m_securityFunc->QueryContextAttributes( &m_context, SECPKG_ATTR_CONNECTION_INFO, &streamInfo );
+    if( ret != SEC_E_OK )
+    {
+      printf( "could not read stream attribs (sizes)\n" );
+      return false;
+    }
+    else
+    {
+      if( streamInfo.dwProtocol == SP_PROT_TLS1_CLIENT )
+        m_certInfo.protocol = "TLS 1.0";
+      else
+        m_certInfo.protocol = "unknown";
+
+      std::ostringstream oss;
+      switch( streamInfo.aiCipher )
+      {
+        case CALG_3DES:
+          oss << "3DES";
+          break;
+        case CALG_AES_128:
+          oss << "AES";
+          break;
+        case CALG_AES_256:
+          oss << "AES";
+          break;
+        case CALG_DES:
+          oss << "DES";
+          break;
+        case CALG_RC2:
+          oss << "RC2";
+          break;
+        case CALG_RC4:
+          oss << "RC4";
+          break;
+        default:
+          oss << "unknown";
+      }
+
+      oss << " " << streamInfo.dwCipherStrength;
+      m_certInfo.cipher = oss.str();
+      oss.str( "" );
+
+      switch( streamInfo.aiHash  )
+      {
+        case CALG_MD5:
+          oss << "MD5";
+          break;
+        case CALG_SHA:
+          oss << "SHA";
+          break;
+        default:
+          oss << "unknown";
+      }
+
+      oss << " " << streamInfo.dwHashStrength;
+      m_certInfo.mac = oss.str();
+
+      m_certInfo.compression = "unknown";
+    }
+
+    m_secure = true;
+
+    return true;
+  }
+
+  bool Connection::handshakeLoop()
+  {
+    const int bufsize = 65536;
+    char *buf = (char*)malloc( bufsize );
+    if( !buf )
+      return false;
+
+    int bufFilled = 0;
+    int dataRecv = 0;
+    bool doRead = true;
+
+    SecBufferDesc outBufferDesc, inBufferDesc;
+    SecBuffer outBuffers[1], inBuffers[2];
+
+    SECURITY_STATUS ret = SEC_I_CONTINUE_NEEDED;
+
+    while( ret == SEC_I_CONTINUE_NEEDED ||
+           ret == SEC_E_INCOMPLETE_MESSAGE ||
+           ret == SEC_I_INCOMPLETE_CREDENTIALS )
+    {
+
+      if( doRead )
+      {
+        dataRecv = ::recv( m_socket, buf + bufFilled, bufsize - bufFilled, 0 );
+
+        if( dataRecv == SOCKET_ERROR || dataRecv == 0 )
+        {
+          break;
+        }
+
+        printf( "%d bytes handshake data received\n", dataRecv );
+
+        bufFilled += dataRecv;
+      }
+      else
+      {
+        doRead = true;
+      }
+
+      outBuffers[0].BufferType = SECBUFFER_TOKEN;
+      outBuffers[0].pvBuffer = NULL;
+      outBuffers[0].cbBuffer = 0;
+
+      outBufferDesc.ulVersion = SECBUFFER_VERSION;
+      outBufferDesc.cBuffers = 1;
+      outBufferDesc.pBuffers = outBuffers;
+
+      inBuffers[0].BufferType = SECBUFFER_TOKEN;
+      inBuffers[0].pvBuffer = buf;
+      inBuffers[0].cbBuffer = bufFilled;
+
+      inBuffers[1].BufferType = SECBUFFER_EMPTY;
+      inBuffers[1].pvBuffer = NULL;
+      inBuffers[1].cbBuffer = 0;
+
+      inBufferDesc.ulVersion = SECBUFFER_VERSION;
+      inBufferDesc.cBuffers = 2;
+      inBufferDesc.pBuffers = inBuffers;
+
+      printf( "buffers inited, calling InitializeSecurityContextA\n" );
+      long unsigned int sspiFlagsOut;
+      TimeStamp timeStamp;
+      ret = m_securityFunc->InitializeSecurityContextA( &m_credentials, &m_context, NULL,
+                                                        m_sspiFlags, 0,
+                                                        SECURITY_NATIVE_DREP, &inBufferDesc, 0, NULL,
+                                                        &outBufferDesc, &sspiFlagsOut, &timeStamp );
+      if( ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED ||
+          ( FAILED( ret ) && sspiFlagsOut & ISC_RET_EXTENDED_ERROR ) )
+      {
+        if( outBuffers[0].cbBuffer != 0 && outBuffers[0].pvBuffer != NULL )
+        {
+          printf( "ISCA returned, buffers not empty\n" );
+          dataRecv = ::send( m_socket, (const char*)outBuffers[0].pvBuffer, outBuffers[0].cbBuffer, 0  );
+          if( dataRecv == SOCKET_ERROR || dataRecv == 0 )
+          {
+            m_securityFunc->FreeContextBuffer( &outBuffers[0].pvBuffer );
+            m_securityFunc->DeleteSecurityContext( &m_context );
+            free( buf );
+            printf( "coudl not send bufer to server, exiting\n" );
+            return false;
+          }
+
+          m_securityFunc->FreeContextBuffer( outBuffers[0].pvBuffer );
+          outBuffers[0].pvBuffer = NULL;
+        }
+      }
+
+      if( ret == SEC_E_INCOMPLETE_MESSAGE )
+        continue;
+
+      if( ret == SEC_E_OK )
+      {
+        printf( "handshake successful\n" );
+        break;
+      }
+
+      if( FAILED( ret ) )
+      {
+        printf( "ISC failed: %ld\n", ret );
+        break;
+      }
+
+      if( ret == SEC_I_INCOMPLETE_CREDENTIALS )
+      {
+        printf( "server requested client credentials\n" );
+        ret = SEC_I_CONTINUE_NEEDED;
+        continue;
+      }
+
+      if( inBuffers[1].BufferType == SECBUFFER_EXTRA )
+      {
+        printf("some xtra mem in inbuf\n" );
+        MoveMemory( buf, buf + ( bufFilled - inBuffers[1].cbBuffer ),
+                   inBuffers[1].cbBuffer );
+
+        bufFilled = inBuffers[1].cbBuffer;
+      }
+      else
+      {
+        bufFilled = 0;
+      }
+    }
+
+    if( FAILED( ret ) )
+      m_securityFunc->DeleteSecurityContext( &m_context );
+
+    free( buf );
+
+    if( ret == SEC_E_OK )
+      return true;
+
+    return false;
+  }
+
+  inline bool Connection::tls_send( const void *data, size_t len )
+  {
+    if( len <= 0 )
+      return true;
+
+    SECURITY_STATUS ret;
+
+    m_obuffers[0].BufferType = SECBUFFER_STREAM_HEADER;
+    m_obuffers[0].pvBuffer = m_oBuffer;
+    m_obuffers[0].cbBuffer = m_streamSizes.cbHeader;
+
+    m_obuffers[1].BufferType = SECBUFFER_DATA;
+    m_obuffers[1].pvBuffer = m_messageOffset;
+
+    m_obuffers[2].BufferType = SECBUFFER_STREAM_TRAILER;
+    m_obuffers[2].cbBuffer = m_streamSizes.cbTrailer;
+
+    m_obuffers[3].BufferType = SECBUFFER_EMPTY;
+    m_obuffers[3].pvBuffer = NULL;
+    m_obuffers[3].cbBuffer = 0;
+
+    m_omessage.ulVersion = SECBUFFER_VERSION;
+    m_omessage.cBuffers = 4;
+    m_omessage.pBuffers = m_obuffers;
+
+    while( len > 0 )
+    {
+      if( m_streamSizes.cbMaximumMessage < len )
+      {
+        memcpy( m_messageOffset, data, m_streamSizes.cbMaximumMessage );
+        len -= m_streamSizes.cbMaximumMessage;
+        m_obuffers[1].cbBuffer = m_streamSizes.cbMaximumMessage;
+        m_obuffers[2].pvBuffer = m_messageOffset + m_streamSizes.cbMaximumMessage;
+      }
+      else
+      {
+        memcpy( m_messageOffset, data, len );
+        m_obuffers[1].cbBuffer = len;
+        m_obuffers[2].pvBuffer = m_messageOffset + len;
+        len = 0;
+      }
+
+      ret = m_securityFunc->EncryptMessage( &m_context, 0, &m_omessage, 0 );
+      if( ret != SEC_E_OK )
+      {
+        printf( "encryptmessage failed %ld\n", ret );
+        return false;
+      }
+
+      int t = ::send( m_socket, m_oBuffer,
+                      m_obuffers[0].cbBuffer + m_obuffers[1].cbBuffer + m_obuffers[2].cbBuffer, 0 );
+      if( t == SOCKET_ERROR || t == 0 )
+      {
+        printf( "could not send: %d\n", WSAGetLastError() );
+        return false;
+      }
+    }
+
+    return true;
+  }
+
+  inline int Connection::tls_recv( void *data, size_t len )
+  {
+    SECURITY_STATUS ret;
+    SecBuffer *dataBuffer = 0;
+    int readable = 0;
+
+    int maxLength = m_streamSizes.cbHeader + m_streamSizes.cbMaximumMessage + m_streamSizes.cbTrailer;
+
+    printf( "bufferOffset is %d\n", m_bufferOffset );
+
+    int t = ::recv( m_socket, m_iBuffer + m_bufferOffset, maxLength - m_bufferOffset, 0 );
+    if( t == SOCKET_ERROR )
+    {
+      printf( "got SocketError\n" );
+      return 0;
+    }
+    else if( t == 0 )
+    {
+      printf( "got connection close\n" );
+      return 0;
+    }
+    else
+      m_bufferOffset += t;
+
+    while( m_bufferOffset )
+    {
+      printf( "continuing with bufferOffset: %d\n", m_bufferOffset );
+
+      m_ibuffers[0].pvBuffer = m_iBuffer;
+      m_ibuffers[0].cbBuffer = m_bufferOffset;
+      m_ibuffers[0].BufferType = SECBUFFER_DATA;
+
+      m_ibuffers[1].BufferType = SECBUFFER_EMPTY;
+      m_ibuffers[2].BufferType = SECBUFFER_EMPTY;
+      m_ibuffers[3].BufferType = SECBUFFER_EMPTY;
+
+      m_imessage.ulVersion = SECBUFFER_VERSION;
+      m_imessage.cBuffers = 4;
+      m_imessage.pBuffers = m_ibuffers;
+
+      ret = m_securityFunc->DecryptMessage( &m_context, &m_imessage, 0, NULL );
+
+      if( ret == SEC_E_INCOMPLETE_MESSAGE )
+      {
+        printf( "recv'ed incomplete message\n" );
+        return readable;
+      }
+
+
+  //    if( ret == SEC_I_CONTEXT_EXPIRED )
+  //      return 0;
+
+      if( ret != SEC_E_OK && ret != SEC_I_RENEGOTIATE )
+      {
+        printf( "DecryptMessage returned %ld\n", ret );
+        printf( "GetLastError(): %ld\n", GetLastError() );
+        printf( "input buffer length: %d, read in this run: %d\n", m_bufferOffset, t );
+        return false;
+      }
+
+      m_bufferOffset = 0;
+
+      for( int i = 1; i < 4; ++i )
+      {
+        if( dataBuffer == 0 && m_ibuffers[i].BufferType == SECBUFFER_DATA )
+        {
+          dataBuffer = &m_ibuffers[i];
+        }
+        if( m_bufferOffset == 0 && m_ibuffers[i].BufferType == SECBUFFER_EXTRA )
+        {
+  //         m_extraBuffer = &m_ibuffers[i];
+  printf( "git exetra buffer, size %ld\n", m_ibuffers[i].cbBuffer );
+//          memcpy( m_iBuffer, m_ibuffers[i].pvBuffer, m_ibuffers[i].cbBuffer );
+//          m_bufferOffset = m_ibuffers[i].cbBuffer;
+        }
+      }
+
+      if( dataBuffer )
+      {
+        if( dataBuffer->cbBuffer > len )
+        {
+          memcpy( data, dataBuffer->pvBuffer, len );
+          return len;
+        }
+        else
+        {
+          memcpy( data, dataBuffer->pvBuffer, dataBuffer->cbBuffer );
+          readable += dataBuffer->cbBuffer;
+          printf( "recvbuffer (%d): %s\n", readable, data );
+        }
+      }
+
+      if( ret == SEC_I_RENEGOTIATE )
+      {
+        printf( "server requested reneg\n" );
+        ret = handshakeLoop();
+      }
+    }
+
+    return readable;
+  }
+
+  inline bool Connection::tls_dataAvailable()
+  {
+    return false;
+  }
+
+  inline void Connection::tls_cleanup()
+  {
+    m_securityFunc->DeleteSecurityContext( &m_context );
+  }
+#endif
+
 #ifdef HAVE_ZLIB
   bool Connection::initCompression( StreamFeature method )
   {
@@ -349,7 +907,7 @@
 
     m_state = StateConnecting;
 
-    if( m_port == -1 )
+    if( m_port == ( unsigned short ) -1 )
       m_socket = DNS::connect( m_server, m_logInstance );
     else
       m_socket = DNS::connect( m_server, m_port, m_logInstance );
@@ -392,6 +950,31 @@
     return m_socket;
   }
 
+  bool Connection::dataAvailable( int timeout )
+  {
+#ifdef HAVE_TLS
+    if( tls_dataAvailable() )
+    {
+        return true;
+    }
+#endif
+
+    fd_set fds;
+    struct timeval tv;
+
+    FD_ZERO( &fds );
+    FD_SET( m_socket, &fds );
+
+    tv.tv_sec = timeout / 1000;
+    tv.tv_usec = timeout % 1000;
+
+    if( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) >= 0 )
+    {
+      return FD_ISSET( m_socket, &fds ) ? true : false;
+    }
+    return false;
+  }
+
   ConnectionError Connection::recv( int timeout )
   {
     if( m_cancel )
@@ -404,39 +987,20 @@
     if( m_socket == -1 )
       return ConnNotConnected;
 
-    if( !m_fdRequested )
+    if( !m_fdRequested && !dataAvailable( timeout ) )
     {
-      fd_set fds;
-      struct timeval tv;
-
-      FD_ZERO( &fds );
-      FD_SET( m_socket, &fds );
-
-      tv.tv_sec = timeout;
-      tv.tv_usec = 0;
-
-      if( select( m_socket + 1, &fds, 0, 0, timeout == -1 ? 0 : &tv ) < 0 )
-        return ConnIoError;
-
-      if( !FD_ISSET( m_socket, &fds ) )
         return ConnNoError;
     }
 
     // optimize(?): recv returns the size. set size+1 = \0
     memset( m_buf, '\0', m_bufsize + 1 );
     int size = 0;
-#if defined( USE_GNUTLS )
+#ifdef HAVE_TLS
     if( m_secure )
     {
-      size = gnutls_record_recv( m_session, m_buf, m_bufsize );
+      size = tls_recv( m_buf, m_bufsize );
     }
     else
-#elif defined( USE_OPENSSL )
-    if( m_secure )
-    {
-      size = SSL_read( m_ssl, m_buf, m_bufsize );
-    }
-    else
 #endif
     {
 #ifdef SKYOS
@@ -456,34 +1020,30 @@
       // connection closed
       return ConnUserDisconnected;
     }
-    else
+
+    std::string buf;
+    buf.assign( m_buf, size );
+    if( m_compression && m_enableCompression )
+      buf = m_compression->decompress( buf );
+
+    Parser::ParserState ret = m_parser->feed( buf );
+    if( ret != Parser::PARSER_OK )
     {
-      std::string buf;
-      if( m_compression && m_enableCompression )
+      cleanup();
+      switch( ret )
       {
-        buf.assign( m_buf, size );
-        buf = m_compression->decompress( buf );
+        case Parser::PARSER_BADXML:
+          m_logInstance.log( LogLevelError, LogAreaClassConnection, "XML parse error" );
+          break;
+        case Parser::PARSER_NOMEM:
+          m_logInstance.log( LogLevelError, LogAreaClassConnection, "memory allocation error" );
+          break;
+        default:
+          m_logInstance.log( LogLevelError, LogAreaClassConnection, "unexpected error" );
+          break;
       }
-      else
-        buf.assign( m_buf, strlen( m_buf ) );
-
-      Parser::ParserState ret = m_parser->feed( buf );
-      if( ret != Parser::PARSER_OK )
-      {
-        cleanup();
-        switch( ret )
-        {
-          case Parser::PARSER_BADXML:
-            m_logInstance.log( LogLevelError, LogAreaClassConnection, "XML parse error" );
-            break;
-          case Parser::PARSER_NOMEM:
-            m_logInstance.log( LogLevelError, LogAreaClassConnection, "memory allocation error" );
-            break;
-          default:
-            break;
-        }
-        return ConnIoError;
-      }
+      //printf( "buffer data: %s\n", buf.c_str() );
+      return ConnIoError;
     }
 
     return ConnNoError;
@@ -505,10 +1065,10 @@
     return m_disconnect;
   }
 
-  void Connection::send( const std::string& data )
+  bool Connection::send( const std::string& data )
   {
     if( data.empty() || ( m_socket == -1 ) )
-      return;
+      return false;
 
     std::string xml;
     if( m_compression && m_enableCompression )
@@ -516,26 +1076,14 @@
     else
       xml = data;
 
-#if defined( USE_GNUTLS )
+#ifdef HAVE_TLS
     if( m_secure )
     {
-      int ret;
       size_t len = xml.length();
-      do
-      {
-        ret = gnutls_record_send( m_session, xml.c_str(), len );
-      }
-      while( ( ret == GNUTLS_E_AGAIN ) || ( ret == GNUTLS_E_INTERRUPTED ) );
+      if( tls_send( xml.c_str (), len ) == false )
+        return false;
     }
     else
-#elif defined( USE_OPENSSL )
-    if( m_secure )
-    {
-      int ret;
-      size_t len = xml.length();
-      ret = SSL_write( m_ssl, xml.c_str(), len );
-    }
-    else
 #endif
     {
       size_t num = 0;
@@ -543,30 +1091,27 @@
       while( num < len )
       {
 #ifdef SKYOS
-        num += ::send( m_socket, (unsigned char*)(xml.c_str()+num), len - num, 0 );
+        int sent = ::send( m_socket, (unsigned char*)(xml.c_str()+num), len - num, 0 );
 #else
-        num += ::send( m_socket, (xml.c_str()+num), len - num, 0 );
+        int sent = ::send( m_socket, (xml.c_str()+num), len - num, 0 );
 #endif
+        if( sent == -1 )
+          return false;
+
+        num += sent;
       }
     }
+
+    return true;
   }
 
   void Connection::cleanup()
   {
-#if defined( USE_GNUTLS )
+#ifdef HAVE_TLS
     if( m_secure )
     {
-      gnutls_bye( m_session, GNUTLS_SHUT_RDWR );
-      gnutls_deinit( m_session );
-      gnutls_certificate_free_credentials( m_credentials );
-      gnutls_global_deinit();
+      tls_cleanup();
     }
-#elif defined( USE_OPENSSL )
-    if( m_secure )
-    {
-      SSL_shutdown( m_ssl );
-      SSL_free( m_ssl );
-    }
 #endif
 
     if( m_socket != -1 )

Index: src/vcardhandler.h
===================================================================
--- src/vcardhandler.h	(.../0.8.1)	(revision 1434)
+++ src/vcardhandler.h	(.../0.8.2)	(revision 1434)
@@ -52,10 +52,10 @@
        * @param jid The JID to which this VCard belongs.
        * @param vcard The fetched VCard.
        */
-      virtual void handleVCard( const JID& jid, const VCard *vcard ) = 0;
+      virtual void handleVCard( const JID& jid, VCard *vcard ) = 0;
 
       /**
-       * This function is called to indicate a successful VCArd store operation
+       * This function is called to indicate the result of a VCard store operation
        * or any error that occurs.
        * @param context The operation which yielded the result.
        * @param jid The JID involved.

Index: src/macros.h
===================================================================
--- src/macros.h	(.../0.8.1)	(revision 1434)
+++ src/macros.h	(.../0.8.2)	(revision 1434)
@@ -14,7 +14,7 @@
 #ifndef GLOOX_MACROS_H__
 #define GLOOX_MACROS_H__
 
-#ifdef WIN32
+#ifdef MSVC
 #pragma warning( disable:4251 )
 #pragma warning( disable:4786 )
 #endif

Index: src/tests/vcard_test.cpp
===================================================================
--- src/tests/vcard_test.cpp	(.../0.8.1)	(revision 1434)
+++ src/tests/vcard_test.cpp	(.../0.8.2)	(revision 1434)
@@ -81,7 +81,7 @@
       printf("log: level: %d, area: %d, %s\n", level, area, message.c_str() );
     };
 
-    virtual void handleVCard( const JID& jid, const VCard *vcard )
+    virtual void handleVCard( const JID& jid, VCard *vcard )
     {
       ++m_count;
       printf( "received vcard for %s: %s, %d\n", jid.full().c_str(), vcard->tag()->xml().c_str(), m_count );
Index: src/tests/message_test.cpp
===================================================================
--- src/tests/message_test.cpp	(.../0.8.1)	(revision 1434)
+++ src/tests/message_test.cpp	(.../0.8.2)	(revision 1434)
@@ -114,10 +114,18 @@
         sub = "Re: " +  stanza->subject();
 
       m_messageEventFilter->raiseMessageEvent( MessageEventDisplayed );
+#if defined( WIN32 ) || defined( SKYOS )
+      Sleep( 1000 );
+#else
       sleep( 1 );
+#endif
       m_messageEventFilter->raiseMessageEvent( MessageEventComposing );
       m_chatStateFilter->setChatState( ChatStateComposing );
+#if defined( WIN32 ) || defined( SKYOS )
+      Sleep( 2000 );
+#else
       sleep( 2 );
+#endif
       m_session->send( msg, sub );
 
       if( stanza->body() == "quit" )

Index: src/tests/ibb_test.cpp
===================================================================
--- src/tests/ibb_test.cpp	(.../0.8.1)	(revision 1434)
+++ src/tests/ibb_test.cpp	(.../0.8.2)	(revision 1434)
@@ -116,10 +116,18 @@
         sub = "Re: " +  stanza->subject();
 
       m_messageEventFilter->raiseMessageEvent( MessageEventDisplayed );
+#if defined( WIN32 ) || defined( SKYOS )
+      Sleep( 1000 );
+#else
       sleep( 1 );
+#endif
       m_messageEventFilter->raiseMessageEvent( MessageEventComposing );
       m_chatStateFilter->setChatState( ChatStateComposing );
+#if defined( WIN32 ) || defined( SKYOS )
+      Sleep( 2000 );
+#else
       sleep( 2 );
+#endif
       m_session->send( msg, sub );
 
       if( stanza->body() == "quit" )

Index: src/gloox.h
===================================================================
--- src/gloox.h	(.../0.8.1)	(revision 1434)
+++ src/gloox.h	(.../0.8.2)	(revision 1434)
@@ -338,7 +338,7 @@
 
   const int XMPP_STREAM_VERSION_MAJOR       = 1;
   const int XMPP_STREAM_VERSION_MINOR       = 0;
-  const std::string GLOOX_VERSION           = "0.8.1";
+  const std::string GLOOX_VERSION           = "0.8.2";
 
   /**
    * This describes the possible states of a stream.

Index: src/connection.h
===================================================================
--- src/connection.h	(.../0.8.1)	(revision 1434)
+++ src/connection.h	(.../0.8.2)	(revision 1434)
@@ -34,6 +34,13 @@
 # include <gnutls/gnutls.h>
 # include <gnutls/x509.h>
 # define HAVE_TLS
+#elif defined( HAVE_WINTLS )
+# define USE_WINTLS
+# define SECURITY_WIN32
+# include <windows.h>
+# include <security.h>
+# include <sspi.h>
+# define HAVE_TLS
 #endif
 
 namespace gloox
@@ -62,7 +69,7 @@
        * to find out about the actual host:port.
        */
       Connection( Parser *parser, const LogSink& logInstance, const std::string& server,
-                  int port = -1 );
+                  unsigned short port = -1 );
 
       /**
        * Virtual destructor
@@ -77,7 +84,7 @@
 
       /**
        * Use this periodically to receive data from the socket and to feed the parser.
-       * @param timeout The timeout to use for select. Default means blocking.
+       * @param timeout The timeout to use for select in microseconds. Default of -1 means blocking.
        * @return The state of the connection.
        */
       ConnectionError recv( int timeout = -1 );
@@ -87,7 +94,7 @@
        * all data has been sent.
        * @param data The data to send.
        */
-      void send( const std::string& data );
+      bool send( const std::string& data );
 
       /**
        * Use this function to put the connection into 'receive mode'.
@@ -134,7 +141,7 @@
 
       /**
        * This function is used to enable stream compression as defined in JEP-0138.
-       * It is necessary because when compression is negotiated it is not enabled at once.
+       * It is necessary because when compression is negotiated it is not enabled instantly.
        */
       void enableCompression();
 #endif
@@ -173,11 +180,20 @@
 #endif
 
     private:
+      Connection &operator = ( const Connection & );
+      bool dataAvailable( int timeout = -1 );
+
       void cancel();
       void cleanup();
 
+#ifdef HAVE_TLS
+      bool tls_send( const void *data, size_t len );
+      int tls_recv( void *data, size_t len );
+      bool tls_dataAvailable();
+      void tls_cleanup();
+#endif
+
 #if defined( USE_GNUTLS )
-
       bool verifyAgainstCAs( gnutls_x509_crt_t cert, gnutls_x509_crt_t *CAList, int CAListSize );
       bool verifyAgainst( gnutls_x509_crt_t cert, gnutls_x509_crt_t issuer );
 
@@ -186,6 +202,25 @@
 
 #elif defined( USE_OPENSSL )
       SSL *m_ssl;
+#elif defined( USE_WINTLS )
+      bool handshakeLoop();
+
+      SecurityFunctionTableA *m_securityFunc;
+      CredHandle m_credentials;
+      CtxtHandle m_context;
+      SecBufferDesc m_imessage;
+      SecBufferDesc m_omessage;
+      SecBuffer m_ibuffers[4];
+      SecBuffer m_obuffers[4];
+      SecPkgContext_StreamSizes m_streamSizes;
+      HMODULE m_lib;
+
+      char *m_messageOffset;
+      char *m_iBuffer;
+      char *m_oBuffer;
+      int m_bufferSize;
+      int m_bufferOffset;
+      int m_sspiFlags;
 #endif
 
       StringList m_cacerts;
@@ -201,7 +236,7 @@
 
       char *m_buf;
       std::string m_server;
-      int m_port;
+      unsigned short m_port;
       int m_socket;
       const int m_bufsize;
       bool m_cancel;

Index: src/dns.cpp
===================================================================
--- src/dns.cpp	(.../0.8.1)	(revision 1434)
+++ src/dns.cpp	(.../0.8.2)	(revision 1434)
@@ -22,14 +22,15 @@
 #include <sys/types.h>
 
 #ifndef WIN32
+#include <arpa/nameser.h>
+#include <resolv.h>
+#include <netdb.h>
+#include <arpa/inet.h>
 #include <netinet/in.h>
-#include <resolv.h>
 #include <sys/socket.h>
 #include <sys/un.h>
-#include <netdb.h>
 #include <unistd.h>
 #include <sys/socket.h>
-#include <arpa/inet.h>
 #else
 #include <winsock.h>
 #endif

Index: src/Makefile.am
===================================================================
--- src/Makefile.am	(.../0.8.1)	(revision 1434)
+++ src/Makefile.am	(.../0.8.2)	(revision 1434)
@@ -20,8 +20,9 @@
                         vcardmanager.cpp
 
 libgloox_la_LDFLAGS = -version-info 3:0:0 -no-undefined -no-allow-shlib-undefined
-libgloox_la_LIBADD = 
+libgloox_la_LIBADD =
 libgloox_la_CFLAGS = $(CPPFLAGS) $(IKSEMEL_CFLAGS)
+libgloox_la_LIBS = -liksemel
 
 libglooxincludedir = $(includedir)/gloox
 libglooxinclude_HEADERS = adhoccommandprovider.h      privacymanager.h        tag.h \

Index: README.win32
===================================================================
--- README.win32	(.../0.8.1)	(revision 1434)
+++ README.win32	(.../0.8.2)	(revision 1434)
@@ -14,13 +14,8 @@
 Note: SRV resolving is disabled on Windows until I find a way to actually do this on that platform.
 
 
-Building gloox in MinGW
------------------------
-gloox should build out of the box on MinGW if you have Iksemel installed.
-
-
-Building Iksemel in MSVC
-------------------------
+Building Iksemel
+----------------
 - add the following lines to iksemel/include/common.h
 
 #ifdef WIN32
@@ -38,6 +33,11 @@
 - build
 
 
+Building gloox on MinGW
+-----------------------
+gloox should build out of the box on MinGW if you have Iksemel installed.
+
+
 Building gloox on MSVC
 ----------------------
 - use the included project file or create your own

Index: configure.ac
===================================================================
--- configure.ac	(.../0.8.1)	(revision 1434)
+++ configure.ac	(.../0.8.2)	(revision 1434)
@@ -4,7 +4,7 @@
 AC_INIT
 AC_CONFIG_SRCDIR([configure.ac])
 dnl Every other copy of the package version number gets its value from here
-AM_INIT_AUTOMAKE(gloox,0.8.1)
+AM_INIT_AUTOMAKE(gloox,0.8.2)
 
 dnl create a config.h file (Automake will add -DHAVE_CONFIG_H)
 AM_CONFIG_HEADER(config.h)
@@ -81,16 +81,17 @@
 
 dnl GnuTLS
 AC_ARG_WITH(gnutls, AC_HELP_STRING([--with-gnutls=[DIR]],
-      [Support Stream Encryption (needs GnuTLS)]),
+      [Support Stream Encryption using GnuTLS]),
       gnutls=$withval, gnutls=yes)
 if test "$gnutls" != "no"; then
   if test "$gnutls" != "yes"; then
     LDFLAGS="${LDFLAGS} -L$gnutls/lib"
     CPPFLAGS="${CPPFLAGS} -I$gnutls/include"
+    gnutls_path="$gnutls/bin/"
   fi
   AC_CHECK_HEADER(gnutls/gnutls.h,
   AC_CHECK_LIB(gnutls, gnutls_check_version,
-           [gnutls=yes LIBS="${LIBS} `libgnutls-config --libs`"], gnutls=no),
+           [gnutls=yes LIBS="${LIBS} `${gnutls_path}libgnutls-config --libs`"], gnutls=no),
            gnutls=no)
 fi
 if test "$gnutls" != "no" ; then
@@ -104,7 +105,7 @@
 dnl OpenSSL
 if test "$gnutls" == "no"; then
   AC_ARG_WITH(openssl, AC_HELP_STRING([--with-openssl=[DIR]],
-        [Support Stream Encryption (needs OpenSSL)]),
+        [Support Stream Encryption using OpenSSL]),
         openssl=$withval, openssl=yes)
   if test "$openssl" != "no"; then
     if test "$openssl" != "yes"; then
@@ -202,7 +203,8 @@
       AC_MSG_CHECKING([for dn_skipname in -lresolv (alternate version)])
       save_libs="$LIBS"
       LIBS="-lresolv $LIBS"
-      AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <resolv.h>]], [[dn_skipname(0,0)]])],
+      AC_LINK_IFELSE([AC_LANG_PROGRAM([[#include <netinet/in.h>
+ #include <resolv.h>]], [[dn_skipname(0,0)]])],
                      [AC_MSG_RESULT(yes)
                       AC_DEFINE(HAVE_DN_SKIPNAME)
                       have_dn_skipname=yes],
@@ -286,7 +288,7 @@
 dnl Checks for header files.
 AC_HEADER_STDC
 AC_CHECK_HEADERS(unistd.h strings.h errno.h arpa/nameser.h)
-AC_CHECK_FUNCS(ns_get16 __ns_get6)
+AC_CHECK_FUNCS(ns_get16 __ns_get16)
 
 dnl Checks for typedefs, structures, and compiler characteristics.
 AC_C_CONST

