static long s_srvRecvAll( PHB_CONSRV conn, void * buffer, long len ) { HB_BYTE * ptr = ( HB_BYTE * ) buffer; long lRead = 0, l; HB_MAXUINT end_timer; end_timer = conn->timeout > 0 ? hb_dateMilliSeconds() + conn->timeout : 0; while( lRead < len && ! conn->stop ) { if( conn->zstream ) l = hb_znetRead( conn->zstream, conn->sd, ptr + lRead, len - lRead, 1000 ); else l = hb_socketRecv( conn->sd, ptr + lRead, len - lRead, 0, 1000 ); if( l <= 0 ) { if( hb_socketGetError() != HB_SOCKET_ERR_TIMEOUT || hb_vmRequestQuery() != 0 || ( end_timer != 0 && end_timer <= hb_dateMilliSeconds() ) ) break; } else { lRead += l; conn->rd_count += l; } } return lRead; }
void hb_idleSleep( double dSeconds ) { if( dSeconds >= 0 ) { HB_MAXUINT end_timer = hb_dateMilliSeconds() + ( HB_MAXUINT ) ( dSeconds * 1000 ); do { hb_idleState(); } while( hb_dateMilliSeconds() < end_timer && hb_vmRequestQuery() == 0 ); hb_idleReset(); } }
/* Returns a double value between 0 and 1 */ double hb_random_num( void ) { HB_I32 * seed = SEED_PTR, t; t = *seed; if( t == 0 ) t = ( HB_I32 ) ( ( hb_dateMilliSeconds() ^ ( HB_PTRUINT ) hb_stackId() ) % MODULUS ); #if ! defined( HB_LONG_LONG_OFF ) t = ( HB_I32 ) ( ( HB_LONGLONG ) t * MULTIPLIER % MODULUS ); #else { const HB_I32 Q = MODULUS / MULTIPLIER; const HB_I32 R = MODULUS % MULTIPLIER; t = MULTIPLIER * ( t % Q ) - R * ( t / Q ); if( t < 0 ) t += MODULUS; } #endif *seed = t; return ( double ) ( t - 1 ) / ( MODULUS - 1 ); }
HB_BOOL hb_lppSend( PHB_LPP pSocket, const void * data, HB_SIZE len, HB_MAXINT timeout ) { HB_MAXINT nTime = 0; long lSend; if( ! pSocket->pSendBuffer ) { pSocket->pSendBuffer = ( char * ) hb_xgrab( len + 4 ); HB_PUT_LE_UINT32( pSocket->pSendBuffer, len ); hb_xmemcpy( pSocket->pSendBuffer + 4, data, len ); pSocket->nSendLen = len + 4; pSocket->nSendPos = 0; } if( timeout > 0 ) nTime = ( HB_MAXINT ) hb_dateMilliSeconds() + timeout; for( ;; ) { if( pSocket->nSendLen - pSocket->nSendPos < ( HB_SIZE ) LONG_MAX ) lSend = ( long ) ( pSocket->nSendLen - pSocket->nSendPos ); else lSend = LONG_MAX; lSend = hb_socketSend( pSocket->sd, pSocket->pSendBuffer + pSocket->nSendPos, lSend, 0, timeout ); if( lSend == -1 ) { pSocket->iError = hb_socketGetError(); return HB_FALSE; } pSocket->nSendPos += lSend; if( pSocket->nSendPos == pSocket->nSendLen ) { hb_xfree( pSocket->pSendBuffer ); pSocket->pSendBuffer = NULL; pSocket->iError = 0; return HB_TRUE; } if( timeout == 0 || ( timeout > 0 && ( timeout = nTime - ( HB_MAXINT ) hb_dateMilliSeconds() ) <= 0 ) ) { pSocket->iError = HB_SOCKET_ERR_TIMEOUT; return HB_FALSE; } } }
static long s_srvSendAll( PHB_CONSRV conn, void * buffer, long len ) { HB_BYTE * ptr = ( HB_BYTE * ) buffer; long lSent = 0, lLast = 1, l; HB_MAXUINT end_timer; if( ! conn->mutex || hb_threadMutexLock( conn->mutex ) ) { end_timer = conn->timeout > 0 ? hb_dateMilliSeconds() + conn->timeout : 0; while( lSent < len && ! conn->stop ) { if( conn->zstream ) l = hb_znetWrite( conn->zstream, conn->sd, ptr + lSent, len - lSent, 1000, &lLast ); else l = lLast = hb_socketSend( conn->sd, ptr + lSent, len - lSent, 0, 1000 ); if( l > 0 ) { lSent += l; conn->wr_count += l; } if( lLast <= 0 ) { if( hb_socketGetError() != HB_SOCKET_ERR_TIMEOUT || hb_vmRequestQuery() != 0 || ( end_timer != 0 && end_timer <= hb_dateMilliSeconds() ) ) break; } } if( conn->zstream && lLast > 0 && ! conn->stop ) { if( hb_znetFlush( conn->zstream, conn->sd, conn->timeout > 0 ? conn->timeout : -1 ) != 0 ) lSent = -1; } if( conn->mutex ) hb_threadMutexUnlock( conn->mutex ); } return lSent; }
static int arc4_seed_rand( void ) { HB_SIZE i; HB_U8 buf[ ADD_ENTROPY ]; srand( ( unsigned ) hb_dateMilliSeconds() ); for( i = 0; i < sizeof( buf ); i++ ) buf[ i ] = ( HB_U8 ) ( rand() % 256 ); /* not biased */ arc4_addrandom( buf, sizeof( buf ) ); memset( buf, 0, sizeof( buf ) ); return 0; }
HB_BOOL hb_lppRecv( PHB_LPP pSocket, void ** data, HB_SIZE * len, HB_MAXINT timeout ) { HB_MAXINT nTime = 0; long lRecv; if( ! pSocket->pRecvBuffer ) { pSocket->pRecvBuffer = ( char * ) hb_xgrab( 4 ); pSocket->nRecvLen = 0; pSocket->fRecvHasSize = HB_FALSE; } if( timeout > 0 ) nTime = ( HB_MAXINT ) hb_dateMilliSeconds() + timeout; for( ;; ) { if( ! pSocket->fRecvHasSize ) { lRecv = ( long ) ( 4 - pSocket->nRecvLen ); lRecv = hb_socketRecv( pSocket->sd, pSocket->pRecvBuffer + pSocket->nRecvLen, lRecv, 0, timeout ); if( lRecv == -1 ) { pSocket->iError = hb_socketGetError(); return HB_FALSE; } else if( lRecv == 0 ) { /* peer closed connection */ pSocket->iError = 0; return HB_FALSE; } pSocket->nRecvLen += lRecv; if( pSocket->nRecvLen < 4 ) { pSocket->iError = HB_SOCKET_ERR_TIMEOUT; return HB_FALSE; } pSocket->nRecvSize = HB_GET_UINT32( pSocket->pRecvBuffer ); if( pSocket->nLimit && pSocket->nRecvSize > pSocket->nLimit ) { /* protection against remote memory exhaust attack */ pSocket->iError = HB_LPP_ERR_TOOLARGE; hb_xfree( pSocket->pRecvBuffer ); pSocket->pRecvBuffer = NULL; return HB_FALSE; } pSocket->nRecvLen = 0; pSocket->fRecvHasSize = HB_TRUE; if( pSocket->nRecvSize != 4 ) pSocket->pRecvBuffer = ( char * ) hb_xrealloc( pSocket->pRecvBuffer, pSocket->nRecvSize ); } if( pSocket->nRecvSize - pSocket->nRecvLen < ( HB_SIZE ) LONG_MAX ) lRecv = ( long ) ( pSocket->nRecvSize - pSocket->nRecvLen ); else lRecv = LONG_MAX; lRecv = hb_socketRecv( pSocket->sd, pSocket->pRecvBuffer + pSocket->nRecvLen, lRecv, 0, timeout ); if( lRecv == -1 ) { pSocket->iError = hb_socketGetError(); return HB_FALSE; } else if( lRecv == 0 ) { /* peer closed connection */ pSocket->iError = 0; return HB_FALSE; } pSocket->nRecvLen += lRecv; if( pSocket->nRecvSize == pSocket->nRecvLen ) { * data = pSocket->pRecvBuffer; * len = pSocket->nRecvLen; pSocket->pRecvBuffer = NULL; pSocket->iError = 0; return HB_TRUE; } if( timeout == 0 || ( timeout > 0 && ( timeout = nTime - ( HB_MAXINT ) hb_dateMilliSeconds() ) <= 0 ) ) { pSocket->iError = HB_SOCKET_ERR_TIMEOUT; return HB_FALSE; } } }
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; }
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; }
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; }
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; }