Ejemplo n.º 1
0
/* flush data in stream structure - return number of bytes left in the
 * buffer which were not sent
 */
long hb_znetFlush( PHB_ZNETSTREAM pStream, HB_SOCKET sd, HB_MAXINT timeout,
                   HB_BOOL fSync )
{
   uInt uiSize = HB_ZNET_BUFSIZE - ( pStream->crypt ? 2 : 0 );

   if( fSync && pStream->wr.avail_out == uiSize &&
       pStream->wr.total_in == 0 && pStream->wr.total_out == 0 )
      return 0;

   if( pStream->wr.avail_out > 0 )
      pStream->err = deflate( &pStream->wr,
                              fSync ? Z_FULL_FLUSH : Z_PARTIAL_FLUSH );
   else
      pStream->err = Z_OK;

   while( pStream->wr.avail_out < uiSize )
   {
      if( hb_znetStreamWrite( pStream, sd, timeout ) <= 0 )
         break;

      if( pStream->err == Z_OK || pStream->err == Z_BUF_ERROR )
         pStream->err = deflate( &pStream->wr,
                                 fSync ? Z_FULL_FLUSH : Z_PARTIAL_FLUSH );
   }

   if( pStream->err == Z_BUF_ERROR )
      pStream->err = Z_OK;

   if( pStream->err != Z_OK )
      hb_socketSetError( HB_ZNET_SOCK_ERROR_BASE - pStream->err );

   return uiSize - pStream->wr.avail_out;
}
Ejemplo n.º 2
0
static int s_zsock_inbuffer( PHB_SOCKEX pSock )
{
   PHB_SOCKEX_Z pZ = HB_ZSOCK_GET( pSock );

   if( pSock->inbuffer == 0 && pZ->fDecompressIn )
   {
      int err;

      if( pSock->buffer == NULL )
      {
         if( pSock->readahead <= 0 )
            pSock->readahead = HB_ZSOCK_READAHEAD;
         pSock->buffer = ( HB_BYTE * ) hb_xgrab( pSock->readahead );
      }

      pZ->z_read.next_out  = ( Bytef * ) pSock->buffer;
      pZ->z_read.avail_out = ( uInt ) pSock->readahead;

      err = inflate( &pZ->z_read, Z_SYNC_FLUSH );
      if( err != Z_OK && err != Z_BUF_ERROR )
         hb_socketSetError( HB_ZSOCK_ERROR_BASE - err );
      pSock->inbuffer = pSock->readahead - pZ->z_read.avail_out;
   }
   return pSock->inbuffer > 0 ? 1 : 0;
}
Ejemplo n.º 3
0
static long s_sockexFlush( PHB_SOCKEX pSock, HB_MAXINT timeout, HB_BOOL fSync )
{
   PHB_SOCKEX_Z pZ = HB_ZSOCK_GET( pSock );
   long lResult = 0;

   if( pZ->fCompressOut &&
       ( ! fSync || pZ->z_write.avail_out != HB_ZSOCK_WRBUFSIZE ||
         pZ->z_write.total_in != 0 || pZ->z_write.total_out != 0 ) )
   {
      int err;

      if( pZ->z_write.avail_out > 0 )
         err = deflate( &pZ->z_write, fSync ? Z_FULL_FLUSH : Z_PARTIAL_FLUSH );
      else
         err = Z_OK;

      while( pZ->z_write.avail_out < HB_ZSOCK_WRBUFSIZE )
      {
         if( s_zsock_write( pZ, timeout ) <= 0 )
            break;
         if( err == Z_OK )
            err = deflate( &pZ->z_write, fSync ? Z_FULL_FLUSH : Z_PARTIAL_FLUSH );
      }
      if( err != Z_OK && err != Z_BUF_ERROR )
         hb_socketSetError( HB_ZSOCK_ERROR_BASE - err );
      lResult = HB_ZSOCK_WRBUFSIZE - pZ->z_write.avail_out;
   }
   return lResult + hb_sockexFlush( pZ->sock, timeout, fSync );
}
Ejemplo n.º 4
0
static int s_sockexCanRead( PHB_SOCKEX pSock, HB_BOOL fBuffer, HB_MAXINT timeout )
{
   if( pSock->inbuffer )
      return 1;
   else if( pSock->sd == HB_NO_SOCKET )
   {
      hb_socketSetError( HB_SOCKET_ERR_INVALIDHANDLE );
      return -1;
   }
   else if( SSL_pending( HB_SSLSOCK_GET( pSock )->ssl ) )
   {
      long len;

      if( pSock->buffer == NULL )
      {
         if( pSock->readahead <= 0 )
            pSock->readahead = HB_SSLSOCK_READAHEAD;
         pSock->buffer = ( HB_BYTE * ) hb_xgrab( pSock->readahead );
      }
      len = hb_ssl_socketRead( HB_SSLSOCK_GET( pSock ), pSock->sd,
                               pSock->buffer, pSock->readahead, 0 );
      if( len > 0 )
      {
         pSock->inbuffer = len;
         len = 1;
      }
      return ( int ) len;
   }
   return fBuffer ? 0 : hb_socketSelectRead( pSock->sd, timeout );
}
Ejemplo n.º 5
0
static long s_sockexRead( PHB_SOCKEX pSock, void * data, long len, HB_MAXINT timeout )
{
   long lRead = HB_MIN( pSock->inbuffer, len );

   if( lRead > 0 )
   {
      memcpy( data, pSock->buffer + pSock->posbuffer, lRead );
      pSock->inbuffer -= lRead;
      if( pSock->inbuffer )
         pSock->posbuffer += lRead;
      else
         pSock->posbuffer = 0;
      len -= lRead;
      if( len == 0 || pSock->sd == HB_NO_SOCKET )
         return lRead;
      data = ( HB_BYTE * ) data + lRead;
      timeout = 0;
   }
   else if( pSock->sd == HB_NO_SOCKET )
   {
      hb_socketSetError( HB_SOCKET_ERR_INVALIDHANDLE );
      return -1;
   }

   len = pSock->cargo ? hb_znetRead( HB_ZNET_GET( pSock ), pSock->sd, data, len, timeout ) :
                        hb_socketRecv( pSock->sd, data, len, 0, timeout );

   return lRead > 0 ? HB_MAX( len, 0 ) + lRead : len;
}
Ejemplo n.º 6
0
static long s_sockexFlush( PHB_SOCKEX pSock, HB_MAXINT timeout, HB_BOOL fSync )
{
   if( pSock->sd == HB_NO_SOCKET )
   {
      hb_socketSetError( HB_SOCKET_ERR_INVALIDHANDLE );
      return -1;
   }
   return pSock->cargo ? hb_znetFlush( HB_ZNET_GET( pSock ), pSock->sd, timeout, fSync ) : 0;
}
Ejemplo n.º 7
0
static long s_sockexWrite( PHB_SOCKEX pSock, const void * data, long len, HB_MAXINT timeout )
{
   if( pSock->sd == HB_NO_SOCKET )
   {
      hb_socketSetError( HB_SOCKET_ERR_INVALIDHANDLE );
      return -1;
   }
   return hb_ssl_socketWrite( HB_SSLSOCK_GET( pSock ), pSock->sd, data, len, timeout, NULL );
}
Ejemplo n.º 8
0
static int s_sockexCanWrite( PHB_SOCKEX pSock, HB_BOOL fBuffer, HB_MAXINT timeout )
{
   if( pSock->sd == HB_NO_SOCKET )
   {
      hb_socketSetError( HB_SOCKET_ERR_INVALIDHANDLE );
      return -1;
   }
   return fBuffer ? 0 : hb_socketSelectWrite( pSock->sd, timeout );
}
Ejemplo n.º 9
0
static long s_sockexWrite( PHB_SOCKEX pSock, const void * data, long len, HB_MAXINT timeout )
{
   if( pSock->sd == HB_NO_SOCKET )
   {
      hb_socketSetError( HB_SOCKET_ERR_INVALIDHANDLE );
      return -1;
   }
   return pSock->cargo ? hb_znetWrite( HB_ZNET_GET( pSock ), pSock->sd, data, len, timeout, NULL ) :
                         hb_socketSend( pSock->sd, data, len, 0, timeout );
}
Ejemplo n.º 10
0
/* check if data can be read from extended socket,
   return 1, 0 or -1 to indicate error.
   If fBuffer parameter is set to true then only data already read
   from socket and stored in memory buffer should be checked without
   any timeout. Such call is executed just before inside
   hb_sockexSelect() just before call to low level socket select()
   function. */
