int LsapiConn::processPacketHeader( char * pBuf, int len ) { if ( m_iPacketHeaderLeft < len ) { len = m_iPacketHeaderLeft; } memmove( ((char *)&m_respHeader) + sizeof( m_respHeader ) - m_iPacketHeaderLeft, pBuf, len ); m_iPacketHeaderLeft -= len; if ( m_iPacketHeaderLeft == 0 ) { m_iPacketLeft = verifyPacketHeader( &m_respHeader ) - LSAPI_PACKET_HEADER_LEN; if ( m_iPacketLeft < 0 ) { LOG_WARN(( "[%s] LSAPI Packet header is invalid!", getLogId() )); errno = EIO; return -1; } // if ( m_iPacketLeft > LSAPI_MAX_HEADER_LEN ) // { // LOG_WARN(( "[%s] LSAPI Packet is too large: %d", // getLogId(), m_iPacketLeft )); // errno = EIO; // return -1; // } switch( m_respHeader.m_type ) { case LSAPI_RESP_END: incReqProcessed(); setInProcess( 0 ); if ( getConnector() ) getConnector()->endResponse( 0, 0 ); return 0; case LSAPI_RESP_HEADER: if ( m_respState == LSAPI_CONN_READ_RESP_BODY ) { LOG_WARN(( "[%s] Invalid LSAPI Response Header Packet following STREAM packet", getLogId() )); errno = EIO; return -1; } else { m_iCurRespHeader = 0; m_respState = LSAPI_CONN_READ_RESP_INFO; m_pRespHeaderProcess = (char *)&m_respInfo; setRespBuf( m_pRespHeaderProcess ); } break; case LSAPI_REQ_RECEIVED: m_reqReceived = 1; break; } } return len; }
int LsapiConn::doWrite() { if ( getConnector() ) { int state = getConnector()->getState(); if ((!state)||( state & (HEC_FWD_REQ_HEADER | HEC_FWD_REQ_BODY) )) { int ret = getConnector()->extOutputReady(); if ( getState() == ABORT ) { if ( getConnector() ) { incReqProcessed(); getConnector()->endResponse( 0, 0 ); } } return ret; } } if ( m_iTotalPending > 0 ) return flush(); else suspendWrite(); return 0; }
int ProxyConn::doWrite() { int ret; if ((m_iSsl) && (!m_ssl.isConnected())) { ret = connectSSL(); if (ret != 1) return ret; } if (getConnector()) { int state = getConnector()->getState(); if ((!state) || (state & (HEC_FWD_REQ_HEADER | HEC_FWD_REQ_BODY))) { int ret = getConnector()->extOutputReady(); if (getState() == ABORT) { if (getConnector()) { incReqProcessed(); getConnector()->endResponse(0, 0); } } return ret; } } if (m_iTotalPending > 0) return flush(); else suspendWrite(); return 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; }
void ProxyConn::init(int fd, Multiplexer *pMplx) { EdStream::init(fd, pMplx, POLLIN | POLLOUT | POLLHUP | POLLERR); reset(); m_iSsl = ((ProxyWorker *)getWorker())->getConfig().getSsl(); if ((m_iSsl) && (m_ssl.getSSL())) m_ssl.release(); m_lReqBeginTime = time(NULL); //Increase the number of successful request to avoid max connections reduction. incReqProcessed(); }
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 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; }
int ProxyConn::doRead() { int ret; LS_DBG_L(this, "ProxyConn::doRead()"); if ((m_iSsl) && (!m_ssl.isConnected())) { ret = connectSSL(); if (ret != 1) return ret; return doWrite(); } ret = processResp(); if (getState() == ABORT) { if (getConnector()) { incReqProcessed(); getConnector()->endResponse(0, 0); } } return ret; }
int LsapiConn::processResp() { int ret; while( getState() == PROCESSING ) { if ( m_iPacketHeaderLeft > 0 ) { ret = read( ((char *)&m_respHeader) + sizeof( m_respHeader ) - m_iPacketHeaderLeft, m_iPacketHeaderLeft ); if ( D_ENABLED( DL_MEDIUM ) ) LOG_D(( getLogger(), "[%s] process packet header %d bytes", getLogId(), ret )); if ( ret > 0 ) { m_iPacketHeaderLeft -= ret; if ( m_iPacketHeaderLeft == 0 ) { m_iPacketLeft = verifyPacketHeader( &m_respHeader ) - LSAPI_PACKET_HEADER_LEN; if ( m_iPacketLeft < 0 ) { const char * p = (const char *)&m_respHeader; LOG_WARN(( "[%s] LSAPI Packet header is invalid," "('%c','%c','%c','%c','%c','%c','%c','%c')", getLogId(), *p, *(p+1), *(p+2), *(p+3), *(p+4), *(p+5), *(p+6), *(p+7) )); break; } // if ( m_iPacketLeft > LSAPI_MAX_HEADER_LEN ) // { // LOG_WARN(( "[%s] LSAPI Packet is too large: %d", // getLogId(), m_iPacketLeft )); // break; // } switch( m_respHeader.m_type ) { case LSAPI_RESP_END: m_respState = 0; incReqProcessed(); setInProcess( 0 ); getConnector()->endResponse( 0, 0 ); return 0; case LSAPI_RESP_HEADER: m_iCurRespHeader = 0; m_respState = LSAPI_CONN_READ_RESP_INFO; m_pRespHeaderProcess = (char *)&m_respInfo; setRespBuf( m_pRespHeaderProcess ); break; case LSAPI_REQ_RECEIVED: m_reqReceived = 1; break; } } } else { if (( m_respState == LSAPI_CONN_READ_RESP_BODY )&& ( getConnector())) getConnector()->flushResp(); return ret; } } if ( m_iPacketLeft > 0 ) { switch( m_respHeader.m_type ) { case LSAPI_RESP_HEADER: ret = processRespHeader(); if ( ret <= 0 ) return ret; break; case LSAPI_RESP_STREAM: ret = readRespBody(); if ( ret <= 0 ) { if (( m_respState == LSAPI_CONN_READ_RESP_BODY )&& ( getConnector())) getConnector()->flushResp(); return ret; } break; case LSAPI_STDERR_STREAM: ret = readStderrStream(); if ( ret <= 0 ) return ret; break; default: //error: protocol error LOG_NOTICE(( getLogger(), "[%s] Unknown Packet Type %c, LSAPI protcol is broken.", getLogId(), m_respHeader.m_type )); errno = EIO; return -1; } } else { m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN; } } errno = EIO; return -1; }
int LsapiConn::processRespBuffed() { int ret; int left; int len; m_pRespHeader = (char *)&m_respHeader; m_pRespHeaderBufEnd = &m_respBuf[1024]; ret = read( m_pRespHeader, m_pRespHeaderBufEnd - m_pRespHeader ); if ( ret <= 0 ) return ret; if ( ret < (int)sizeof( lsapi_packet_header ) ) { m_iPacketHeaderLeft = sizeof( lsapi_packet_header ) - ret; return ret; } m_pRespHeaderBufEnd = m_pRespHeader + ret; m_iPacketLeft = verifyPacketHeader( &m_respHeader ) - LSAPI_PACKET_HEADER_LEN; if ( m_iPacketLeft < 0 ) { errno = EIO; return -1; } if ( !m_iPacketLeft ) m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN; else m_iPacketHeaderLeft = 0; if ( ret < (int)(sizeof( lsapi_packet_header ) + sizeof( lsapi_resp_info )) ) { m_pRespHeader += ret; switch( m_respHeader.m_type ) { case LSAPI_RESP_END: m_respState = LSAPI_CONN_IDLE; incReqProcessed(); setInProcess( 0 ); getConnector()->endResponse( 0, 0 ); return 0; case LSAPI_RESP_HEADER: m_iCurRespHeader = 0; m_respState = LSAPI_CONN_READ_RESP_INFO; m_pRespHeaderProcess = (char *)&m_respInfo; setRespBuf( m_pRespHeaderProcess ); return ret; case LSAPI_REQ_RECEIVED: m_reqReceived = 1; break; } m_pRespHeaderProcess = (char *)&m_respInfo; } else { m_iCurRespHeader = 0; m_respState = LSAPI_CONN_READ_HEADER_LEN; m_pRespHeaderProcess = m_respBuf; } while( (left = m_pRespHeaderBufEnd - m_pRespHeaderProcess) > 0 ) { if ( m_iPacketHeaderLeft > 0 ) { ret = processPacketHeader( m_pRespHeaderProcess, left ); if ( ret <= 0 ) return ret; m_pRespHeaderProcess += ret; left -= ret; } if ( m_iPacketLeft > 0 ) { register HttpExtConnector * pHEC = getConnector(); if ( !pHEC ) return -1; int &respState = pHEC->getRespState(); if ( m_iPacketLeft < left ) { len = m_iPacketLeft; m_iPacketLeft = 0; m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN; } else { len = left; m_iPacketLeft -= left; left = 0; } switch( m_respHeader.m_type ) { case LSAPI_RESP_HEADER: ret = processRespHeader(m_pRespHeaderBufEnd, respState); if ( ret < 0 ) return ret; break; case LSAPI_RESP_STREAM: if ( D_ENABLED( DL_MEDIUM ) ) LOG_D(( getLogger(), "[%s] process response stream %d bytes", getLogId(), len )); ret = pHEC->processRespData( m_pRespHeaderProcess, len ); if ( respState & 0xff ) m_respState = LSAPI_CONN_READ_RESP_BODY; if ( ret == -1 ) return ret; m_pRespHeaderProcess += len; break; case LSAPI_STDERR_STREAM: if ( D_ENABLED( DL_MEDIUM ) ) LOG_D(( getLogger(), "[%s] process STDERR stream %d bytes", getLogId(), len )); ret = pHEC->processErrData( m_pRespHeaderProcess, len ); m_pRespHeaderProcess += len; break; default: LOG_NOTICE(( getLogger(), "[%s] Unknown Packet Type %c, LSAPI protcol is broken.", getLogId(), m_respHeader.m_type )); errno = EIO; return -1; } } else m_iPacketHeaderLeft = LSAPI_PACKET_HEADER_LEN; } return 1; }
int ProxyConn::readRespBody() { HttpExtConnector *pHEC = getConnector(); int ret = 0; size_t bufLen; if (!pHEC) return LS_FAIL; if (m_pChunkIS) { while (getState() != ABORT && !m_pChunkIS->eos()) { char *pBuf = pHEC->getRespBuf(bufLen); if (!pBuf) return LS_FAIL; ret = m_pChunkIS->read(pBuf, bufLen); if (ret >= 0) { if (ret > 0) { m_lLastRespRecvTime = time(NULL); m_iRespBodyRecv += ret; int ret1 = pHEC->processRespBodyData(pBuf, ret); if (ret1 == -1) ret = LS_FAIL; if (ret > 1024 || (ret < (int)bufLen)) pHEC->flushResp(); } if (m_pChunkIS->eos()) { ret = 0; break; } pHEC->flushResp(); return ret; } else { if ((errno == ECONNRESET) && (getConnector())) break; return LS_FAIL; } } } else { while ((getState() != ABORT) && (m_iRespBodySize - m_iRespBodyRecv > 0)) { char *pBuf = pHEC->getRespBuf(bufLen); if (!pBuf) return LS_FAIL; int64_t toRead = m_iRespBodySize - m_iRespBodyRecv; if (toRead > (int64_t)bufLen) toRead = bufLen ; ret = read(pBuf, toRead); if (ret > 0) { m_iRespBodyRecv += ret; pHEC->processRespBodyData(pBuf, ret); if (ret > 1024) pHEC->flushResp(); //if ( ret1 ) // return ret1; if (m_iRespBodySize - m_iRespBodyRecv <= 0) break; if (ret < (int)toRead) { pHEC->flushResp(); return 0; } } else { if (ret) { if ((errno == ECONNRESET) && (getConnector())) break; } return ret; } } } incReqProcessed(); if (pHEC->getRespState() & HEC_RESP_CONN_CLOSE) setState(CLOSING); setInProcess(0); pHEC->endResponse(0, 0); return ret; }
int ProxyConn::processResp() { HttpExtConnector *pHEC = getConnector(); if (!pHEC) { errno = ECONNRESET; return LS_FAIL; } int len = 0; int ret = 0; int &respState = pHEC->getRespState(); if (!(respState & 0xff)) { char *p = HttpResourceManager::getGlobalBuf(); const char *pBuf = p; if (m_iSsl) len = m_ssl.read(p, 1460); else len = ExtConn::read(p, 1460); if (len > 0) { int copy = len; if (m_iRespHeaderRecv + copy > 4095) copy = 4095 - m_iRespHeaderRecv; //memmove( &m_achRespBuf[ m_iRespHeaderRecv ], pBuf, copy ); m_iRespHeaderRecv += copy; m_iRespRecv += len; LS_DBG_L(this, "Read Response %d bytes", len); //debug code //::write( 1, pBuf, len ); ret = pHEC->parseHeader(pBuf, len, 1); switch (ret) { case -2: LS_WARN(this, "Invalid Http response header, retry!"); //debug code //::write( 1, pBuf, len ); errno = ECONNRESET; case -1: return LS_FAIL; } } else return len; if (respState & 0xff) { //debug code //::write(1, HttpResourceManager::getGlobalBuf(), // pBuf - HttpResourceManager::getGlobalBuf() ); HttpReq *pReq = pHEC->getHttpSession()->getReq(); if (pReq->noRespBody()) { incReqProcessed(); if (len > 0) abort(); else if (respState & HEC_RESP_CONN_CLOSE) setState(CLOSING); else if (getState() == ABORT) setState(PROCESSING); setInProcess(0); pHEC->endResponse(0, 0); return 0; } m_iRespBodySize = pHEC->getHttpSession()->getResp()->getContentLen(); LS_DBG_L(this, "Response body size of proxy reply is %d", m_iRespBodySize); if (m_iRespBodySize == LSI_RSP_BODY_SIZE_CHUNKED) setupChunkIS(); else if (!(respState & HEC_RESP_CONT_LEN)) m_iRespBodySize = INT_MAX; m_pBufBegin = pBuf; m_pBufEnd = pBuf + len; LS_DBG_M(this, "Process Response body %d bytes", len); return readRespBody(); } } else return readRespBody(); return 0; }