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 JConn::sendReqHeader() { m_iovec.clear(); m_iovec.append( m_buf, m_pBufEnd - m_buf ); m_iTotalPending = m_pBufEnd - m_buf; setInProcess( 1 ); return 1; }
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::sendReqHeader() { int ret = m_lsreq.buildReq( getConnector()->getHttpConn(), &m_iTotalPending ); if ( ret ) { LOG_INFO(( getLogger(), "[%s] Failed to build LSAPI request header, " "can't forward request to external LSAPI application ", getLogId() )); // ((HttpExtConnector *)pReq)->setProcessor( NULL ); // setConnector( NULL ); return -1; } setInProcess( 1 ); m_lReqSentTime = DateTime::s_curTime; return 1; }
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; }
int ProxyConn::sendReqHeader() { m_iovec.clear(); HttpSession *pSession = getConnector()->getHttpSession(); HttpReq *pReq = pSession->getReq(); //remove the trailing "\r\n" before adding our headers const char *pBegin = pReq->getOrgReqLine(); m_iTotalPending = pReq->getHttpHeaderLen(); int newReqLineLen = 0; int headerLen = 17; char *pExtraHeader = &m_extraHeader[23]; const char *pForward = pReq->getHeader(HttpHeader::H_X_FORWARDED_FOR); int len; if (*pForward != '\0') { len = pReq->getHeaderLen(HttpHeader::H_X_FORWARDED_FOR); if (len > 160) len = 160; memmove(&pExtraHeader[headerLen], pForward, len); headerLen += len; pExtraHeader[headerLen++] = ','; } //add "X-Forwarded-For" header memmove(&pExtraHeader[headerLen], pSession->getPeerAddrString(), pSession->getPeerAddrStrLen()); headerLen += pSession->getPeerAddrStrLen(); pExtraHeader[headerLen++] = '\r'; pExtraHeader[headerLen++] = '\n'; #if 1 //always set "Accept-Encoding" header to "gzip" char *pAE = (char *)pReq->getHeader(HttpHeader::H_ACC_ENCODING); if (*pAE) { int len = pReq->getHeaderLen(HttpHeader::H_ACC_ENCODING); if (len >= 4) { memmove(pAE, "gzip", 4); memset(pAE + 4, ' ', len - 4); } } else { pExtraHeader = m_extraHeader; headerLen += 23; } #endif if (*(pBegin + --m_iTotalPending - 1) == '\r') --m_iTotalPending; if (*pForward) { if ((pBegin + m_iTotalPending) - (pForward + pReq->getHeaderLen(HttpHeader::H_X_FORWARDED_FOR)) == 2) { const char *p = pForward -= 16; while (*(p - 1) != '\n') --p; m_iTotalPending = p - pBegin; } } //reconstruct request line if URL has been rewritten if (pReq->getRedirects() > 0) { const char *pReqLine = pReq->encodeReqLine(newReqLineLen); if (newReqLineLen > 0) { m_iovec.append(pReqLine, newReqLineLen); pBegin += pReq->getOrgReqLineLen() - 9; m_iTotalPending -= pReq->getOrgReqLineLen() - 9; } } int newHostLen = pReq->getNewHostLen(); char *pHost = (char *)pReq->getHeader(HttpHeader::H_HOST); int hostLen = pReq->getHeaderLen(HttpHeader::H_HOST); if (newHostLen > 0) { if (*pHost) { m_iovec.append(pBegin, pHost - pBegin); m_iovec.append(pReq->getNewHost(), newHostLen); m_iovec.append(pHost + hostLen, pBegin + m_iTotalPending - pHost - hostLen); m_iTotalPending += (newHostLen - hostLen); } else { m_iovec.append(pBegin, m_iTotalPending); m_iovec.append("Host: ", 6); m_iovec.append(pReq->getNewHost(), newHostLen); m_iovec.append("\r\n", 2); m_iTotalPending += newHostLen + 8; } } else m_iovec.append(pBegin, m_iTotalPending); m_iTotalPending += newReqLineLen; if (hostLen) { m_iovec.append(s_achForwardHost, sizeof(s_achForwardHost) - 1); m_iovec.append(pHost, hostLen); m_iovec.append("\r\n", 2); m_iTotalPending += hostLen + sizeof(s_achForwardHost) + 1 ; } if (pSession->isSSL()) { m_iovec.append(s_achForwardHttps, sizeof(s_achForwardHttps) - 1); m_iTotalPending += sizeof(s_achForwardHttps) - 1; } //if ( headerLen > 0 ) { pExtraHeader[headerLen++] = '\r'; pExtraHeader[headerLen++] = '\n'; m_iovec.append(pExtraHeader, headerLen); m_iTotalPending += headerLen; } m_iReqHeaderSize = m_iTotalPending; m_iReqBodySize = pReq->getContentFinished(); setInProcess(1); return 1; }