static int s_sockexCanRead( PHB_SOCKEX pSock, HB_BOOL fBuffer, HB_MAXINT timeout )
{
   if( pSock->inbuffer > 0 )
      return 1;
   else if( pSock->sd == HB_NO_SOCKET )
   {
      hb_socketSetError( HB_SOCKET_ERR_INVALIDHANDLE );
      return -1;
   }
   return fBuffer ? 0 : hb_socketSelectRead( pSock->sd, timeout );
}
Ejemplo n.º 11
0
static long s_sockexRead( PHB_SOCKEX pSock, void * data, long len, HB_MAXINT timeout )
{
   PHB_SOCKEX_Z pZ = HB_ZSOCK_GET( pSock );
   long lRecv = 0;

   if( pSock->inbuffer > 0 && len > 0 )
   {
      lRecv = HB_MIN( pSock->inbuffer, len );
      memcpy( data, pSock->buffer + pSock->posbuffer, lRecv );
      if( ( pSock->inbuffer -= lRecv ) > 0 )
         pSock->posbuffer += lRecv;
      else
         pSock->posbuffer = 0;
      return lRecv;
   }
   else if( pZ->fDecompressIn )
   {
      int err = Z_OK;

      pZ->z_read.next_out  = ( Bytef * ) data;
      pZ->z_read.avail_out = ( uInt ) len;
      pZ->z_read.total_out = 0;

      while( pZ->z_read.avail_out )
      {
         if( err == Z_BUF_ERROR && pZ->z_read.avail_in == 0 )
         {
            lRecv = hb_sockexRead( pZ->sock, pZ->rdbuf, HB_ZSOCK_RDBUFSIZE,
                                   pZ->z_read.total_out == 0 ? timeout : 0 );
            if( lRecv <= 0 )
               break;
            pZ->z_read.next_in = ( Bytef * ) pZ->rdbuf;
            pZ->z_read.avail_in = ( uInt ) lRecv;
         }
         else if( err != Z_OK )
         {
            hb_socketSetError( HB_ZSOCK_ERROR_BASE - err );
            lRecv = -1;
            break;
         }
         err = inflate( &pZ->z_read, Z_SYNC_FLUSH );
      }

      if( pZ->z_read.total_out != 0 )
         lRecv = ( long ) pZ->z_read.total_out;

      return pZ->z_read.total_out != 0 ? ( long ) pZ->z_read.total_out : lRecv;
   }
   else
      return hb_sockexRead( pZ->sock, data, len, timeout );
}
Ejemplo n.º 12
0
static int s_sockexCanWrite( PHB_SOCKEX pSock, HB_BOOL fBuffer, HB_MAXINT timeout )
{
   if( pSock->sd == HB_NO_SOCKET )
   {
      hb_socketSetError( HB_SOCKET_ERR_INVALIDHANDLE );
      return -1;
   }
   else if( fBuffer && pSock->cargo && /* HB_ZNET_GET( pSock )->wr.avail_out > 0 && */
            ( uInt ) ( HB_ZNET_BUFSIZE - ( HB_ZNET_GET( pSock )->crypt ? 2 : 0 ) ) <=
            HB_ZNET_GET( pSock )->wr.avail_out )
      return 1;
   else
      return fBuffer ? 0 : hb_socketSelectWrite( pSock->sd, timeout );
}
Ejemplo n.º 13
0
static long s_sockexRead( PHB_SOCKEX pSock, void * data, long len, HB_MAXINT timeout )
{
   long lRead = HB_MIN( pSock->inbuffer, len );

   if( lRead > 0 )
   {
      memcpy( data, pSock->buffer + pSock->posbuffer, lRead );
      pSock->inbuffer -= lRead;
      if( pSock->inbuffer )
         pSock->posbuffer += lRead;
      else
         pSock->posbuffer = 0;
      return lRead;
   }
   else if( pSock->sd == HB_NO_SOCKET )
   {
      hb_socketSetError( HB_SOCKET_ERR_INVALIDHANDLE );
      return -1;
   }
   return hb_ssl_socketRead( HB_SSLSOCK_GET( pSock ), pSock->sd, data, len, timeout );
}
Ejemplo n.º 14
0
static long s_sockexWrite( PHB_SOCKEX pSock, const void * data, long len, HB_MAXINT timeout )
{
   PHB_SOCKEX_Z pZ = HB_ZSOCK_GET( pSock );

   if( pZ->fCompressOut )
   {
      long lWritten = 0;

      pZ->z_write.next_in  = ( Bytef * ) data;
      pZ->z_write.avail_in = ( uInt ) len;

      while( pZ->z_write.avail_in )
      {
         int err;

         if( pZ->z_write.avail_out == 0 )
         {
            lWritten = s_zsock_write( pZ, timeout );
            if( lWritten <= 0 )
               break;
            timeout = 0;
         }
         err = deflate( &pZ->z_write, Z_NO_FLUSH );
         if( err != Z_OK )
         {
            if( err != Z_BUF_ERROR )
            {
               hb_socketSetError( HB_ZSOCK_ERROR_BASE - err );
               lWritten = -1;
            }
            break;
         }
      }

      return lWritten >= 0 ? ( long ) ( len - pZ->z_write.avail_in ) : lWritten;
   }
   else
      return hb_sockexWrite( pZ->sock, data, len, timeout );
}
Ejemplo n.º 15
0
/* write data using stream structure
 */
