//interface defined by EdStream
int CgiConnection::onRead()
{
    if ( !getConnector() )
        return -1;
    if ( D_ENABLED( DL_MEDIUM ) )
        LOG_D(( getLogger(), "[%s] CgiConnection::onRead()\n", getLogId() ));
    int len = 0;
    int ret = 0;
    do
    {
        len = ret = read( HttpGlobals::g_achBuf, G_BUF_SIZE );
        if ( ret > 0 )
        {
            if ( D_ENABLED( DL_MEDIUM ) )
                LOG_D(( getLogger(), "[%s] process STDOUT %d bytes",
                    getLogId(), len ));
            //printf( ">>read %d bytes from CGI\n", len );
            //achBuf[ ret ] = 0;
            //printf( "%s", achBuf );
            ret = getConnector()->processRespData( HttpGlobals::g_achBuf, len );
            if ( ret == -1 )
                break;
        }
        else
        {
            if ( ret )
                getConnector()->endResponse( 0, 0 );
            break;
        }    
    }while( len == G_BUF_SIZE );
    if (( ret != -1 )&&( getConnector() ))
        getConnector()->flushResp();
    return ret;
}
void FileCacheDataEx::release()
{
    switch( getStatus() )
    {
    case MMAPED:
        if ( m_pCache )
        {
            if ( D_ENABLED( DL_MORE ))
                LOG_D(( "[MMAP] Release mapped data at %p", m_pCache ));
            munmap( m_pCache, m_lSize );
            s_iCurTotalMMAPCache -= m_lSize;
        }
        break;
    case CACHED:
        if ( m_pCache )
        {
            s_iCurTotalInMemCache -= m_lSize;
            free( m_pCache );
        }
        break;
    default:
        if ( m_fd != -1 )
        {
            close( m_fd );
            m_fd = -1;
        }
    }
    memset( &m_iStatus, 0,
            (char *)(&m_pCache + 1) - (char *)&m_iStatus );
}
void LshttpdMain::gracefulRestart()
{
    if ( D_ENABLED( DL_LESS ) )
        LOG_D(( "Graceful Restart... " ));
    close( m_fdAdmin );
    broadcastSig( SIGTERM, 1 );
    s_iRunning = 0;
    m_pidFile.closePidFile();
    m_pServer->passListeners();
    int pid = fork();
    if ( !pid )
    {
        char achCmd[1024];
        int fd = HttpGlobals::getStdErrLogger()->getStdErr();
        if ( fd != 2 )
            close( fd );
        int len = getFullPath( "bin/litespeed", achCmd, 1024 );
        achCmd[len - 10] = 0;
        chdir( achCmd );
        achCmd[len - 10] = '/';
        if ( execl( achCmd, "litespeed", NULL  ) )
        {
            LOG_ERR(( "Failed to start new instance of LiteSpeed Web server!" ));
        }
        exit( 0 );
    }
    if ( pid == -1 )
        LOG_ERR(( "Failed to restart the server!" ));
}
Exemple #4
0
int L4Handler::init(HttpReq &req, const GSockAddr *pGSockAddr, const char *pIP, int iIpLen)
{
    int ret = m_pL4conn->init(pGSockAddr);
    if (ret != 0)
        return ret;
    
    int hasSlashR = 1; //"\r\n"" or "\n"
    LoopBuf *pBuff = m_pL4conn->getBuf();
    pBuff->append(req.getOrgReqLine(), req.getHttpHeaderLen());
    char *pBuffEnd = pBuff->end();
    assert(pBuffEnd[-1] == '\n');
    if (pBuffEnd[-2] == 'n')
        hasSlashR = 0;
    else
    {
        assert(pBuffEnd[-2] == '\r');
    }
    
    pBuff->used( -1 * hasSlashR - 1);
    pBuff->append("X-Forwarded-For", 15);
    pBuff->append(": ", 2);
    pBuff->append(pIP, iIpLen);
    if (hasSlashR)
        pBuff->append("\r\n\r\n", 4);
    else
        pBuff->append("\n\n", 2);
    
    continueRead();
    if ( D_ENABLED( DL_LESS ) )
    {
        LOG_D ((getLogger(), "[%s] L4Handler: init web socket, reqheader [%s], len [%d]",
                getLogId(), req.getOrgReqLine(), req.getHttpHeaderLen() ));
    }
    return 0;
}
int  FcgiRequest::processStdErr( char * pBuf, int size )
{
    HttpExtConnector * pConnector = getConnector();
    assert( pConnector );
    if ( D_ENABLED( DL_MEDIUM ) )
        LOG_D(( pConnector->getLogger(), "[%s] process STDERR %d bytes",
            pConnector->getLogId(), size ));
    return pConnector->processErrData( pBuf, size );
}
int FcgiRequest::sendAbortRec( )
{
    if ( D_ENABLED( DL_LESS ) )
        LOG_D(( getLogger(), "[%s] [FCGI] send abort packet!",
            getConnector()->getLogId() ));
    FCGI_Header rec;
    FcgiRecord::setRecordHeader( rec, FCGI_ABORT_REQUEST, m_iId, 0 );
    return m_pFcgiConn->sendRecord( (const char *)&rec, sizeof( rec ) );
}
int LshttpdMain::preFork()
{
    if ( D_ENABLED( DL_LESS ) )
        LOG_D(( "[AutoRestarter] prepare to fork new child process to handle request!" ));
    
    if ( LsiApiHooks::getServerHooks()->isEnabled( LSI_HKPT_MAIN_PREFORK) )
        LsiApiHooks::getServerHooks()->runCallbackNoParam(LSI_HKPT_MAIN_PREFORK, NULL);
    return 0;
}
int LsapiConn::sendAbortReq()
{
    if ( D_ENABLED( DL_LESS ) )
        LOG_D(( getLogger(), "[%s] [LSAPI] send abort packet!",
            getLogId() ));
    lsapi_packet_header rec;
    LsapiReq::buildPacketHeader( &rec, LSAPI_ABORT_REQUEST, LSAPI_PACKET_HEADER_LEN );
    return write( (char *)&rec, sizeof( rec ) );
}
int FcgiRequest::onStdOut()
{
    HttpExtConnector * pConnector = getConnector();
    assert( pConnector );
    if ( D_ENABLED( DL_MEDIUM ) )
        LOG_D(( pConnector->getLogger(), "[%s] onStdOut()",
            pConnector->getLogId() ));
    return pConnector->extInputReady();

}
int CgiConnection::onError()
{
    if ( !getConnector() )
        return -1;
    if ( D_ENABLED( DL_MEDIUM ) )
        LOG_D(( getLogger(), "[%s] CgiConnection::onError()\n", getLogId() ));
    //getState() = HEC_COMPLETE;
    getConnector()->endResponse( SC_500, 0 );
    return -1;
}
Exemple #11
0
int JConn::processPacketHeader( unsigned char * &p )
{
    if (( *p != AJP_RESP_PREFIX_B1)||
        ( *(p+1) != AJP_RESP_PREFIX_B2 ))
    {
        LOG_ERR(( getLogger(), "[%s] Invalid AJP response signature %x%x",
                    getLogId(), (int) *p,
                    (int) *(p+1) ));
        return -1;
    }
    p+= 2;
    m_curPacketSize = getInt( p );
    if ( m_curPacketSize > AJP_MAX_PKT_BODY_SIZE )
    {
        LOG_ERR(( getLogger(), "[%s] packet size is too large - %d",
                getLogId(), m_curPacketSize ));
        return -1;
    }
    m_packetType = *p++;
    m_packetLeft = m_curPacketSize - 1;
    switch(m_packetType)
    {
    case AJP13_RESP_BODY_CHUNK:
        m_iPacketState = CHUNK_LEN;
        break;
    case AJP13_RESP_HEADERS:
        m_iPacketState = STATUS_CODE;
        break;
    case AJP13_END_RESP:
        if ( *p != 1)
        {
            if ( D_ENABLED( DL_LESS ) )
                LOG_D(( getLogger(),
                    "[%s] close connection required by servlet engine %s ",
                    getLogId(), getWorker()->getURL() ));
            
            setState( CLOSING );
        }
        p++;
        if ( getConnector() )
        {
            incReqProcessed();
            if ( getState() == ABORT )
                setState( PROCESSING );
            setInProcess( 0 );            
            getConnector()->endResponse( 0, 0 );
        }
        break;
    case AJP13_MORE_REQ_BODY:
    default:
        break;
    }
    return 0;    
}
int LsapiConn::doError( int err)
{
    if ( D_ENABLED( DL_LESS ) )
        LOG_D(( getLogger(), "[%s] LsapiConn::doError()", getLogId() ));
    if ( getConnector())
    {
        int state = getConnector()->getState();
        if ( !(state & (HEC_FWD_RESP_BODY | HEC_ABORT_REQUEST
                        | HEC_ERROR|HEC_COMPLETE) ))
        {
            if ( D_ENABLED( DL_LESS ) )
                LOG_D(( getLogger(), "[%s] Lsapi Peer closed connection, "
                            "try another connection!", getLogId() ));
            connError( err );
            return 0;
        }
        if ( !(state & HEC_COMPLETE) )
            getConnector()->endResponse( SC_500, -1 );
    }
    return 0;
}
int StaticFileCacheData::tryCreateGziped()
{
    if ( !s_iAutoUpdateStaticGzip )
        return -1;
    off_t size = m_fileData.getFileSize();
    if (( size > s_iMaxFileSize )||( size < s_iMinFileSize ))
        return -1;
    char *p = m_gzippedPath.buf() + m_gzippedPath.len() + 4;
    int fd = createLockFile( m_gzippedPath.buf(), p );
    if ( fd == -1 )
        return -1;
    close( fd );
    if ( size < 409600 )
    {

        long ret = compressFile();
        *p = 'l';
        unlink( m_gzippedPath.buf() );
        *p = 0;
        return ret;

    }
    else
    {
        //IMPROVE: move this to a standalone process,
        //          fork() is too expensive.

        if ( D_ENABLED( DL_MORE ))
        {
            LOG_D(( "To compressed file %s in another process.",
                    m_real.c_str() ));
        }
        int forkResult;
        forkResult = fork();
        if( forkResult )  //error or parent process
        {
            return -1;
        }
        //child process
        setpriority( PRIO_PROCESS, 0, 5 );

        long ret = compressFile();
        if ( ret == -1 )
        {
            LOG_WARN(( "Failed to compress file %s!", m_real.c_str() ));

        }
        *p = 'l';
        unlink( m_gzippedPath.buf() );
        *p = 0;
        exit(1);
    }
}
Exemple #14
0
int L4Handler::onWriteEx()
{
    bool full = ((getBuf()->available() == 0) ? true : false);
    int length;
    
    while ((length = getBuf()->blockSize()) > 0 )
    {
        int n = getStream()->write(getBuf()->begin(), length);
        if ( D_ENABLED( DL_LESS ) )
                LOG_D ((getLogger(), "[%s] L4Handler: write [%d of %d]", getLogId(), n, length ));
        
        if (n > 0)
            getBuf()->pop_front(n);
        else if ( n == 0 )
            break;
        else // if (n < 0)
        {
            closeBothConnection();
            return -1;
        }
    }
    
    if (getBuf()->available() != 0)
    {
        if (full)
            m_pL4conn->continueRead();
    
        if ( getBuf()->empty() )
        {
            suspendWrite();
            if ( D_ENABLED( DL_LESS ) )
            {
                LOG_D(( getLogger(), "[%s] [L4conn] m_pL4conn->continueRead",
                    getLogId() ));
            }
        }
    }
        
    return 0;
}
Exemple #15
0
int L4Handler::onReadEx()
{
    bool empty = m_pL4conn->getBuf()->empty();
    int space;
    
    while ( (space = m_pL4conn->getBuf()->contiguous()) > 0)
    {
        int n = getStream()->read(m_pL4conn->getBuf()->end(), space);
        if ( D_ENABLED( DL_LESS ) )
        {
            LOG_D ((getLogger(), "[%s] L4Handler: read [%d]", getLogId(), n ));
        }
        
        if (n > 0) 
            m_pL4conn->getBuf()->used(n);
        else if ( n == 0 )
            break;
        else // if (n < 0)
        {
            closeBothConnection();
            return -1;
        }
    }
    
    if ( !m_pL4conn->getBuf()->empty() )
    {
        m_pL4conn->doWrite();
        if ( !m_pL4conn->getBuf()->empty() && empty)
            m_pL4conn->continueWrite();
  
        if (m_pL4conn->getBuf()->available() <= 0 )
        {
            suspendRead();
            if ( D_ENABLED( DL_LESS ) )
                LOG_D ((getLogger(), "[%s] L4Handler: suspendRead", getLogId() ));
        }
    }
    
    return 0;
}
int CgiConnection::onWrite()
{
    if ( !getConnector() )
        return -1;
    if ( D_ENABLED( DL_MEDIUM ) )
        LOG_D(( getLogger(), "[%s] CgiConnection::onWrite()\n", getLogId() ));
    int ret = extOutputReady();
    if (!( getConnector()->getState() & HEC_FWD_REQ_BODY ))
    {
        suspendWrite();
    }
    return ret;
}
Exemple #17
0
int SSIEngine::executeComponent( HttpSession *pSession, SSIComponent * pComponent )
{
    AutoBuf * pBuf;
    int ret;

    if ( D_ENABLED( DL_MORE ) )
        LOG_D(( pSession->getLogger(), "[%s] SSI Process component: %d",
               pSession->getLogId(), pComponent->getType() ));

    switch( pComponent->getType() )
    {
    case SSIComponent::SSI_String:
        pBuf = pComponent->getContentBuf();
        pSession->appendDynBody( pBuf->begin(), pBuf->size() );
        break;
    case SSIComponent::SSI_Config:
        updateSSIConfig( pSession, pComponent, pSession->getReq()->getSSIRuntime() );
        break;
    case SSIComponent::SSI_Echo:
        processEcho( pSession, pComponent );
        break;
    case SSIComponent::SSI_Exec:
        ret = processExec( pSession, pComponent );
        return ret;
        break;
    case SSIComponent::SSI_FSize:
    case SSIComponent::SSI_Flastmod:
        processFileAttr( pSession, pComponent );
        break;
    case SSIComponent::SSI_Include:
        ret = processInclude( pSession, pComponent );
        return ret;
        break;
    case SSIComponent::SSI_Printenv:
        processPrintEnv( pSession );
        break;
    case SSIComponent::SSI_Set:
        processSet( pSession, pComponent );
        break;
    case SSIComponent::SSI_If:
    case SSIComponent::SSI_Elif:
        processIf( pSession, (SSI_If *)pComponent );
        break;
        //SSI_Else,
        //SSI_Elif,
        //SSI_Endif,

    }
    return 0;
}
void LocalWorker::removeUnixSocket()
{
    const GSockAddr &addr = ((LocalWorkerConfig *)getConfigPointer())->getServerAddr();
    if (( m_fdApp >= 0 )&&( getPidList()->size() > 0 )&&
        ( addr.family() == PF_UNIX ))
    {
        if ( D_ENABLED( DL_LESS ) )
            LOG_D(( "[%s] remove unix socket: %s", getName(),
                addr.getUnix() ));
        unlink( addr.getUnix() );
        close( m_fdApp );
        m_fdApp = -2;
        getConfigPointer()->altServerAddr();        
    }
}
void LocalWorker::cleanStopPids( )
{
    if (( m_pidListStop )&&
        ( m_pidListStop->size() > 0 ))
    {
        pid_t pid;
        PidList::iterator iter, iterDel;
        for( iter = m_pidListStop->begin(); iter != m_pidListStop->end();  )
        {
            pid = (pid_t)(long)iter->first();
            long delta = DateTime::s_curTime - (long)iter->second();
            int sig = 0;
            iterDel = iter;
            iter = m_pidListStop->next( iter );
            if ( delta > GRACE_TIMEOUT )
            {
                if (( kill(  pid, 0 ) == -1 )&&( errno == ESRCH ))
                {
                    m_pidListStop->erase( iterDel );
                    continue;
                }
                if ( delta > KILL_TIMEOUT )
                {
                    sig = SIGKILL;
                    LOG_NOTICE(( "[%s] Send SIGKILL to process [%d] that won't stop.",
                            getName(), pid ));
                }
                else 
                {
                    sig = m_sigGraceStop;
                    LOG_NOTICE(( "[%s] Send SIGTERM to process [%d].",
                            getName(), pid ));
                }
                if ( kill(  pid , sig ) != -1 )
                {
                    if ( D_ENABLED( DL_LESS ) )
                        LOG_D(( "[%s] kill pid: %d", getName(), pid ));
                }
                else if ( errno == EPERM )
                {
                    PidRegistry::markToStop( pid, KILL_TYPE_TERM );
                }
            }
        }
    }
}
int FileCacheDataEx::readyData(const char * pPath)
{
    int fd;
    int ret = openFile( pPath, fd );
    if ( ret )
        return ret;
    if ( (size_t)m_lSize < s_iMaxInMemCacheSize )
    {
        ret = allocateCache( m_lSize );
        if ( ret == 0 )
        {
            ret = nio_read( fd, m_pCache, m_lSize );
            if ( ret == m_lSize )
            {
                close( fd );
                return 0;
            }
            else
            {
                release();
            }
        }
    }
    else if (( (size_t)m_lSize < s_iMaxMMapCacheSize )
            &&((size_t)m_lSize + s_iCurTotalMMAPCache < s_iMaxTotalMMAPCache ))
    {
        m_pCache = (char *)mmap( 0, m_lSize, PROT_READ,
                MAP_PRIVATE, fd, 0 );
        s_iCurTotalMMAPCache += m_lSize;
        if ( D_ENABLED( DL_MORE ))
            LOG_D(( "[MMAP] Map %p to file:%s", m_pCache, pPath ));
        if ( m_pCache == MAP_FAILED )
        {
            m_pCache = 0;
        }
        else
        {
            setStatus( MMAPED );
            close( fd );
            return 0;
        }
    }
    setfd( fd );
    fcntl( fd, F_SETFD, FD_CLOEXEC );
    return 0;
}
int HttpListener::checkAccess( struct conn_data * pData )
{
    struct sockaddr * pPeer = ( struct sockaddr *) pData->achPeerAddr;
    if (( AF_INET6 == pPeer->sa_family )&&
        ( IN6_IS_ADDR_V4MAPPED( &((struct sockaddr_in6 *)pPeer)->sin6_addr )) )
    {
        pPeer->sa_family = AF_INET;
        ((struct sockaddr_in *)pPeer)->sin_addr.s_addr = *((in_addr_t *)&pData->achPeerAddr[20]);
    }
    ClientInfo * pInfo = HttpGlobals::getClientCache()->getClientInfo( pPeer );
    pData->pInfo = pInfo;

    if ( D_ENABLED( DL_MORE ))
        LOG_D(( "[%s] New connection from %s:%d.", getAddrStr(),
                    pInfo->getAddrString(), ntohs( ((struct sockaddr_in*)pPeer)->sin_port) ));

    return pInfo->checkAccess();
}
Exemple #22
0
int JConn::doRead()
{
    int len = 0;
    int ret = 0;
    while( true )
    {
        int toRead = m_pRespBufEnd - m_pCurPos;
        len = read( (char *)m_pCurPos, toRead);
        if ( len > 0 )
        {
            if ( D_ENABLED( DL_MEDIUM ) )
                LOG_D(( getLogger(), "[%s] process STDOUT %d bytes",
                    getLogId(), len ));
            //printf( ">>read %d bytes from CGI\n", len );
            //::write( 1, m_pCurPos, len );
            m_pCurPos += len;
            ret = processRespData();
            if ( ret == -1 )
            {
                errno = EIO;
                len = -1;
                break;
            }
            if ( len < toRead )
            {
                if (( m_packetType != AJP13_END_RESP )&&
                    ( getConnector() ))
                    getConnector()->flushResp();
                break;
            }
        }
        else 
            break;
    }
    if ( getState() == ABORT )
    {
        if ( getConnector() )
        {
            incReqProcessed();
            getConnector()->endResponse( 0, 0 );
        }
    }    
    return len;
}
int LsapiConn::connect( Multiplexer * pMplx )
{
    LsapiWorker * pWorker = (LsapiWorker *)getWorker();
    if ( pWorker->selfManaged() )
        return ExtConn::connect( pMplx );
    int fds[2];
    errno = ECONNRESET;
    if ( socketpair( AF_UNIX, SOCK_STREAM, 0, fds ) == -1 )
    {
        LOG_ERR(( "[LsapiConn::connect()] socketpair() failed!" ));
        return -1;
    }
    fcntl( fds[0], F_SETFD, FD_CLOEXEC );
    setReqProcessed( 0 );
    setToStop( 0 );
    //if ( pApp->getCurInstances() >= pApp->getConfig().getInstances() )
    //    return -1;
    m_pid = LocalWorker::workerExec( pWorker->getConfig(), fds[1] );
    ::close( fds[1] );
    
    if ( m_pid == -1 )
    {
        ::close( fds[0] );
        return -1;
    }
    else
    {
        if ( D_ENABLED( DL_LESS ) )
            LOG_D(( "[%s] add child process pid: %d", pWorker->getName(), m_pid ));
        PidRegistry::add( m_pid, pWorker, 0 );
    }

    ::fcntl( fds[0], F_SETFL, HttpGlobals::getMultiplexer()->getFLTag() );
    init( fds[0], pMplx );

    //Increase the number of successful request to avoid max connections reduction.
    incReqProcessed();

    setState( PROCESSING );
    onWrite();

    return 1;
}
int LocalWorker::stop()
{
    pid_t pid;
    PidList::iterator iter;
    removeUnixSocket();
    LOG_NOTICE(( "[%s] stop worker processes", getName() ));
    for( iter = getPidList()->begin(); iter != getPidList()->end();  )
    {
        pid = (pid_t)(long)iter->first();
        iter = getPidList()->next( iter );
        killProcess( pid );
        if ( D_ENABLED( DL_LESS ) )
            LOG_D(( "[%s] kill pid: %d", getName(), pid ));
    }
    moveToStopList();
    setState( ST_NOTSTARTED );

    return 0;
}
int CgidConn::doWrite()
{
    if ( !getConnector() )
        return -1;
    if ( D_ENABLED( DL_MEDIUM ) )
        LOG_D(( getLogger(), "[%s] CgidConn::onWrite()\n", getLogId() ));
    int ret = getConnector()->extOutputReady();
    if (!( getConnector()->getState() & HEC_FWD_REQ_BODY ))
    {
        if ( m_iTotalPending > 0 )
            return flush();
        else
        {
            suspendWrite();
            ::shutdown( getfd(), SHUT_WR );
        }
    }
    return ret;
}
int LsapiConn::doRead()
{
    if ( D_ENABLED( DL_LESS ) )
        LOG_D(( getLogger(), "[%s] LsapiConn::doRead()\n", getLogId() ));
    int ret;
    ret = processResp();
//    if ( m_respState )
//        ret = processResp();
//    else
//        ret = processRespBuffed();
    if ( getState() == ABORT )
    {
        if ( getConnector() )
        {
            incReqProcessed();
            getConnector()->endResponse( 0, 0 );
        }
    }
    return ret;
}
Exemple #27
0
int JConn::addRequest( ExtRequest * pReq )
{
    assert( pReq );
    setConnector( (HttpExtConnector *)pReq );
    reset();
    m_pCurPos = m_respBuf;
    m_iPacketState = PACKET_HEADER;
    int ret = buildReqHeader();
    if ( ret )
    {
        if ( D_ENABLED( DL_LESS ) )
            LOG_D(( getLogger(),
                "[%s] Request header can't fit into 8K buffer, "
                "can't forward request to servlet engine",
                getLogId() ));
        ((HttpExtConnector *)pReq)->setProcessor( NULL );
        setConnector( NULL );
        ret = SC_500;
    }
    return ret;
    //return 0;
}
int LsapiConn::readStderrStream()
{
    register HttpExtConnector * pHEC = getConnector();
    int     ret;
    size_t  bufLen;
    char    achBuf[2049];
    
    while( m_iPacketLeft > 0 )
    {
        char * pBuf = achBuf;
        bufLen = sizeof( achBuf );
        int toRead = m_iPacketLeft + sizeof( m_respHeader );
        if ( toRead > (int)bufLen )
            toRead = bufLen ;
        ret = read( pBuf, toRead );
        if ( ret > 0 )
        {
            int len, packetLen;
            if ( D_ENABLED( DL_MEDIUM ) )
                LOG_D(( getLogger(), "[%s] process STDERR stream %d bytes, packet left: %d",
                    getLogId(), ret, m_iPacketLeft ));
            if ( ret >= m_iPacketLeft )
            {
                packetLen       = m_iPacketLeft;
                m_iPacketLeft   = 0;
            }
            else
            {
                packetLen       = ret;
                m_iPacketLeft  -= ret;
            }
            if ( pHEC )
                pHEC->processErrData( pBuf, packetLen );
            else
            {
                char ch = pBuf[packetLen];
                pBuf[ packetLen ] = 0;
                LOG_NOTICE(( getLogger(), "[%s] [LSAPI:STDERR]: %s", getLogId(), pBuf ));
                pBuf[ packetLen ] = ch;
            }

            if ( m_iPacketLeft <= 0 )
            {
                m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN;
                if ( ret > packetLen )
                {
                    if ( D_ENABLED( DL_MEDIUM ) )
                        LOG_D(( getLogger(), "[%s] process packet header %d bytes",
                            getLogId(), ret - packetLen ));
                    len = processPacketHeader( pBuf + packetLen, ret - packetLen );
                    if ( len <= 0 )
                        return len;
                    if (( m_respHeader.m_type != LSAPI_STDERR_STREAM )||
                        ( m_iPacketLeft <= 0 ))
                        return 1;
                }
                else
                    break;
            }
        }
        else
        {
            return ret;
        }
    }
    return 1;
}
int LsapiConn::readRespBody()
{
    register HttpExtConnector * pHEC = getConnector();
    int ret;
    size_t bufLen;
    if ( !pHEC )
        return -1;
    int &respState = pHEC->getRespState();
    while( m_iPacketLeft > 0 )
    {
        char * pBuf = pHEC->getRespBuf( bufLen );
        if ( !pBuf )
        {
            return -1;
        }
        int toRead = m_iPacketLeft + sizeof( m_respHeader );
        if ( toRead > (int)bufLen )
            toRead = bufLen ;
        ret = read( pBuf, toRead );
        if ( ret > 0 )
        {
            int len, packetLen;
            if ( D_ENABLED( DL_MEDIUM ) )
                LOG_D(( getLogger(), "[%s] process response stream %d bytes, packet left: %d",
                    getLogId(), ret, m_iPacketLeft ));
            if ( ret >= m_iPacketLeft )
            {
                packetLen       = m_iPacketLeft;
                m_iPacketLeft   = 0;
            }    
            else
            {
                packetLen       = ret;
                m_iPacketLeft  -= ret;
            }    
            if ( !(respState & 0xff) )
            {
                len = pHEC->processRespData( pBuf, packetLen );
                if ( respState & 0xff )
                    m_respState = LSAPI_CONN_READ_RESP_BODY;
                if ( len == -1 )
                    return len;
            }
            else
            {
                len = pHEC->respBodyRecv( pBuf, packetLen );
            }
            if ( m_iPacketLeft <= 0 )
            {
                m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN;
                if ( ret > packetLen )
                {
                    if ( D_ENABLED( DL_MEDIUM ) )
                        LOG_D(( getLogger(), "[%s] process packet header %d bytes",
                            getLogId(), ret - packetLen ));
                    int len1 = processPacketHeader( pBuf + packetLen, ret - packetLen );
                    if ( len1 <= 0 )
                        return len1;
                    if (( m_respHeader.m_type != LSAPI_RESP_STREAM )||
                        ( m_iPacketLeft <= 0 ))
                        return 1;
                }
                else
                    break;
            }
            if ( len == 1)
                return 0;
            if ( len )
                return len;
            if ( ret < (int)toRead)
            {
                pHEC->flushResp();
                return 0;
            }
        }
        else
        {
            return ret;
        }
    }  
    return 1;
}
int LsapiConn::processRespHeader()
{
    register HttpExtConnector * pHEC = getConnector();
    int ret;
    int len = 0;
    if ( !pHEC )
        return -1;
    int &respState = pHEC->getRespState();
    if ( !(respState & 0xff) )
    {        
        while( m_iPacketLeft > 0 )
        {
            len = ExtConn::read( m_pRespHeader, m_pRespHeaderBufEnd - m_pRespHeader );
            if ( D_ENABLED( DL_MEDIUM ) )
                LOG_D(( getLogger(), "[%s] process response header %d bytes",
                    getLogId(), len ));
            if ( len > 0 )
            {
                m_iPacketLeft -= len;
                ret = processRespHeader( m_pRespHeader + len, respState ); 
                switch( ret )
                {
                case -2:
                    LOG_WARN(( getLogger(), "[%s] Invalid Http response header, retry!",
                            getLogId() ));
                    //debug code
                    //::write( 1, pBuf, len );
                    errno = ECONNRESET;
                case -1:
                    return -1;
                }
                
                if ( m_iPacketLeft > 0 )
                {
                    m_pRespHeader += len;
                    if (( m_pRespHeader > m_pRespHeaderProcess )&&
                        ( m_pRespHeader != &m_respBuf[ m_respInfo.m_cntHeaders * sizeof(short) ] ))
                    {
                        len = m_pRespHeader - m_pRespHeaderProcess;
                        memmove( &m_respBuf[ m_respInfo.m_cntHeaders * sizeof(short) ],
                                m_pRespHeaderProcess, m_pRespHeader - m_pRespHeaderProcess );
                        m_pRespHeaderProcess = &m_respBuf[ m_respInfo.m_cntHeaders * sizeof(short) ];
                        m_pRespHeader = m_pRespHeaderProcess + len;
                    }    
                    else
                        m_pRespHeader = m_pRespHeaderProcess = 
                                    &m_respBuf[ m_respInfo.m_cntHeaders * sizeof(short) ];
                    setRespBuf( m_pRespHeader );
                }
                
            }
            else
                return len;
        }
        if ( m_iPacketLeft == 0 )
        {
            m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN;
            len = 1;
        }
        return len;        
    }
    else
    {
        //error: protocol error, header received already.
		errno = EIO;
        return -1;
    }    
}