long hb_znetWrite( PHB_ZNETSTREAM pStream, HB_SOCKET sd, const void * buffer, long len, HB_MAXINT timeout, long * plast )
{
   long snd = 0;

   pStream->wr.next_in = ( Bytef * ) HB_UNCONST( buffer );
   pStream->wr.avail_in = ( uInt ) len;
   pStream->err = Z_OK;

   while( pStream->wr.avail_in )
   {
      if( pStream->wr.avail_out == 0 )
      {
         snd = hb_znetStreamWrite( pStream, sd, timeout );
         if( plast )
            *plast = snd;
         if( snd <= 0 )
            break;
         snd = 0;
      }
      pStream->err = deflate( &pStream->wr, Z_NO_FLUSH );
      if( pStream->err != Z_OK )
      {
         if( pStream->err == Z_BUF_ERROR )
            pStream->err = Z_OK;
         else
         {
            hb_socketSetError( HB_ZNET_SOCK_ERROR_BASE - pStream->err );
            snd = -1;
         }
         break;
      }
   }

   len -= pStream->wr.avail_in;

   return len == 0 ? snd : len;
}
Ejemplo n.º 16
0
long hb_ssl_socketRead( PHB_SSLSTREAM pStream, HB_SOCKET sd,
                        void * buffer, long len, HB_MAXINT timeout )
{
   HB_MAXUINT timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
   long lRead = -1;
   int iToRead = -1;

   /* sd = SSL_get_rfd( pStream->ssl ); */

#if LONG_MAX > INT_MAX
   if( len > INT_MAX )
      len = INT_MAX;
#endif

#if 0
   while( ERR_get_error() != 0 ) { /* eat pending errors */ }
#endif

   if( pStream->blocking ? timeout >= 0 : timeout < 0 )
   {
      if( hb_socketSetBlockingIO( sd, timeout < 0 ) >= 0 )
         pStream->blocking = ! pStream->blocking;
   }

   if( len > 0 )
   {
      iToRead = SSL_pending( pStream->ssl );
      if( iToRead <= 0 )
      {
         iToRead = timeout < 0 ? 1 : hb_socketSelectRead( sd, timeout );
         if( iToRead > 0 )
            iToRead = ( int ) len;
         else if( iToRead == 0 )
            hb_socketSetError( HB_SOCKET_ERR_TIMEOUT );
      }
      else if( iToRead > len )
         iToRead = ( int ) len;
   }

   while( iToRead > 0 )
   {
      lRead = SSL_read( pStream->ssl, buffer, iToRead );
      if( lRead > 0 )
         hb_socketSetError( 0 );
      else
      {
         int iError = SSL_get_error( pStream->ssl, ( int ) lRead );
         switch( iError )
         {
            case SSL_ERROR_ZERO_RETURN:
               hb_socketSetError( HB_SOCKET_ERR_PIPE );
               lRead = 0;
               break;
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_WRITE:
               if( hb_vmRequestQuery() == 0 )
               {
                  if( timeout > 0 )
                  {
                     HB_MAXUINT timecurr = hb_dateMilliSeconds();
                     if( timecurr > timer )
                        timeout -= timecurr - timer;
                     if( timeout > 0 )
                     {
                        timer = timecurr;
                        if( iError == SSL_ERROR_WANT_READ )
                           iError = hb_socketSelectRead( sd, timeout );
                        else
                           iError = hb_socketSelectWrite( sd, timeout );
                        if( iError > 0 )
                           continue;
                        else if( iError < 0 )
                           break;
                     }
                  }
                  hb_socketSetError( HB_SOCKET_ERR_TIMEOUT );
                  break;
               }
            default:
               hb_socketSetError( HB_SSL_SOCK_ERROR_BASE + iError );
         }
      }
      break;
   }

   return lRead;
}
Ejemplo n.º 17
0
PHB_SSLSTREAM hb_ssl_socketNew( HB_SOCKET sd, SSL * ssl, HB_BOOL fServer,
                                HB_MAXINT timeout, int * piResult )
{
   int iResult;

   PHB_SSLSTREAM pStream;
   HB_MAXUINT timer;

   pStream = ( HB_SSLSTREAM * ) hb_xgrabz( sizeof( HB_SSLSTREAM ) );
   timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();

   pStream->ssl = ssl;
   pStream->pSSL = hb_itemNew( hb_param( 2, HB_IT_POINTER ) );
   pStream->blocking = timeout < 0;
   if( hb_socketSetBlockingIO( sd, pStream->blocking ) < 0 )
      pStream->blocking = ! pStream->blocking;

   SSL_set_mode( ssl, HB_SSL_MODE_AUTO_RETRY );
   iResult = SSL_set_fd( ssl, sd );
   while( iResult == 1 )
   {
      if( fServer )
         iResult = SSL_accept( ssl );
      else
         iResult = SSL_connect( ssl );

      if( iResult != 1 && hb_vmRequestQuery() == 0 )
      {
         int iError = SSL_get_error( ssl, iResult );
         if( iError == SSL_ERROR_WANT_READ ||
             iError == SSL_ERROR_WANT_WRITE )
         {
            if( timeout < 0 )
            {
               iResult = 1;
               continue;
            }
            else if( timeout > 0 )
            {
               HB_MAXUINT timecurr = hb_dateMilliSeconds();
               if( timecurr > timer )
               {
                  timeout -= timecurr - timer;
                  timer = timecurr;
               }

               if( timeout > 0 )
               {
                  if( iError == SSL_ERROR_WANT_READ )
                     iError = hb_socketSelectRead( sd, timeout );
                  else
                     iError = hb_socketSelectWrite( sd, timeout );
                  if( iError > 0 )
                  {
                     iResult = 1;
                     continue;
                  }
               }
            }
            hb_socketSetError( HB_SOCKET_ERR_TIMEOUT );
         }
      }
      break;
   }

   if( iResult != 1 )
   {
      hb_ssl_socketClose( pStream );
      pStream = NULL;
   }
   else
      pStream->blocking = hb_socketSetBlockingIO( sd, HB_FALSE ) < 0;

   if( piResult )
      *piResult = iResult;

   return pStream;
}
Ejemplo n.º 18
0
PHB_SSLSTREAM hb_ssl_socketNew( HB_SOCKET sd, SSL * ssl, HB_BOOL fServer,
                                HB_MAXINT timeout, PHB_ITEM pSSL,
                                int * piResult )
{
   int iResult;

   PHB_SSLSTREAM pStream;
   HB_MAXUINT timer;

   pStream = ( HB_SSLSTREAM * ) hb_xgrabz( sizeof( HB_SSLSTREAM ) );
   timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();

   pStream->ssl = ssl;
   pStream->pSSL = pSSL ? hb_itemNew( pSSL ) : NULL;
   pStream->blocking = timeout < 0;
   if( hb_socketSetBlockingIO( sd, pStream->blocking ) < 0 )
      pStream->blocking = ! pStream->blocking;

   SSL_set_mode( ssl, HB_SSL_MODE_AUTO_RETRY );
   iResult = SSL_set_fd( ssl, sd );  /* Truncates `sd` on win64. OpenSSL bug: https://rt.openssl.org/Ticket/Display.html?id=1928&user=guest&pass=guest */
   while( iResult == 1 )
   {
      if( fServer )
         iResult = SSL_accept( ssl );
      else
         iResult = SSL_connect( ssl );

      if( iResult != 1 && hb_vmRequestQuery() == 0 )
      {
         int iError = SSL_get_error( ssl, iResult );
         if( iError == SSL_ERROR_WANT_READ ||
             iError == SSL_ERROR_WANT_WRITE )
         {
            if( timeout < 0 )
            {
               iResult = 1;
               continue;
            }
            else if( timeout > 0 )
            {
               HB_MAXUINT timecurr = hb_dateMilliSeconds();
               if( timecurr > timer )
               {
                  timeout -= timecurr - timer;
                  if( timeout < 0 )
                     timeout = 0;
                  timer = timecurr;
               }

               if( timeout > 0 )
               {
                  if( iError == SSL_ERROR_WANT_READ )
                     iError = hb_socketSelectRead( sd, timeout );
                  else
                     iError = hb_socketSelectWrite( sd, timeout );
                  if( iError > 0 )
                  {
                     iResult = 1;
                     continue;
                  }
               }
            }
            hb_socketSetError( HB_SOCKET_ERR_TIMEOUT );
         }
      }
      break;
   }

   if( iResult != 1 )
   {
      hb_ssl_socketClose( pStream );
      pStream = NULL;
   }
   else
      pStream->blocking = hb_socketSetBlockingIO( sd, HB_FALSE ) < 0;

   if( piResult )
      *piResult = iResult;

   return pStream;
}
Ejemplo n.º 19
0
long hb_ssl_socketWrite( PHB_SSLSTREAM pStream, HB_SOCKET sd,
                         const void * buffer, long len, HB_MAXINT timeout,
                         long * plast )
{
   HB_MAXUINT timer = timeout <= 0 ? 0 : hb_dateMilliSeconds();
   long lWritten = 0, lWr = 0;

   /* sd = SSL_get_wfd( pStream->ssl ); */

#if LONG_MAX > INT_MAX
   if( len > INT_MAX )
      len = INT_MAX;
#endif

#if 0
   while( ERR_get_error() != 0 ) { /* eat pending errors */ }
#endif

   if( pStream->blocking ? timeout >= 0 : timeout < 0 )
   {
      if( hb_socketSetBlockingIO( sd, timeout < 0 ) >= 0 )
         pStream->blocking = ! pStream->blocking;
   }

   while( len > 0 )
   {
      lWr = SSL_write( pStream->ssl, buffer, ( int ) len );

      if( plast )
         *plast = lWr;

      if( lWr > 0 )
      {
         lWritten += lWr;
         len -= lWr;
         buffer = ( const char * ) buffer + lWr;
         hb_socketSetError( 0 );
      }
      else
      {
         int iError = SSL_get_error( pStream->ssl, ( int ) lWr );
         switch( iError )
         {
            case SSL_ERROR_WANT_READ:
            case SSL_ERROR_WANT_WRITE:
               if( hb_vmRequestQuery() == 0 )
               {
                  if( timeout > 0 )
                  {
                     HB_MAXUINT timecurr = hb_dateMilliSeconds();
                     if( timecurr > timer )
                        timeout -= timecurr - timer;
                     if( timeout > 0 )
                     {
                        timer = timecurr;
                        if( iError == SSL_ERROR_WANT_READ )
                           iError = hb_socketSelectRead( sd, timeout );
                        else
                           iError = hb_socketSelectWrite( sd, timeout );
                        if( iError > 0 )
                           continue;
                     }
                     else
                        iError = 0;
                  }
                  else
                     iError = 0;
                  if( lWritten == 0 && iError == 0 )
                     hb_socketSetError( HB_SOCKET_ERR_TIMEOUT );
                  break;
               }
            default:
               hb_socketSetError( HB_SSL_SOCK_ERROR_BASE + iError );
         }
         break;
      }
   }

   return lWritten != 0 ? lWritten : lWr;
}
Ejemplo n.º 20
0
/* read data using stream structure
 */
long hb_znetRead( PHB_ZNETSTREAM pStream, HB_SOCKET sd, void * buffer, long len, HB_MAXINT timeout )
{
   long rec = 0;

   pStream->rd.next_out = ( Bytef * ) buffer;
   pStream->rd.avail_out = ( uInt ) len;
   pStream->err = Z_OK;

   while( pStream->rd.avail_out )
   {
      if( pStream->rd.avail_in == 0 && pStream->err == Z_BUF_ERROR )
      {
         if( pStream->skip_in )
         {
            pStream->rd.next_in += pStream->skip_in;
            pStream->skip_in = 0;
         }
         if( pStream->crypt_in && pStream->rd.next_in > pStream->inbuf )
            memmove( pStream->inbuf, pStream->rd.next_in, pStream->crypt_in );
         pStream->rd.next_in = pStream->inbuf;

         if( ! pStream->crypt || pStream->crypt_in < 8 )
         {
            if( pStream->rd.avail_out != ( uInt ) len )
               timeout = 0;
            rec = hb_socketRecv( sd, pStream->inbuf + pStream->crypt_in, HB_ZNET_BUFSIZE - pStream->crypt_in, 0, timeout );
            if( rec <= 0 )
               break;
         }

         if( pStream->crypt )
         {
            pStream->crypt_in += rec;
            if( pStream->crypt_size == 0 )
            {
               if( pStream->crypt_in >= 8 )
               {
                  hb_znetDecrypt( pStream, pStream->rd.next_in );
                  pStream->crypt_size = HB_GET_BE_UINT16( pStream->rd.next_in );
                  pStream->rd.next_in += 2;
                  pStream->crypt_in -= 8;
                  rec = HB_MIN( pStream->crypt_size, 6 );
                  pStream->crypt_size -= ( uInt ) rec;
                  pStream->rd.avail_in += ( uInt ) rec;
                  pStream->skip_in = ( uInt ) ( 6 - rec );
                  rec = 0;
               }
            }
            if( pStream->skip_in == 0 )
            {
               long l = ( pStream->crypt_size + 0x07 ) & ~0x07;
               rec = pStream->crypt_in & ~0x07;
               if( rec > l )
                  rec = l;
               /* decrypt the buffer */
               for( l = 0; l < rec; l += 8 )
                  hb_znetDecrypt( pStream, pStream->rd.next_in + pStream->rd.avail_in + l );
               pStream->crypt_in -= rec;
               if( ( uInt ) rec > pStream->crypt_size )
               {
                  pStream->skip_in = rec - pStream->crypt_size;
                  rec = pStream->crypt_size;
               }
               pStream->crypt_size -= rec;
            }
         }

         pStream->rd.avail_in += ( uInt ) rec;
         rec = 0;
         if( pStream->rd.avail_in == 0 )
         {
            if( pStream->rd.avail_out == ( uInt ) len )
               continue;
            else
               break;
         }
      }
      pStream->err = inflate( &pStream->rd, Z_SYNC_FLUSH );
/*
      if( pStream->err == Z_STREAM_END && pStream->rd.avail_in == 0 )
         pStream->err = Z_BUF_ERROR;
 */
      if( pStream->err != Z_OK &&
          ! ( pStream->err == Z_BUF_ERROR && pStream->rd.avail_in == 0 ) )
      {
         hb_socketSetError( HB_ZNET_SOCK_ERROR_BASE - pStream->err );
         rec = -1;
         break;
      }
   }

   len -= pStream->rd.avail_out;

   return len == 0 ? rec : len;
}