diff --git a/configure b/configure index 6a8cdaf13..1dbc80f35 100755 --- a/configure +++ b/configure @@ -1458,10 +1458,8 @@ Optional Features: --enable-adminssl=[yes/no] Enable HTTPS for admin console (modify adminssl.conf before installation) [default=yes] - --enable-spdy Enable SPDY and http2 over HTTPS (Spdy and http2 are - disabled by default) - --enable-http2 Enable SPDY and http2 over HTTPS (Spdy and http2 are - disabled by default) + --enable-spdy=[yes/no] Enable SPDY and http2 over HTTPS [default=yes] + --enable-http2=[yes/no] Enable SPDY and http2 over HTTPS [default=yes] --enable-redis Enable redis for cache module (Using redis is disabled by default) --enable-debug Enable debugging symbols (Debug is disabled by @@ -15667,21 +15665,25 @@ fi +OPENLSWS_HTTP2="?" # Check whether --enable-spdy was given. if test "${enable_spdy+set}" = set; then : - enableval=$enable_spdy; -$as_echo "#define LS_ENABLE_SPDY 1" >>confdefs.h - - echo "SPDY/http2 enabled!!!" + enableval=$enable_spdy; OPENLSWS_HTTP2="$enableval" fi # Check whether --enable-http2 was given. if test "${enable_http2+set}" = set; then : - enableval=$enable_http2; + enableval=$enable_http2; OPENLSWS_HTTP2="$enableval" +fi + +if test "$OPENLSWS_HTTP2" = "no" ; then + echo "SPDY/http2 disabled!!!" +else + $as_echo "#define LS_ENABLE_SPDY 1" >>confdefs.h - echo "SPDY/http2 enabled!!!" + echo "SPDY/http2 enabled!!!" fi diff --git a/configure.ac b/configure.ac index bde1574d7..e7454b3af 100644 --- a/configure.ac +++ b/configure.ac @@ -80,17 +80,23 @@ AC_ARG_ENABLE([adminssl], [OPENLSWS_ADMINSSL="$enableval"], [OPENLSWS_ADMINSSL=yes]) AC_SUBST([OPENLSWS_ADMINSSL]) +OPENLSWS_HTTP2="?" AC_ARG_ENABLE([spdy], - [AC_HELP_STRING([--enable-spdy], - [Enable SPDY and http2 over HTTPS (Spdy and http2 are disabled by default)])], - [ AC_DEFINE([LS_ENABLE_SPDY], [1], [Define if need spdy/http2 feature]) - echo "SPDY/http2 enabled!!!" ], []) - + [AC_HELP_STRING([--enable-spdy=@<:@yes/no@:>@], + [Enable SPDY and http2 over HTTPS @<:@default=yes@:>@])], + [OPENLSWS_HTTP2="$enableval"], []) + AC_ARG_ENABLE([http2], - [AC_HELP_STRING([--enable-http2], - [Enable SPDY and http2 over HTTPS (Spdy and http2 are disabled by default)])], - [ AC_DEFINE([LS_ENABLE_SPDY], [1], [Define if need spdy/http2 feature]) - echo "SPDY/http2 enabled!!!" ], []) + [AC_HELP_STRING([--enable-http2=@<:@yes/no@:>@], + [Enable SPDY and http2 over HTTPS @<:@default=yes@:>@])], + [OPENLSWS_HTTP2="$enableval"], []) +if test "$OPENLSWS_HTTP2" = "no" ; then + echo "SPDY/http2 disabled!!!" +else + AC_DEFINE([LS_ENABLE_SPDY], [1], [Define if need spdy/http2 feature]) + echo "SPDY/http2 enabled!!!" +fi + AC_ARG_ENABLE([cacheredis], [AC_HELP_STRING([--enable-redis], diff --git a/src/extensions/cgi/cgidworker.cpp b/src/extensions/cgi/cgidworker.cpp index d77547c71..1df54f760 100644 --- a/src/extensions/cgi/cgidworker.cpp +++ b/src/extensions/cgi/cgidworker.cpp @@ -46,7 +46,8 @@ int CgidWorker::s_iCgidWorkerPid = -1; CgidWorker::CgidWorker(const char *pName) - : m_pid(-1) + : ExtWorker(HandlerType::HT_CGI) + , m_pid(-1) , m_fdCgid(-1) , m_lve(1) { diff --git a/src/extensions/extworker.cpp b/src/extensions/extworker.cpp index 52ac1b6d6..01c8d5f91 100644 --- a/src/extensions/extworker.cpp +++ b/src/extensions/extworker.cpp @@ -34,8 +34,9 @@ #include -ExtWorker::ExtWorker() - : m_pConfig(NULL) +ExtWorker::ExtWorker(int type) + : HttpHandler(type) + , m_pConfig(NULL) , m_iRole(EXTAPP_RESPONDER) , m_iMultiplexConns(0) , m_iWantManagementInfo(1) diff --git a/src/extensions/extworker.h b/src/extensions/extworker.h index 421f6b653..f4d5debc6 100644 --- a/src/extensions/extworker.h +++ b/src/extensions/extworker.h @@ -74,7 +74,7 @@ class ExtWorker : public HttpHandler ST_GOOD }; - ExtWorker(); + explicit ExtWorker(int type); virtual ~ExtWorker(); ConnPool &getConnPool() { return m_connPool; } diff --git a/src/extensions/fcgi/fcgiapp.cpp b/src/extensions/fcgi/fcgiapp.cpp index cfe80b460..084001356 100644 --- a/src/extensions/fcgi/fcgiapp.cpp +++ b/src/extensions/fcgi/fcgiapp.cpp @@ -18,6 +18,7 @@ #include "fcgiapp.h" #include "fcgiappconfig.h" #include "fcgiconnection.h" +#include #include #include @@ -27,7 +28,8 @@ FcgiApp::FcgiApp(const char *pName) - : m_iMaxConns(10) + : LocalWorker(HandlerType::HT_FASTCGI) + , m_iMaxConns(10) , m_iMaxReqs(10) { setConfigPointer(new FcgiAppConfig(pName)); diff --git a/src/extensions/jk/jworker.cpp b/src/extensions/jk/jworker.cpp index 806e48a47..9ffa71292 100644 --- a/src/extensions/jk/jworker.cpp +++ b/src/extensions/jk/jworker.cpp @@ -18,8 +18,10 @@ #include "jworker.h" #include "jworkerconfig.h" #include "jconn.h" +#include JWorker::JWorker(const char *pName) + : ExtWorker(HandlerType::HT_SERVLET) { setConfigPointer(new JWorkerConfig(pName)); } diff --git a/src/extensions/loadbalancer.cpp b/src/extensions/loadbalancer.cpp index a2458b8ea..d12b29bd2 100644 --- a/src/extensions/loadbalancer.cpp +++ b/src/extensions/loadbalancer.cpp @@ -17,15 +17,12 @@ *****************************************************************************/ #include "loadbalancer.h" #include - -LoadBalancer::LoadBalancer() - : m_lastWorker(0) -{ -} +#include LoadBalancer::LoadBalancer(const char *pName) - : m_lastWorker(0) + : ExtWorker(HandlerType::HT_LOADBALANCER) + , m_lastWorker(0) { setConfigPointer(new ExtWorkerConfig(pName)); } diff --git a/src/extensions/loadbalancer.h b/src/extensions/loadbalancer.h index 8d1ee2a8f..13a3ddb5f 100644 --- a/src/extensions/loadbalancer.h +++ b/src/extensions/loadbalancer.h @@ -34,8 +34,7 @@ class LoadBalancer: public ExtWorker int workerLoadCompare(ExtWorker *pWorker, ExtWorker *pSelect); public: - LoadBalancer(const char *pName); - LoadBalancer(); + explicit LoadBalancer(const char *pName); ~LoadBalancer(); ExtWorker *selectWorker(HttpSession *pSession, ExtRequest *pExtReq); diff --git a/src/extensions/localworker.cpp b/src/extensions/localworker.cpp index 64a048c15..9fb52234e 100644 --- a/src/extensions/localworker.cpp +++ b/src/extensions/localworker.cpp @@ -42,8 +42,9 @@ #define GRACE_TIMEOUT 20 #define KILL_TIMEOUT 25 -LocalWorker::LocalWorker() - : m_fdApp(-1) +LocalWorker::LocalWorker(int type) + : ExtWorker(type) + , m_fdApp(-1) , m_sigGraceStop(SIGTERM) , m_pidList(NULL) , m_pidListStop(NULL) diff --git a/src/extensions/localworker.h b/src/extensions/localworker.h index ac76b9454..e4b83c593 100644 --- a/src/extensions/localworker.h +++ b/src/extensions/localworker.h @@ -33,7 +33,7 @@ class LocalWorker : public ExtWorker void moveToStopList(); public: - LocalWorker(); + explicit LocalWorker(int type); ~LocalWorker(); diff --git a/src/extensions/lsapi/lsapiworker.cpp b/src/extensions/lsapi/lsapiworker.cpp index 55095fbcd..69365f55d 100644 --- a/src/extensions/lsapi/lsapiworker.cpp +++ b/src/extensions/lsapi/lsapiworker.cpp @@ -18,9 +18,11 @@ #include "lsapiworker.h" #include "lsapiconfig.h" #include "lsapiconn.h" +#include LsapiWorker::LsapiWorker(const char *pName) + : LocalWorker(HandlerType::HT_LSAPI) { setConfigPointer(new LsapiConfig(pName)); } diff --git a/src/extensions/proxy/proxyworker.cpp b/src/extensions/proxy/proxyworker.cpp index 2e9299385..05efcb1be 100644 --- a/src/extensions/proxy/proxyworker.cpp +++ b/src/extensions/proxy/proxyworker.cpp @@ -18,7 +18,9 @@ #include "proxyworker.h" #include "proxyconfig.h" #include "proxyconn.h" +#include ProxyWorker::ProxyWorker(const char *pName) + : ExtWorker(HandlerType::HT_PROXY) { setConfigPointer(new ProxyConfig(pName)); } diff --git a/src/extensions/registry/extappregistry.cpp b/src/extensions/registry/extappregistry.cpp index 08fe4d939..f7e40e315 100644 --- a/src/extensions/registry/extappregistry.cpp +++ b/src/extensions/registry/extappregistry.cpp @@ -246,8 +246,6 @@ static ExtWorker *newWorker(int type, const char *pName) default: return NULL; } - if (pWorker) - pWorker->setHandlerType(type + HandlerType::HT_CGI); return pWorker; } diff --git a/src/http/awstats.cpp b/src/http/awstats.cpp index 277eef21c..e23edcdbd 100644 --- a/src/http/awstats.cpp +++ b/src/http/awstats.cpp @@ -570,7 +570,7 @@ void Awstats::config(HttpVHost *pVHost, int val, char *achBuf, "AWStats CGI-BIN directory"); if (pVHost->getRootContext().determineMime("pl", - NULL)->getHandler()->getHandlerType()) + NULL)->getHandler()->getType()) handlerType = HandlerType::HT_NULL; else handlerType = HandlerType::HT_CGI; diff --git a/src/http/hiohandlerfactory.cpp b/src/http/hiohandlerfactory.cpp index e39197bc3..d4e0ef2cb 100644 --- a/src/http/hiohandlerfactory.cpp +++ b/src/http/hiohandlerfactory.cpp @@ -23,25 +23,21 @@ #include #include -HioHandler *HioHandlerFactory::getHioHandler(HiosProtocol ver) +HioHandler *HioHandlerFactory::getHioHandler(HiosProtocol proto) { HioHandler *pHioHandler; - switch (ver) + switch (proto) { case HIOS_PROTO_HTTP: pHioHandler = HttpResourceManager::getInstance().getConnection(); return pHioHandler; case HIOS_PROTO_HTTP2: - pHioHandler = (HioHandler *)(new H2Connection()); + pHioHandler = H2Connection::get(); break; default: - pHioHandler = (HioHandler *)(new SpdyConnection()); + pHioHandler = SpdyConnection::get( proto ); break; } - if (!pHioHandler) - return NULL; - - pHioHandler->init(ver); return pHioHandler; } diff --git a/src/http/hiostream.cpp b/src/http/hiostream.cpp index 3a1fe4ce8..6ab0c4cba 100644 --- a/src/http/hiostream.cpp +++ b/src/http/hiostream.cpp @@ -57,3 +57,10 @@ HioHandler::~HioHandler() } + +int HioHandler::h2cUpgrade(HioHandler *pOld) +{ + return LS_FAIL; +} + + diff --git a/src/http/hiostream.h b/src/http/hiostream.h index ce0f40337..d15d9e837 100644 --- a/src/http/hiostream.h +++ b/src/http/hiostream.h @@ -23,12 +23,14 @@ #include #include #include +#include class IOVec; class Aiosfcb; class HioHandler; class HttpRespHeaders; +class HioChainStream; class NtwkIOLink; enum HioState @@ -63,16 +65,19 @@ enum HiosProtocol #define HIO_FLAG_PASS_SETCOOKIE (1<<11) #define HIO_FLAG_SENDFILE (1<<12) +#define HIO_PRIORITY_HIGHEST (0) +#define HIO_PRIORITY_LOWEST (7) +#define HIO_PRIORITY_HTML (2) +#define HIO_PRIORITY_CSS (HIO_PRIORITY_HTML + 1) +#define HIO_PRIORITY_JS (HIO_PRIORITY_CSS + 1) +#define HIO_PRIORITY_IMAGE (HIO_PRIORITY_JS + 1) +#define HIO_PRIORITY_DOWNLOAD (HIO_PRIORITY_IMAGE + 1) +#define HIO_PRIORITY_LARGEFILE (HIO_PRIORITY_LOWEST) + + class HioStream : public InputStream, public OutputStream, public LogTracker { - HioHandler *m_pHandler; - off_t m_lBytesRecv; - off_t m_lBytesSent; - char m_iState; - char m_iProtocol; - short m_iFlag; - uint32_t m_tmLastActive; public: HioStream() @@ -82,6 +87,7 @@ class HioStream : public InputStream, public OutputStream, , m_iState(HIOS_DISCONNECTED) , m_iProtocol(HIOS_PROTO_HTTP) , m_iFlag(0) + , m_iPriority(0) , m_tmLastActive(0) {} virtual ~HioStream(); @@ -94,7 +100,7 @@ class HioStream : public InputStream, public OutputStream, virtual int readv(struct iovec *vector, size_t count) { return -1; } - virtual int sendRespHeaders(HttpRespHeaders *pHeaders) = 0; + virtual int sendRespHeaders(HttpRespHeaders *pHeaders, int isNoBody) = 0; virtual int shutdown() = 0; virtual void suspendRead() = 0; @@ -103,8 +109,15 @@ class HioStream : public InputStream, public OutputStream, virtual void continueWrite() = 0; virtual void switchWriteToRead() = 0; virtual void onTimer() = 0; + virtual uint16_t getEvents() const = 0; + virtual void suspendEventNotify() {}; + virtual void resumeEventNotify() {}; + //virtual SSLConnection * getSSL() = 0; + virtual int isFromLocalAddr() const = 0; virtual NtwkIOLink *getNtwkIoLink() = 0; + virtual void cork(int doCork) {} + //virtual uint32_t GetStreamID() = 0; void reset(int32_t timeStamp) @@ -113,14 +126,29 @@ class HioStream : public InputStream, public OutputStream, m_tmLastActive = timeStamp; } - HioHandler *getHandler() const { return m_pHandler; } - void setHandler(HioHandler *p) { m_pHandler = p; } + int getPriority() const { return m_iPriority; } + void setPriority(int pri) + { + if (pri > HIO_PRIORITY_LOWEST) + pri = HIO_PRIORITY_LOWEST; + else if (pri < HIO_PRIORITY_HIGHEST) + pri = HIO_PRIORITY_HIGHEST; + m_iPriority = pri; + } + void raisePriority(int by = 1) + { setPriority(m_iPriority - by); } + void lowerPriority(int by = 1) + { setProtocol(m_iPriority + by); } + - void wantRead( int want ) + HioHandler *getHandler() const { return m_pHandler; } + void setHandler(HioHandler *p) { m_pHandler = p; } + + void wantRead(int want) { - if ( !(m_iFlag & HIO_FLAG_WANT_READ) == !want ) + if (!(m_iFlag & HIO_FLAG_WANT_READ) == !want) return; - if ( want ) + if (want) { m_iFlag |= HIO_FLAG_WANT_READ; continueRead(); @@ -131,12 +159,11 @@ class HioStream : public InputStream, public OutputStream, suspendRead(); } } - - void wantWrite( int want ) + void wantWrite(int want) { - if ( !(m_iFlag & HIO_FLAG_WANT_WRITE) == !want ) + if (!(m_iFlag & HIO_FLAG_WANT_WRITE) == !want) return; - if ( want ) + if (want) { m_iFlag |= HIO_FLAG_WANT_WRITE; continueWrite(); @@ -147,54 +174,59 @@ class HioStream : public InputStream, public OutputStream, suspendWrite(); } } - - short isWantRead() const { return m_iFlag & HIO_FLAG_WANT_READ; } - short isWantWrite() const { return m_iFlag & HIO_FLAG_WANT_WRITE; } - short isReadyToRelease() const { return m_iFlag & HIO_FLAG_HANDLER_RELEASE; } + short isWantRead() const { return m_iFlag & HIO_FLAG_WANT_READ; } + short isWantWrite() const { return m_iFlag & HIO_FLAG_WANT_WRITE; } + short isReadyToRelease() const { return m_iFlag & HIO_FLAG_HANDLER_RELEASE; } void setFlag(int flagbit, int val) - { m_iFlag = (val) ? (m_iFlag | flagbit) : (m_iFlag & ~flagbit); } - short getFlag(int flagbit) const { return flagbit & m_iFlag; } + { m_iFlag = (val) ? (m_iFlag | flagbit) : (m_iFlag & ~flagbit); } + short getFlag(int flagbit) const { return flagbit & m_iFlag; } - short isAborted() const { return m_iFlag & HIO_FLAG_ABORT; } - void setAbortedFlag() { m_iFlag |= HIO_FLAG_ABORT; } + short isAborted() const { return m_iFlag & HIO_FLAG_ABORT; } + void setAbortedFlag() { m_iFlag |= HIO_FLAG_ABORT; } - void handlerReadyToRelease() { m_iFlag |= HIO_FLAG_HANDLER_RELEASE; } - short canWrite() const { return m_iFlag & HIO_FLAG_BUFF_FULL; } + int isClosing() const { return m_iState != HIOS_CONNECTED; } - char getProtocol() const { return m_iProtocol; } - void setProtocol(int p) { m_iProtocol = p; } + void handlerReadyToRelease(){ m_iFlag |= HIO_FLAG_HANDLER_RELEASE; } + short canWrite() const { return m_iFlag & HIO_FLAG_BUFF_FULL; } - int isSpdy() const { return m_iProtocol; } + char getProtocol() const { return m_iProtocol; } + void setProtocol(int p) { m_iProtocol = p; } - short getState() const { return m_iState; } - void setState(HioState st) { m_iState = st; } + int isSpdy() const { return m_iProtocol; } - void bytesRecv(int n) { m_lBytesRecv += n; } - void bytesSent(int n) { m_lBytesSent += n; } + char getState() const { return m_iState; } + void setState(HioState st) { m_iState = st; } + + void bytesRecv(int n) { m_lBytesRecv += n; } + void bytesSent(int n) { m_lBytesSent += n; } off_t getBytesRecv() const { return m_lBytesRecv; } off_t getBytesSent() const { return m_lBytesSent; } + void resetBytesCount() + { + m_lBytesRecv = 0; + m_lBytesSent = 0; + } + void setActiveTime(uint32_t lTime) { m_tmLastActive = lTime; } uint32_t getActiveTime() const { return m_tmLastActive; } - - void onPeerClose() - { + + void onPeerClose() + { m_iFlag |= HIO_FLAG_PEER_SHUTDOWN; if (m_pHandler) - { handlerOnClose(); - } close(); } - - void tobeClosed() - { + + void tobeClosed() + { if (m_iState != HIOS_SHUTDOWN) - m_iState = HIOS_CLOSING; + m_iState = HIOS_CLOSING; } short isPeerShutdown() const { return m_iFlag & HIO_FLAG_PEER_SHUTDOWN; } @@ -203,12 +235,23 @@ class HioStream : public InputStream, public OutputStream, private: + + HioHandler *m_pHandler; + off_t m_lBytesRecv; + off_t m_lBytesSent; + char m_iState; + char m_iProtocol; + short m_iFlag; + int32_t m_iPriority; + uint32_t m_tmLastActive; + + HioStream(const HioStream &other); HioStream &operator=(const HioStream &other); bool operator==(const HioStream &other) const; void handlerOnClose(); - + }; class HioHandler @@ -229,10 +272,10 @@ class HioHandler p->setHandler(this); } - HioStream *detachStream() + HioStream *detachStream() { - HioStream * pStream = m_pStream; - if ( pStream ) + HioStream *pStream = m_pStream; + if (pStream) { m_pStream = NULL; pStream->setHandler(NULL); @@ -240,13 +283,13 @@ class HioHandler return pStream; } - LOG4CXX_NS::Logger* getLogger() const - { return m_pStream?m_pStream->getLogger():NULL; } + LOG4CXX_NS::Logger *getLogger() const + { return m_pStream ? m_pStream->getLogger() : NULL; } + + const char *getLogId() + { return m_pStream ? m_pStream->getLogId() : "DETACHED"; } - const char * getLogId() - { return m_pStream?m_pStream->getLogId():"DETACHED"; } - virtual int onInitConnected() = 0; virtual int onReadEx() = 0; virtual int onWriteEx() = 0; @@ -255,8 +298,7 @@ class HioHandler virtual void recycle() = 0; - virtual void init(HiosProtocol ver) {}; - virtual void upgradedStream(HioHandler *) {}; + virtual int h2cUpgrade(HioHandler *pOld); private: HioHandler(const HioHandler &other); diff --git a/src/http/httpcontext.h b/src/http/httpcontext.h index 6de356bb0..92a77dda5 100644 --- a/src/http/httpcontext.h +++ b/src/http/httpcontext.h @@ -253,7 +253,7 @@ class HttpContext const AutoStr2 *getRoot() const { return &m_sLocation; } void setRoot(const char *pRoot); - int getHandlerType() const { return m_pHandler->getHandlerType(); } + int getHandlerType() const { return m_pHandler->getType(); } void setHandler(const HttpHandler *p) { m_pHandler = p; } const HttpHandler *getHandler() const { return m_pHandler; } diff --git a/src/http/httpextconnector.cpp b/src/http/httpextconnector.cpp index e8318b553..df164000d 100644 --- a/src/http/httpextconnector.cpp +++ b/src/http/httpextconnector.cpp @@ -401,7 +401,7 @@ int HttpExtConnector::process(HttpSession *pSession, setHttpSession(pSession); setAttempts(0); m_iRespHeaderSize = 0; - if (pHandler->getHandlerType() == HandlerType::HT_LOADBALANCER) + if (pHandler->getType() == HandlerType::HT_LOADBALANCER) { LoadBalancer *pLB = (LoadBalancer *)pHandler; setLB(pLB); diff --git a/src/http/httphandler.cpp b/src/http/httphandler.cpp index fd206a939..f01aa6bd1 100644 --- a/src/http/httphandler.cpp +++ b/src/http/httphandler.cpp @@ -17,8 +17,8 @@ *****************************************************************************/ #include "httphandler.h" -HttpHandler::HttpHandler() - : m_iType(0) +HttpHandler::HttpHandler(int type) + : m_iType(type) {} HttpHandler::HttpHandler(const HttpHandler &rhs) diff --git a/src/http/httphandler.h b/src/http/httphandler.h index 8a80bd934..c23173699 100644 --- a/src/http/httphandler.h +++ b/src/http/httphandler.h @@ -24,12 +24,11 @@ class HttpHandler int m_iType; void operator=(const HttpHandler &rhs); public: - HttpHandler(); + explicit HttpHandler(int type); HttpHandler(const HttpHandler &rhs); virtual ~HttpHandler(); - int getHandlerType() const { return m_iType; } - void setHandlerType(int type) { m_iType = type; } + int getType() const { return m_iType; } virtual const char *getName() const = 0; }; diff --git a/src/http/httpmime.cpp b/src/http/httpmime.cpp index f56bb517c..5c31820cf 100644 --- a/src/http/httpmime.cpp +++ b/src/http/httpmime.cpp @@ -170,7 +170,7 @@ void MIMESetting::setHandler(const HttpHandler *pHdlr) void MIMESetting::inherit(const MIMESetting *pParent, int updateOnly) { - if (!m_expires.cfgHandler() && (!m_pHandler->getHandlerType() + if (!m_expires.cfgHandler() && (!m_pHandler->getType() || !updateOnly)) m_pHandler = (HttpHandler *)pParent->getHandler(); if (!m_expires.cfgCompress()) diff --git a/src/http/httpreq.cpp b/src/http/httpreq.cpp index b23859b31..c2cfdd368 100644 --- a/src/http/httpreq.cpp +++ b/src/http/httpreq.cpp @@ -1273,7 +1273,7 @@ int HttpReq::checkSuffixHandler(const char *pURI, int len, int &cacheable) if (ret) return ret; } - if (m_pHttpHandler->getHandlerType() == HandlerType::HT_PROXY) + if (m_pHttpHandler->getType() == HandlerType::HT_PROXY) return -2; if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] Cannot found appropriate handler for [%s]", @@ -1301,7 +1301,7 @@ int HttpReq::processSuffix(const char *pURI, const char *pURIEnd, } } } - if (m_pHttpHandler->getHandlerType() == HandlerType::HT_NULL) + if (m_pHttpHandler->getType() == HandlerType::HT_NULL) return setMimeBySuffix(pSuffix); return 0; } @@ -1330,7 +1330,7 @@ int HttpReq::setMimeBySuffix(const char *pSuffix) getLogId(), pSuffix ? pSuffix : "")); return SC_403; } - if (m_pHttpHandler->getHandlerType() != HandlerType::HT_NULL) + if (m_pHttpHandler->getType() != HandlerType::HT_NULL) { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] Find handler [%s] for [.%s]", @@ -1469,7 +1469,7 @@ int HttpReq::processContext() if (m_pContext->getMatchList()) //regular expression match processMatchList(m_pContext, pURI, iURILen); } - if (m_pHttpHandler->getHandlerType() == HandlerType::HT_PROXY) + if (m_pHttpHandler->getType() == HandlerType::HT_PROXY) return -2; if (m_pContext != pOldCtx) m_iContextState &= ~CONTEXT_AUTH_CHECKED; @@ -1546,7 +1546,7 @@ int HttpReq::processMatchedURI(const char *pURI, int uriLen, getLogId(), m_pContext->getURI())); return SC_403; //access denied } - if (m_pHttpHandler->getHandlerType() >= HandlerType::HT_FASTCGI) + if (m_pHttpHandler->getType() >= HandlerType::HT_FASTCGI) { m_pRealPath = NULL; return 0; @@ -1674,7 +1674,7 @@ int HttpReq::processPath(const char *pURI, int uriLen, char *pBuf, if (p != pEnd) return checkSuffixHandler(pURI, uriLen, cacheable); //NOTE: why need to check this? - //if (m_pHttpHandler->getHandlerType() != HandlerType::HT_NULL ) + //if (m_pHttpHandler->getType() != HandlerType::HT_NULL ) // return SC_404; int l = pBuf + GLOBAL_BUF_SIZE - p; const StringList *pIndexList = m_pContext->getIndexFileList(); @@ -1727,7 +1727,7 @@ int HttpReq::processPath(const char *pURI, int uriLen, char *pBuf, if (m_pContext->shouldMatchFiles()) forcedType = filesMatch(p); if ((!forcedType) && - (m_pHttpHandler->getHandlerType() == HandlerType::HT_NULL)) + (m_pHttpHandler->getType() == HandlerType::HT_NULL)) { //m_pMimeType = NULL; ret = processSuffix(pBuf, p, cacheable); diff --git a/src/http/httprespheaders.h b/src/http/httprespheaders.h index b4584c3bb..1d71cb5af 100644 --- a/src/http/httprespheaders.h +++ b/src/http/httprespheaders.h @@ -122,12 +122,11 @@ class HttpRespHeaders int del(const char *pName, int nameLen); int del(HEADERINDEX headerIndex); - int getHeadersCount(int dupLineAsOne) + int getUniqueCnt() const { return m_iHeaderUniqueCount; } + + int getCount() const { - if (dupLineAsOne) - return m_iHeaderUniqueCount; - else - return m_aKVPairs.getSize() - m_iHeaderRemovedCount; + return m_aKVPairs.getSize() - m_iHeaderRemovedCount; } int getTotalCount() const { return m_aKVPairs.getSize(); } diff --git a/src/http/httpsession.cpp b/src/http/httpsession.cpp index e5d1af710..494ae05ca 100644 --- a/src/http/httpsession.cpp +++ b/src/http/httpsession.cpp @@ -1331,7 +1331,7 @@ int HttpSession::processContextRewrite() int HttpSession::processFileMap() { if (getReq()->getHttpHandler() == NULL || - getReq()->getHttpHandler()->getHandlerType() != HandlerType::HT_MODULE) + getReq()->getHttpHandler()->getType() != HandlerType::HT_MODULE) { int ret = m_request.processContextPath(); if (D_ENABLED(DL_LESS)) @@ -1415,7 +1415,7 @@ int HttpSession::processAuthorizer() int HttpSession::processNewUri() { if (getReq()->getHttpHandler() != NULL && - getReq()->getHttpHandler()->getHandlerType() == HandlerType::HT_MODULE) + getReq()->getHttpHandler()->getType() == HandlerType::HT_MODULE) m_processState = HSPS_BEGIN_HANDLER_PROCESS; else m_processState = HSPS_VHOST_REWRITE; @@ -1500,12 +1500,12 @@ int HttpSession::handlerProcess(const HttpHandler *pHandler) m_processState = HSPS_HANDLER_PROCESSING; if (m_pHandler) cleanUpHandler(); - int type = pHandler->getHandlerType(); + int type = pHandler->getType(); if ((type >= HandlerType::HT_DYNAMIC) && (type != HandlerType::HT_PROXY)) if (m_request.checkScriptPermission() == 0) return SC_403; - if (pHandler->getHandlerType() == HandlerType::HT_SSI) + if (pHandler->getType() == HandlerType::HT_SSI) { const HttpContext *pContext = m_request.getContext(); if (pContext && !pContext->isIncludesOn()) @@ -1579,7 +1579,7 @@ int HttpSession::assignHandler(const HttpHandler *pHandler) { ReqHandler *pNewHandler; int handlerType; - handlerType = pHandler->getHandlerType(); + handlerType = pHandler->getType(); pNewHandler = HandlerFactory::getHandler(handlerType); if (pNewHandler == NULL) { @@ -1793,7 +1793,7 @@ int HttpSession::buildErrorResponse(const char *errMsg) LOG_ERR(("[%s] invalid HTTP version: %d!", getLogId(), ver)); ver = HTTP_1_1; } - if (sendBody()) + if (!isNoRespBody()) { const char *pHtml = HttpStatusCode::getInstance().getRealHtml(errCode); if (pHtml) @@ -2923,7 +2923,7 @@ int HttpSession::endResponseInternal(int success) return 1; } - if (sendBody() && m_sessionHooks.isEnabled(LSI_HKPT_RECV_RESP_BODY)) + if (!isNoRespBody() && m_sessionHooks.isEnabled(LSI_HKPT_RECV_RESP_BODY)) { ret = runFilter(LSI_HKPT_RECV_RESP_BODY, (filter_term_fn)appendDynBodyTermination, @@ -2986,8 +2986,12 @@ int HttpSession::endResponse(int success) } + setState(HSS_WRITING); setFlag(HSF_RESP_FLUSHED, 0); - ret = flush(); + if (getStream()->isSpdy()) + getStream()->continueWrite(); + else + ret = flush(); return ret; } @@ -3079,7 +3083,7 @@ int HttpSession::flush() suspendWrite(); return LS_DONE; } - if (!sendBody() && !getFlag(HSF_HANDLER_DONE)) + if (isNoRespBody() && !getFlag(HSF_HANDLER_DONE)) { ret = endResponseInternal(1); if (ret) @@ -3100,7 +3104,7 @@ int HttpSession::flush() return LS_DONE; } - if (sendBody()) + if (!isNoRespBody()) { ret = flushBody(); if (D_ENABLED(DL_LESS)) @@ -3194,7 +3198,8 @@ int HttpSession::sendRespHeaders() if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] sendRespHeaders()", getLogId())); - if (sendBody()) + int isNoBody = isNoRespBody(); + if ( !isNoBody ) { if (m_sessionHooks.isEnabled(LSI_HKPT_SEND_RESP_BODY)) m_response.setContentLen(LSI_RESP_BODY_SIZE_UNKNOWN); @@ -3208,7 +3213,7 @@ int HttpSession::sendRespHeaders() if (finalizeHeader(m_request.getVersion(), m_request.getStatusCode())) return 1; - getStream()->sendRespHeaders(&m_response.getRespHeaders()); + getStream()->sendRespHeaders(&m_response.getRespHeaders(), isNoBody); m_iFlag |= HSF_RESP_HEADER_SENT; setState(HSS_WRITING); return 0; @@ -3219,7 +3224,7 @@ int HttpSession::setupDynRespBodyBuf() { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] setupDynRespBodyBuf()", getLogId())); - if (sendBody()) + if (!isNoRespBody()) { if (setupRespCache() == -1) return LS_FAIL; @@ -3761,7 +3766,7 @@ int HttpSession::finalizeHeader(int ver, int code) return ret; } - if (sendBody()) + if (!isNoRespBody()) return contentEncodingFixup(); return 0; } diff --git a/src/http/httpsession.h b/src/http/httpsession.h index 1ba8d0c93..f97c18036 100644 --- a/src/http/httpsession.h +++ b/src/http/httpsession.h @@ -360,8 +360,8 @@ class HttpSession : public LsiSession, public HioHandler, int writeRespBodyDirect(const char *pBuf, int size); int writeRespBody(const char *pBuf, int len); - bool sendBody() const - { return !m_request.noRespBody(); } + int isNoRespBody() const + { return m_request.noRespBody(); } int onReadEx(); diff --git a/src/http/ntwkiolink.cpp b/src/http/ntwkiolink.cpp index 35c00dfd7..66ea0f9ee 100644 --- a/src/http/ntwkiolink.cpp +++ b/src/http/ntwkiolink.cpp @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -278,7 +279,7 @@ int NtwkIOLink::switchToHttp2Handler(HioHandler *pSession) clearLogId(); setProtocol(HIOS_PROTO_HTTP2); pHandler->attachStream(this); - pHandler->upgradedStream(pSession); + pHandler->h2cUpgrade(pSession); return 0; } @@ -702,9 +703,21 @@ int NtwkIOLink::flush() } +void NtwkIOLink::flushSslWpending() +{ + int pending = m_ssl.wpending(); + if (D_ENABLED(DL_LESS)) + LOG_D((getLogger(), "[%s] SSL wpending: %d", + getLogId(), pending)); + if (pending > 0) + flush(); +} + + int NtwkIOLink::onWriteSSL(NtwkIOLink *pThis) { pThis->dumpState("onWriteSSL", "none"); + pThis->flushSslWpending(); if (pThis->m_ssl.wantWrite()) { if (!pThis->m_ssl.isConnected() || (pThis->m_ssl.lastRead())) @@ -1146,7 +1159,7 @@ int NtwkIOLink::writevEx(LsiSession *pOS, const iovec *vector, int count) } -int NtwkIOLink::sendRespHeaders(HttpRespHeaders *pHeader) +int NtwkIOLink::sendRespHeaders(HttpRespHeaders *pHeader, int isNoBody) { if (pHeader) { @@ -1406,6 +1419,7 @@ int NtwkIOLink::writevExT(LsiSession *pOS, const iovec *vector, int count) void NtwkIOLink::onTimerSSL_T(NtwkIOLink *pThis) { + pThis->flushSslWpending(); if (pThis->allowWrite() && (pThis->m_ssl.wantWrite())) onWriteSSL_T(pThis); if (pThis->allowRead() && (pThis->m_ssl.wantRead())) @@ -1859,4 +1873,16 @@ const char *NtwkIOLink::buildLogId() } +int NtwkIOLink::isFromLocalAddr() const +{ + char achAddr[128]; + socklen_t addrlen = 128; + if ( getsockname( getfd(), (struct sockaddr *) achAddr, &addrlen ) == -1 ) + { + return 0; + } + const struct sockaddr * pServer = (struct sockaddr *) achAddr; + const struct sockaddr * pClient = getClientInfo()->getAddr(); + return ( GSockAddr::compareAddr( pServer, pClient ) == 0 ); +} diff --git a/src/http/ntwkiolink.h b/src/http/ntwkiolink.h index 9616f48cf..36ea78cd4 100644 --- a/src/http/ntwkiolink.h +++ b/src/http/ntwkiolink.h @@ -209,6 +209,7 @@ class NtwkIOLink : public LsiSession, public EventReactor, public HioStream void updateSSLEvent(); void checkSSLReadRet(int ret); + void flushSslWpending(); int setupHandler(HiosProtocol verSpdy); int sslSetupHandler(); @@ -240,7 +241,7 @@ class NtwkIOLink : public LsiSession, public EventReactor, public HioStream unsigned short getRemotePort() const { return m_iRemotePort; }; - int sendRespHeaders(HttpRespHeaders *pHeaders); + int sendRespHeaders(HttpRespHeaders *pHeaders, int isNoBody); const char *buildLogId(); LogTracker *getLogTracker() { return this; } @@ -333,12 +334,15 @@ class NtwkIOLink : public LsiSession, public EventReactor, public HioStream void suspendWrite(); void continueWrite(); void switchWriteToRead(); + uint16_t getEvents() const + { return EventReactor::getEvents(); } void checkThrottle(); //void setThrottleLimit( int limit ) //{ m_baseIO.getThrottleCtrl().setLimit( limit ); } void onTimer(); + int isFromLocalAddr() const; //void stopThrottleTimer(); //void startThrottleTimer(); diff --git a/src/http/staticfilehandler.cpp b/src/http/staticfilehandler.cpp index 90abefe39..4243250a7 100644 --- a/src/http/staticfilehandler.cpp +++ b/src/http/staticfilehandler.cpp @@ -48,8 +48,8 @@ RedirectHandler::RedirectHandler() + : HttpHandler(HandlerType::HT_REDIRECT) { - setHandlerType(HandlerType::HT_REDIRECT); } @@ -64,8 +64,8 @@ const char *RedirectHandler::getName() const StaticFileHandler::StaticFileHandler() + : HttpHandler(HandlerType::HT_STATIC) { - setType(0); } diff --git a/src/lsiapi/lsiapilib.cpp b/src/lsiapi/lsiapilib.cpp index f89157452..03c78938f 100644 --- a/src/lsiapi/lsiapilib.cpp +++ b/src/lsiapi/lsiapilib.cpp @@ -552,7 +552,7 @@ static int get_resp_headers_count(lsi_session_t *session) if (pSession == NULL) return LS_FAIL; HttpRespHeaders &respHeaders = pSession->getResp()->getRespHeaders(); - return respHeaders.getHeadersCount(0); //For API, retuen the non-spdy case + return respHeaders.getCount(); //For API, retuen the non-spdy case } diff --git a/src/lsiapi/modulemanager.cpp b/src/lsiapi/modulemanager.cpp index 5f7c94739..2649ec6fe 100644 --- a/src/lsiapi/modulemanager.cpp +++ b/src/lsiapi/modulemanager.cpp @@ -35,8 +35,8 @@ ModuleConfig ModuleManager::g_moduleConfig; LsiModule::LsiModule(lsi_module_t *pModule) + : HttpHandler(HandlerType::HT_MODULE) { - setHandlerType(HandlerType::HT_MODULE); m_pModule = pModule; } diff --git a/src/socket/gsockaddr.cpp b/src/socket/gsockaddr.cpp index 56907e292..1a32aa94e 100644 --- a/src/socket/gsockaddr.cpp +++ b/src/socket/gsockaddr.cpp @@ -434,4 +434,22 @@ GSockAddr &GSockAddr::operator=(const in_addr_t addr) } +int GSockAddr::compareAddr( const struct sockaddr * pAddr1, + const struct sockaddr * pAddr2 ) +{ + switch( pAddr1->sa_family ) + { + case AF_INET: + return memcmp( &((const struct sockaddr_in *)pAddr1)->sin_addr, + &((const struct sockaddr_in *)pAddr2)->sin_addr, + sizeof( in_addr_t ) ); + case AF_INET6: + return memcmp( &((const struct sockaddr_in6 *)pAddr1)->sin6_addr, + &((const struct sockaddr_in6 *)pAddr2)->sin6_addr, + sizeof( in6_addr ) ); + default: + return 0; + } + +} diff --git a/src/socket/gsockaddr.h b/src/socket/gsockaddr.h index 6b07ce543..8c061a41f 100644 --- a/src/socket/gsockaddr.h +++ b/src/socket/gsockaddr.h @@ -116,6 +116,9 @@ class GSockAddr const char *toString() const; int getPort() const; void setPort(short port); + + static int compareAddr( const struct sockaddr * pAddr1, + const struct sockaddr * pAddr2 ); }; #endif diff --git a/src/spdy/h2connection.cpp b/src/spdy/h2connection.cpp index e3ce15a68..41e38e32d 100644 --- a/src/spdy/h2connection.cpp +++ b/src/spdy/h2connection.cpp @@ -22,11 +22,12 @@ #include #include #include +#include #include -#include - -#include +#include +#include +#include static const char s_h2sUpgradeResponse[] = "HTTP/1.1 101 Switching Protocols\r\nConnection: Upgrade\r\nUpgrade: h2c\r\n\r\n"; @@ -85,20 +86,29 @@ H2Connection::H2Connection() { m_timevalPing.tv_sec = 0; m_pCurH2Header = (H2FrameHeader *)m_iaH2HeaderMem; + } -void H2Connection::init(HiosProtocol ver) +HioHandler *H2Connection::get() +{ + H2Connection *pConn = new H2Connection(); + //pConn->init(); + return pConn; +} + + +int H2Connection::init() { m_iCurDataOutWindow = H2_FCW_INIT_SIZE; m_uiLastStreamID = 0; - m_timevalPing.tv_sec = 0; m_iStreamOutInitWindowSize = H2_FCW_INIT_SIZE; m_iServerMaxStreams = 100; m_iClientMaxStreams = 100; m_tmIdleBegin = 0; m_iCurrentFrameRemain = -H2_FRAME_HEADER_SIZE; m_pCurH2Header = (H2FrameHeader *)m_iaH2HeaderMem; + return 0; } @@ -118,16 +128,13 @@ H2Connection::~H2Connection() int H2Connection::onReadEx() { - int ret = onReadEx2(); + int ret; + m_iFlag &= ~H2_CONN_FLAG_WAIT_PROCESS; + ret = onReadEx2(); + if ((m_iFlag & H2_CONN_FLAG_WAIT_PROCESS) != 0) + onWriteEx(); if (getBuf()->size() > 1024) flush(); - - if (D_ENABLED(DL_LESS)) - { - LOG_D((getLogger(), "[%s] H2Connection::onReadEx() buffered data sise = %d", - getLogId(), getBuf()->size())); - } - return ret; } @@ -160,14 +167,14 @@ int H2Connection::parseFrame() break; m_bufInput.moveTo((char *)m_pCurH2Header, H2_FRAME_HEADER_SIZE); uint32_t id = m_pCurH2Header->getStreamId(); - if (id && (id % 2 == 0)) + if (id && (id % 2 == 0)) { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] invalid frame id %d (type %d)", getLogId(), id, m_pCurH2Header->getType())); return LS_FAIL; } - + m_iCurrentFrameRemain = m_pCurH2Header->getLength(); if (D_ENABLED(DL_LESS)) { @@ -197,9 +204,7 @@ int H2Connection::parseFrame() if ((m_iFlag & H2_CONN_HEADERS_START) == H2_CONN_HEADERS_START && m_pCurH2Header->getType() != H2_FRAME_CONTINUATION) - { return LS_FAIL; - } if (m_pCurH2Header->getType() != H2_FRAME_DATA) { @@ -208,10 +213,7 @@ int H2Connection::parseFrame() if (processFrame(m_pCurH2Header) == LS_FAIL) return LS_FAIL; if (m_iCurrentFrameRemain > 0) - { m_bufInput.pop_front(m_iCurrentFrameRemain); - m_iCurrentFrameRemain = 0; - } m_iCurrentFrameRemain = -H2_FRAME_HEADER_SIZE; } else @@ -249,7 +251,7 @@ int H2Connection::onReadEx2() n = getStream()->read(m_bufInput.end(), avaiLen); if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] read() return %d", - getLogId(), n)); + getLogId(), n)); if (n == -1) break; @@ -282,24 +284,23 @@ int H2Connection::processFrame(H2FrameHeader *pHeader) { static uint32_t requiredLength[11] = { 0, 0, 5, 4, 0, 0, 8, 0, 4, 0, 0 }; - + m_tmLastFrameIn = DateTime::s_curTime; - + int type = pHeader->getType(); //m_bufInput.moveTo((char *)pHeader + H2_FRAME_HEADER_SIZE, extraHeader); - if ( type < H2_FRAME_MAX_TYPE) + if (type < H2_FRAME_MAX_TYPE) { - if ((requiredLength[type] != 0) + if ((requiredLength[type] != 0) && (requiredLength[type] != pHeader->getLength())) { - doGoAway( H2_ERROR_FRAME_SIZE_ERROR ); + doGoAway(H2_ERROR_FRAME_SIZE_ERROR); return 0; } } memset((char *)pHeader + H2_FRAME_HEADER_SIZE, 0, 10); printLogMsg(pHeader); - switch (type) { case H2_FRAME_HEADERS: @@ -322,7 +323,7 @@ int H2Connection::processFrame(H2FrameHeader *pHeader) case H2_FRAME_PING: return processPingFrame(pHeader); default: - sendPingFrame(0, (uint8_t *)"01234567" ); + sendPingFrame(0, (uint8_t *)"01234567"); break; } return 0; @@ -333,31 +334,32 @@ void H2Connection::printLogMsg(H2FrameHeader *pHeader) { if (D_ENABLED(DL_LESS)) { - const char * message = ""; + const char *message = ""; int messageLen = 0; if (pHeader->getType() == H2_FRAME_GOAWAY) { message = (const char *)m_bufInput.begin() + 8; messageLen = pHeader->getLength() - 8; } - LOG_D((getLogger(), "[%s] Received %s, size: %d, stream: %d, flag: 0x%hhx, Message: '%.*s'\n", - getLogId(), getH2FrameName(pHeader->getType()), pHeader->getLength(), - pHeader->getStreamId(), pHeader->getFlags(), - messageLen, message)); + LOG_D((getLogger(), + "[%s-%d] Received %s, size: %d, flag: 0x%hhx, Message: '%.*s'\n", + getLogId(), pHeader->getStreamId(), + getH2FrameName(pHeader->getType()), pHeader->getLength(), + pHeader->getFlags(), messageLen, message)); } } int H2Connection::processPriorityFrame(H2FrameHeader *pHeader) { - if (pHeader->getStreamId() == 0 ) + if (pHeader->getStreamId() == 0) { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), - "[%s] bad PRIORITY frame, stream ID is zero.", - getLogId())); + "[%s] bad PRIORITY frame, stream ID is zero.", + getLogId())); return LS_FAIL; - + } return 0; @@ -385,24 +387,24 @@ int H2Connection::processSettingFrame(H2FrameHeader *pHeader) "SETTINGS_MAX_HEADER_LIST_SIZE" }; uint32_t iEntryID, iEntryValue; - if (pHeader->getStreamId() != 0 ) + if (pHeader->getStreamId() != 0) { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), - "[%s] bad SETTINGS frame, stream ID must be zero.", - getLogId())); + "[%s] bad SETTINGS frame, stream ID must be zero.", + getLogId())); doGoAway(H2_ERROR_PROTOCOL_ERROR); return 0; - + } - + int iEntries = m_iCurrentFrameRemain / 6; if (m_iCurrentFrameRemain % 6 != 0) { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), - "[%s] bad SETTINGS frame, frame size does not match.", - getLogId())); + "[%s] bad SETTINGS frame, frame size does not match.", + getLogId())); doGoAway(H2_ERROR_FRAME_SIZE_ERROR); return 0; } @@ -413,8 +415,8 @@ int H2Connection::processSettingFrame(H2FrameHeader *pHeader) { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), - "[%s] bad SETTINGS frame with ACK flag, has %d entries.", - getLogId(), iEntries)); + "[%s] bad SETTINGS frame with ACK flag, has %d entries.", + getLogId(), iEntries)); return LS_FAIL; } if (m_iFlag & H2_CONN_FLAG_SETTING_SENT) @@ -426,8 +428,8 @@ int H2Connection::processSettingFrame(H2FrameHeader *pHeader) { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), - "[%s] received SETTINGS frame with ACK flag before sending our SETTINGS frame.", - getLogId())); + "[%s] received SETTINGS frame with ACK flag before sending our SETTINGS frame.", + getLogId())); return LS_FAIL; } } @@ -456,13 +458,13 @@ int H2Connection::processSettingFrame(H2FrameHeader *pHeader) { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] MAX_FRAME_SIZE value is invalid, %d.", - getLogId(), iEntryValue)); + getLogId(), iEntryValue)); return LS_FAIL; } m_iPeerMaxFrameSize = iEntryValue; break; case H2_SETTINGS_INITIAL_WINDOW_SIZE: - if (iEntryValue > H2_FCW_MAX_SIZE ) + if (iEntryValue > H2_FCW_MAX_SIZE) { doGoAway(H2_ERROR_FLOW_CONTROL_ERROR); return 0; @@ -477,9 +479,7 @@ int H2Connection::processSettingFrame(H2FrameHeader *pHeader) break; case H2_SETTINGS_ENABLE_PUSH: if (iEntryValue > 1) - { return LS_FAIL; - } default: break; } @@ -510,17 +510,17 @@ int H2Connection::processWindowUpdateFrame(H2FrameHeader *pHeader) m_bufInput.moveTo(sTemp, 4); m_iCurrentFrameRemain -= 4; uint32_t id = pHeader->getStreamId(); - uint32_t delta = beReadUint32((const unsigned char *)sTemp); + int32_t delta = beReadUint32((const unsigned char *)sTemp); delta &= 0x7FFFFFFFu; if (delta == 0) { if (D_ENABLED(DL_LESS)) { LOG_D((getLogger(), - "[%s] session WINDOW_UPDATE ERROR: %d", - getLogId(), delta)); + "[%s] session WINDOW_UPDATE ERROR: %d", + getLogId(), delta)); } - if ( id ) + if (id) sendRstFrame(id, H2_ERROR_PROTOCOL_ERROR); else doGoAway(H2_ERROR_PROTOCOL_ERROR); @@ -532,14 +532,14 @@ int H2Connection::processWindowUpdateFrame(H2FrameHeader *pHeader) { // || (id == 0 && ((delta % 4) != 0)) uint32_t tmpVal = m_iCurDataOutWindow + delta; - if (tmpVal > 2147483647) //2^31 -1 + if (tmpVal > 2147483647) //2^31 -1 { //sendRstFrame(pHeader->getStreamId(), H2_ERROR_PROTOCOL_ERROR); if (D_ENABLED(DL_LESS)) { LOG_D((getLogger(), - "[%s] session WINDOW_UPDATE ERROR: %d, window size: %d, total %d (m_iDataInWindow: %d) ", - getLogId(), delta, m_iCurDataOutWindow, tmpVal, m_iDataInWindow)); + "[%s] session WINDOW_UPDATE ERROR: %d, window size: %d, total %d (m_iDataInWindow: %d) ", + getLogId(), delta, m_iCurDataOutWindow, tmpVal, m_iDataInWindow)); } doGoAway(H2_ERROR_FLOW_CONTROL_ERROR); return 0; @@ -550,7 +550,7 @@ int H2Connection::processWindowUpdateFrame(H2FrameHeader *pHeader) "[%s] session WINDOW_UPDATE: %d, current window size: %d, new: %d ", getLogId(), delta, m_iCurDataOutWindow, tmpVal)); } - if (m_iCurDataOutWindow < 0 && tmpVal > 0) + if (m_iCurDataOutWindow <= 0 && tmpVal > 0) { m_iCurDataOutWindow = tmpVal; onWriteEx(); @@ -566,15 +566,15 @@ int H2Connection::processWindowUpdateFrame(H2FrameHeader *pHeader) int ret = pStream->adjWindowOut(delta); if (ret < 0) sendRstFrame(id, H2_ERROR_FLOW_CONTROL_ERROR); - else if ( pStream->getWindowOut() <= (int)delta ) + else if (pStream->getWindowOut() <= delta) pStream->continueWrite(); - + } else { if (id > m_uiLastStreamID) return LS_FAIL; - sendRstFrame(id, H2_ERROR_FLOW_CONTROL_ERROR); + //sendRstFrame(id, H2_ERROR_STREAM_CLOSED); } //flush(); @@ -587,15 +587,13 @@ int H2Connection::processWindowUpdateFrame(H2FrameHeader *pHeader) int H2Connection::processRstFrame(H2FrameHeader *pHeader) { uint32_t streamID = pHeader->getStreamId(); - + if (streamID == 0 || streamID > m_uiLastStreamID) return LS_FAIL; - + H2Stream *pH2Stream = findStream(streamID); if (pH2Stream == NULL) - { return 0; - } unsigned char p[4]; m_bufInput.moveTo((char *)p, 4); @@ -624,9 +622,9 @@ void H2Connection::skipRemainData() int H2Connection::processDataFrame(H2FrameHeader *pHeader) { uint32_t streamID = pHeader->getStreamId(); - if ( streamID == 0 || streamID > m_uiLastStreamID) + if (streamID == 0 || streamID > m_uiLastStreamID) return LS_FAIL; - + H2Stream *pH2Stream = findStream(streamID); if (pH2Stream == NULL || pH2Stream->isPeerShutdown()) { @@ -652,12 +650,10 @@ int H2Connection::processDataFrame(H2FrameHeader *pHeader) if (len > m_iCurrentFrameRemain) len = m_iCurrentFrameRemain; m_iCurrentFrameRemain -= len; - if ( pH2Stream->appendReqData(m_bufInput.begin(), len, - m_iCurrentFrameRemain ? 0 - : pHeader->getFlags()) == LS_FAIL) - { + if (pH2Stream->appendReqData(m_bufInput.begin(), len, + m_iCurrentFrameRemain ? 0 + : pHeader->getFlags()) == LS_FAIL) sendRstFrame(streamID, H2_ERROR_PROTOCOL_ERROR); - } m_bufInput.pop_front(len); m_iCurInBytesToUpdate += len; } @@ -689,7 +685,7 @@ int H2Connection::processContinuationFrame(H2FrameHeader *pHeader) return 0; uint32_t id = pHeader->getStreamId(); if ((id != m_uiLastStreamID) - || (m_iFlag & H2_CONN_HEADERS_START) == 0 ) + || (m_iFlag & H2_CONN_HEADERS_START) == 0) { if (D_ENABLED(DL_LESS)) { @@ -735,7 +731,7 @@ int H2Connection::processReqHeader(unsigned char iHeaderFlag) } m_iCurrentFrameRemain -= iDatalen; } - + if (iHeaderFlag & H2_FLAG_END_HEADERS) { unsigned char *pSrc = NULL; @@ -755,7 +751,8 @@ int H2Connection::processReqHeader(unsigned char iHeaderFlag) } -int H2Connection::decodeHeaders(unsigned char *pSrc, int length, unsigned char iHeaderFlag) +int H2Connection::decodeHeaders(unsigned char *pSrc, int length, + unsigned char iHeaderFlag) { char method[10] = {0}; int methodLen = 0; @@ -764,14 +761,15 @@ int H2Connection::decodeHeaders(unsigned char *pSrc, int length, unsigned char i int contentLen = -1; unsigned char *bufEnd = pSrc + length; - int rc = decodeData(pSrc, bufEnd, method, &methodLen, &uri, &uriLen, &contentLen); + int rc = decodeData(pSrc, bufEnd, method, &methodLen, &uri, &uriLen, + &contentLen); if (rc < 0) { if (uri) free(uri); if (D_ENABLED(DL_LESS)) { - LOG_D((getLogger(), "[%s] decodeData() failure, return %d", + LOG_D((getLogger(), "[%s] decodeData() failure, return %d", getLogId(), rc)); } return LS_FAIL; @@ -802,20 +800,27 @@ int H2Connection::decodeHeaders(unsigned char *pSrc, int length, unsigned char i int H2Connection::processHeadersFrame(H2FrameHeader *pHeader) { + uint32_t id = pHeader->getStreamId(); if (m_iFlag & H2_CONN_FLAG_GOAWAY) return 0; - uint32_t id = pHeader->getStreamId(); + + if (id == 0) + { + LOG_INFO(("[%s] Protocol error, HEADER frame STREAM ID is 0", + getLogId())); + return LS_FAIL; + } + if (id <= m_uiLastStreamID) { - if ( id != 0) - sendRstFrame(id, H2_ERROR_PROTOCOL_ERROR); + sendRstFrame(id, H2_ERROR_PROTOCOL_ERROR); LOG_INFO(("[%s] Protocol error, STREAM ID: %d is less the" " previously received stream ID: %d, go away!", getLogId(), id, m_uiLastStreamID)); return LS_FAIL; } m_uiLastStreamID = id; - + unsigned char iHeaderFlag = pHeader->getFlags(); unsigned char *pSrc = (unsigned char *)m_bufInput.begin(); @@ -832,7 +837,7 @@ int H2Connection::processHeadersFrame(H2FrameHeader *pHeader) pSrc = (unsigned char *)m_bufInput.begin(); m_priority.m_exclusive = *pSrc >> 7; m_priority.m_dependStreamId = beReadUint32((const unsigned char *)pSrc) & - 0x7FFFFFFFu; + 0x7FFFFFFFu; //Add one to the value to obtain a weight between 1 and 256. m_priority.m_weight = *(pSrc + 4) + 1; @@ -850,8 +855,8 @@ int H2Connection::processHeadersFrame(H2FrameHeader *pHeader) } -int H2Connection::decodeData(unsigned char *pSrc, unsigned char *bufEnd, - char *method, int *methodLen, char **uri, +int H2Connection::decodeData(unsigned char *pSrc, unsigned char *bufEnd, + char *method, int *methodLen, char **uri, int *uriLen, int *contentLen) { int rc, n = 0; @@ -860,9 +865,9 @@ int H2Connection::decodeData(unsigned char *pSrc, unsigned char *bufEnd, AutoBuf namevaleBuf(8192); uint16_t name_len = 0 ; uint16_t val_len = 0; - AutoBuf cookieStr( 0 ); + AutoBuf cookieStr(0); int regular_header = 0; - + bool authority = false; bool scheme = false; bool error = false; @@ -939,14 +944,14 @@ int H2Connection::decodeData(unsigned char *pSrc, unsigned char *bufEnd, cookieStr.append(val, val_len); name_len = 0; } - else if (name_len == 2 && memcmp(name, "te", 2) == 0 ) + else if (name_len == 2 && memcmp(name, "te", 2) == 0) { - if ( val_len != 8 || strncasecmp("trailers", val, 8) != 0 ) + if (val_len != 8 || strncasecmp("trailers", val, 8) != 0) return LS_FAIL; } else if (name_len == 14 && memcmp(name, "content-length", 14) == 0) { - char * pEnd = val + val_len; + char *pEnd = val + val_len; int64_t len = strtoll(val, &pEnd, 10); if (len < INT_MAX) *contentLen = len; @@ -989,7 +994,7 @@ int H2Connection::decodeData(unsigned char *pSrc, unsigned char *bufEnd, } -int H2Connection::appendReqHeaders(H2Stream *pStream, char *method, +int H2Connection::appendReqHeaders(H2Stream *pStream, char *method, int methodLen, char *uri, int uriLen) { if (method && methodLen && uri && uriLen) @@ -1020,9 +1025,11 @@ H2Stream *H2Connection::getNewStream(uint8_t ubH2_Flags) m_mapStream.insert((void *)(long)m_uiLastStreamID, pStream); if (D_ENABLED(DL_MORE)) { - LOG_D((getLogger(), "[%s] getNewStream(), ID: %d, stream map size: %d ", + LOG_D((getLogger(), "[%s-%d] getNewStream(), stream map size: %d ", getLogId(), m_uiLastStreamID, m_mapStream.size())); } + if (m_tmIdleBegin) + m_tmIdleBegin = 0; pStream->init(m_uiLastStreamID, this, ubH2_Flags, pSession, &m_priority); pStream->setProtocol(HIOS_PROTO_HTTP2); pStream->setFlag(HIO_FLAG_FLOWCTRL, 1); @@ -1030,7 +1037,7 @@ H2Stream *H2Connection::getNewStream(uint8_t ubH2_Flags) } -void H2Connection::upgradedStream(HioHandler *pSession) +int H2Connection::h2cUpgrade(HioHandler *pSession) { assert(pSession != NULL); H2Stream *pStream = new H2Stream(); @@ -1044,7 +1051,7 @@ void H2Connection::upgradedStream(HioHandler *pSession) setPendingWrite(); getBuf()->append(s_h2sUpgradeResponse, sizeof(s_h2sUpgradeResponse) - 1); sendSettingsFrame(); - pStream->onInitConnected(true); + return pStream->onInitConnected(true); } @@ -1062,16 +1069,13 @@ void H2Connection::recycleStream(StreamMap::iterator it) H2Stream *pH2Stream = it.second(); m_mapStream.erase(it); pH2Stream->close(); - - //TODO: use array for m_dqueStreamRespon - //m_dqueStreamRespon[pH2Stream->getPriority()].remove(pH2Stream); - m_priQue.remove(pH2Stream); + m_priQue[pH2Stream->getPriority()].remove(pH2Stream); if (pH2Stream->getHandler()) pH2Stream->getHandler()->recycle(); if (D_ENABLED(DL_MORE)) { - LOG_D((getLogger(), "[%s] recycleStream(), ID: %d, stream map size: %d " + LOG_D((getLogger(), "[%s-%d] recycleStream(), stream map size: %d " , getLogId(), pH2Stream->getStreamID(), m_mapStream.size())); } //H2StreamPool::recycle( pH2Stream ); @@ -1080,11 +1084,16 @@ void H2Connection::recycleStream(StreamMap::iterator it) -int H2Connection::sendDataFrame(uint32_t uiStreamId, int flag, - IOVec *pIov, int total ) +int H2Connection::sendDataFrame(uint32_t uiStreamId, int flag, + IOVec *pIov, int total) { int ret = 0; - appendCtrlFrameHeader(H2_FRAME_DATA, total, flag, uiStreamId); + H2FrameHeader header(total, H2_FRAME_DATA, flag, uiStreamId); + + if (m_buf.empty() && !getStream()->isWantWrite()) + getStream()->continueWrite(); + + m_buf.append((char *)&header, 9); if (pIov) ret = cacheWritev(*pIov, total); if (ret != -1) @@ -1102,8 +1111,8 @@ int H2Connection::sendFrame8Bytes(H2FrameType type, uint32_t uiStreamId, appendNbo4Bytes(getBuf(), uiVal2); if (D_ENABLED(DL_MORE)) { - LOG_D((getLogger(), "[%s] send %s frame, stream: %d, value: %d" - , getLogId(), getH2FrameName(type), uiVal1, uiVal2)); + LOG_D((getLogger(), "[%s-%d] send %s frame, stream: %d, value: %d" + , getLogId(), uiStreamId, getH2FrameName(type), uiVal1, uiVal2)); } return 0; } @@ -1118,8 +1127,8 @@ int H2Connection::sendFrame4Bytes(H2FrameType type, uint32_t uiStreamId, appendNbo4Bytes(getBuf(), uiVal1); if (D_ENABLED(DL_MORE)) { - LOG_D((getLogger(), "[%s] send %s frame, value: %d", getLogId(), - getH2FrameName(type), uiVal1)); + LOG_D((getLogger(), "[%s-%d] send %s frame, value: %d", getLogId(), + uiStreamId, getH2FrameName(type), uiVal1)); } return 0; } @@ -1132,8 +1141,8 @@ int H2Connection::sendFrame0Bytes(H2FrameType type, unsigned char flags, appendCtrlFrameHeader(type, 0, flags, uiStreamId); if (D_ENABLED(DL_MORE)) { - LOG_D((getLogger(), "[%s] send %s frame, with Flag: %d" - , getLogId(), getH2FrameName(type), flags)); + LOG_D((getLogger(), "[%s-%d] send %s frame, with Flag: %d" + , getLogId(), uiStreamId, getH2FrameName(type), flags)); } return 0; } @@ -1159,13 +1168,13 @@ int H2Connection::sendSettingsFrame() //{0x00, 0x01, 0x00, 0x00, 0x10, 0x00 }, {0x00, 0x03, 0x00, 0x00, 0x00, 0x64 }, {0x00, 0x04, 0x00, 0x01, 0x00, 0x00 }, - //{0x00, 0x05, 0x00, 0x00, 0x40, 0x00 }, + {0x00, 0x05, 0x00, 0x00, 0x40, 0x00 }, //{0x00, 0x06, 0x00, 0x00, 0x40, 0x00 }, }; - getBuf()->guarantee(21); - appendCtrlFrameHeader(H2_FRAME_SETTINGS, 12); - getBuf()->append((char *)s_settings, 12); + getBuf()->guarantee(27); + appendCtrlFrameHeader(H2_FRAME_SETTINGS, 18); + getBuf()->append((char *)s_settings, 18); if (D_ENABLED(DL_MORE)) { LOG_D((getLogger(), @@ -1175,8 +1184,8 @@ int H2Connection::sendSettingsFrame() } m_iFlag |= H2_CONN_FLAG_SETTING_SENT; - sendWindowUpdateFrame( 0, H2_FCW_INIT_SIZE ); - m_iDataInWindow += H2_FCW_INIT_SIZE; + sendWindowUpdateFrame(0, H2_FCW_INIT_SIZE * 3); + m_iDataInWindow += H2_FCW_INIT_SIZE * 3; return 0; } @@ -1191,7 +1200,7 @@ int H2Connection::processPingFrame(H2FrameHeader *pHeader) //doGoAway(H2_ERROR_PROTOCOL_ERROR); if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] invalid PING frame id %d", - getLogId(), pHeader->getStreamId())); + getLogId(), pHeader->getStreamId())); return LS_FAIL; } @@ -1203,12 +1212,12 @@ int H2Connection::processPingFrame(H2FrameHeader *pHeader) { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] unexpected PING frame, %.*s", - getLogId(), 8, payload)); + getLogId(), 8, payload)); return 0; } return sendPingFrame(H2_FLAG_ACK, payload); } - + gettimeofday(&CurTime, NULL); msec = (CurTime.tv_sec - m_timevalPing.tv_sec) * 1000; msec += (CurTime.tv_usec - m_timevalPing.tv_usec) / 1000; @@ -1241,19 +1250,13 @@ int H2Connection::flush() } -void H2Connection::setPendingWrite() -{ - if (isEmpty()) - getStream()->continueWrite(); -} - int H2Connection::onCloseEx() { if (getStream()->isReadyToRelease()) return 0; if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] H2Connection::onCloseEx() ", getLogId())); - + getStream()->tobeClosed(); releaseAllStream(); return 0; @@ -1333,40 +1336,47 @@ int H2Connection::timerRoutine() } if (m_mapStream.size() == 0) { + if (m_tmIdleBegin == 0) - m_tmIdleBegin = time(NULL); - else + m_tmIdleBegin = DateTime::s_curTime; + else { int idle = DateTime::s_curTime - m_tmIdleBegin; if (idle > HttpServerConfig::getInstance().getSpdyKeepaliveTimeout()) + { + if (D_ENABLED(DL_LESS)) + LOG_D((getLogger(), "[%s] Session idle for %d seconds, GOAWAY.", + getLogId(), idle)); + doGoAway(H2_ERROR_NO_ERROR); + } } } else { if (stuckRead > 0) { - if ( m_timevalPing.tv_sec == 0) + if (m_timevalPing.tv_sec == 0) { if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] send PING to check if peer is still alive.", - getLogId())); + getLogId())); sendPingFrame(0, (uint8_t *)"RUALIVE?"); m_timevalPing.tv_sec = DateTime::s_curTime; m_timevalPing.tv_usec = DateTime::s_curTimeUs; - + } - else if (DateTime::s_curTime - m_timevalPing.tv_sec > 20) + else if (DateTime::s_curTime - m_timevalPing.tv_sec > 20) { - doGoAway(H2_ERROR_PROTOCOL_ERROR); if (D_ENABLED(DL_LESS)) LOG_D((getLogger(), "[%s] PING timeout.", - getLogId())); + getLogId())); + doGoAway(H2_ERROR_PROTOCOL_ERROR); } } m_tmIdleBegin = 0; } - + return 0; } @@ -1375,7 +1385,7 @@ int H2Connection::timerRoutine() #define MAX_LINE_COUNT_OF_MULTILINE_HEADER 100 int H2Connection::encodeHeaders(HttpRespHeaders *pRespHeaders, - unsigned char *buf, int maxSize) + unsigned char *buf, int maxSize) { unsigned char *pCur = buf; unsigned char *pBufEnd = pCur + maxSize; @@ -1401,17 +1411,23 @@ int H2Connection::encodeHeaders(HttpRespHeaders *pRespHeaders, if (count <= 0) continue; + char *p = key; + char *pKeyEnd = key + keyLen; + //to lowercase + while (p < pKeyEnd) + { + *p = tolower(*p); + ++p; + } + if (keyLen + 8 > pBufEnd - pCur) return LS_FAIL; pIov = iov; pIovEnd = &iov[count]; for (pIov = iov; pIov < pIovEnd; ++pIov) - { - StringTool::strLower(key, key, keyLen); pCur = m_hpack.encHeader(pCur, pBufEnd, key, keyLen, (char *)pIov->iov_base, pIov->iov_len, 0); - } } return pCur - buf;; @@ -1419,11 +1435,11 @@ int H2Connection::encodeHeaders(HttpRespHeaders *pRespHeaders, int H2Connection::sendRespHeaders(HttpRespHeaders *pRespHeaders, - uint32_t uiStreamID) + uint32_t uiStreamID, uint8_t flag) { if (D_ENABLED(DL_MORE)) { - LOG_D((getLogger(), "[%s] sendRespHeaders(), ID: %d" + LOG_D((getLogger(), "[%s-%d] sendRespHeaders()" , getLogId(), uiStreamID)); } @@ -1433,8 +1449,7 @@ int H2Connection::sendRespHeaders(HttpRespHeaders *pRespHeaders, return LS_FAIL; getBuf()->guarantee(rc + 9); - appendCtrlFrameHeader(H2_FRAME_HEADERS, rc, H2_FLAG_END_HEADERS, - uiStreamID); //H2_FLAG_END_STREAM + appendCtrlFrameHeader(H2_FRAME_HEADERS, rc, flag, uiStreamID); // getBuf()->append((const char *)achHdrBuf, rc); return 0; } @@ -1442,9 +1457,18 @@ int H2Connection::sendRespHeaders(HttpRespHeaders *pRespHeaders, void H2Connection::add2PriorityQue(H2Stream *pH2Stream) { - //TODO: use array for m_dqueStreamRespon - //m_dqueStreamRespon[pH2Stream->getPriority()].append(pH2Stream); - m_priQue.append(pH2Stream); + if (pH2Stream->next()) + pH2Stream->remove(); + if (D_ENABLED(DL_MORE)) + { + LOG_D((getLogger(), "[%s-%d] add to priority queue: %d", + getLogId(), pH2Stream->getStreamID(), pH2Stream->getPriority())); + } + + m_priQue[pH2Stream->getPriority()].append(pH2Stream); + m_iFlag |= H2_CONN_FLAG_WAIT_PROCESS; + if (m_iCurDataOutWindow > 0 && !getStream()->isWantWrite()) + getStream()->continueWrite(); } @@ -1453,13 +1477,14 @@ int H2Connection::onWriteEx() H2Stream *pH2Stream = NULL; int wantWrite = 0; + if (D_ENABLED(DL_MORE)) { - LOG_D((getLogger(), "[%s] onWriteEx() state: %d, output buffer size=%d\n ", - getLogId(), m_iState, getBuf()->size())); + LOG_D((getLogger(), "[%s] onWriteEx() state: %d, output buffer size=%d, Data Out Window: %d", + getLogId(), m_iState, getBuf()->size(), m_iCurDataOutWindow)); } - if ( getBuf()->size() > 32768 ) - { + if (getBuf()->size() > 32768) + { flush(); if (!isEmpty()) return 0; @@ -1467,55 +1492,41 @@ int H2Connection::onWriteEx() if (getStream()->canWrite() & HIO_FLAG_BUFF_FULL) return 0; - -//TODO: use array for m_dqueStreamRespon -// for (int i = 0; i < H2_STREAM_PRIORITYS; ++i) -// { -// if (m_dqueStreamRespon[i].empty()) -// continue; -// DLinkedObj *it = m_dqueStreamRespon[i].begin();//H2Stream* -// DLinkedObj *itn; -// for (; it != m_dqueStreamRespon[i].end();) -// { -// pH2Stream = (H2Stream *)it; -// itn = it->next(); -// if (pH2Stream->isWantWrite()) -// { -// pH2Stream->onWrite(); -// if (pH2Stream->isWantWrite() && (pH2Stream->getWindowOut() > 0)) -// ++wantWrite; -// } -// if (pH2Stream->getState() == HIOS_DISCONNECTED) -// recycleStream(pH2Stream->getStreamID()); -// it = itn; -// } -// if (getStream()->canWrite() & HIO_FLAG_BUFF_FULL) -// return 0; -// } - -// if (m_dqueStreamRespon.empty()) -// return 0; - - DLinkedObj *it = m_priQue.begin();//H2Stream* - DLinkedObj *itn; - for (; it != m_priQue.end() && m_iCurDataOutWindow > 0;) + for (int i = 0; i < H2_STREAM_PRIORITYS && m_iCurDataOutWindow > 0; ++i) { - pH2Stream = (H2Stream *)it; - itn = it->next(); - if (pH2Stream->isWantWrite()) + if (D_ENABLED(DL_MORE)) { - pH2Stream->onWrite(); - if (pH2Stream->isWantWrite() && (pH2Stream->getWindowOut() > 0)) - ++wantWrite; + LOG_D((getLogger(), "[%s] processing priority queue: %d", + getLogId(), i)); } - if (pH2Stream->getState() != HIOS_CONNECTED) - recycleStream(pH2Stream->getStreamID()); - it = itn; + if (m_priQue[i].empty()) + continue; + DLinkedObj *it = m_priQue[i].begin();//H2Stream* + DLinkedObj *itn; + + for (; it != m_priQue[i].end() && m_iCurDataOutWindow > 0;) + { + pH2Stream = (H2Stream *)it; + itn = it->next(); + if (pH2Stream->isWantWrite()) + { + pH2Stream->onWrite(); + if (pH2Stream->isWantWrite() && (pH2Stream->getWindowOut() > 0)) + ++wantWrite; + } + if (pH2Stream->getState() != HIOS_CONNECTED) + recycleStream(pH2Stream->getStreamID()); + it = itn; + } + if (getStream()->canWrite() & HIO_FLAG_BUFF_FULL) + return 0; + if (wantWrite > 0) + break; } if (!isEmpty()) flush(); - + if ((wantWrite == 0 || m_iCurDataOutWindow <= 0) && isEmpty()) getStream()->suspendWrite(); return 0; @@ -1526,7 +1537,7 @@ void H2Connection::recycle() { if (D_ENABLED(DL_MORE)) LOG_D((getLogger(), "[%s] H2Connection::recycle()", getLogId())); - if ( m_mapStream.size() > 0 ) + if (m_mapStream.size() > 0) releaseAllStream(); detachStream(); delete this; diff --git a/src/spdy/h2connection.h b/src/spdy/h2connection.h index 02b3eebc7..0a2535fb2 100644 --- a/src/spdy/h2connection.h +++ b/src/spdy/h2connection.h @@ -39,8 +39,9 @@ #define H2_CONN_FLAG_CONFIRMED (1<<4) #define H2_CONN_FLAG_FLOW_CTRL (1<<5) #define H2_CONN_HEADERS_START (1<<6) +#define H2_CONN_FLAG_WAIT_PROCESS (1<<7) -#define H2_STREAM_PRIORITYS (256 + 1) +#define H2_STREAM_PRIORITYS (8) class H2Stream; @@ -69,7 +70,7 @@ class H2Connection: public HioHandler, public BufferedOS //Following functions are just placeholder //Placeholder - void init(HiosProtocol ver); + int init(); int onInitConnected(); int onTimerEx(); @@ -90,8 +91,9 @@ class H2Connection: public HioHandler, public BufferedOS int32_t getPeerMaxFrameSize() const { return m_iPeerMaxFrameSize; } - - int sendRespHeaders(HttpRespHeaders *pRespHeaders, uint32_t uiStreamID); + + int sendRespHeaders(HttpRespHeaders *pRespHeaders, uint32_t uiStreamID, + uint8_t flag); int sendWindowUpdateFrame(uint32_t id, int32_t delta) { return sendFrame4Bytes(H2_FRAME_WINDOW_UPDATE, id, delta); } @@ -106,15 +108,26 @@ class H2Connection: public HioHandler, public BufferedOS return sendFrame0Bytes(H2_FRAME_DATA, H2_FLAG_END_STREAM, uiStreamID); } - int sendDataFrame(uint32_t uiStreamID, int flag, IOVec *pIov, int total ); - - void upgradedStream(HioHandler *pSession); + int sendDataFrame(uint32_t uiStreamID, int flag, IOVec *pIov, int total); + + int h2cUpgrade(HioHandler *pSession); void recycleStream(uint32_t uiStreamID); + uint16_t getEvents() + { return getStream()->getEvents(); } + int isFromLocalAddr() const + { return getStream()->isFromLocalAddr(); } + NtwkIOLink *getNtwkIoLink(); - void setPendingWrite(); + static HioHandler *get(); + + void setPendingWrite() + { + if (isEmpty() && !getStream()->isWantWrite()) + getStream()->continueWrite(); + } private: typedef THash< H2Stream * > StreamMap; @@ -131,7 +144,8 @@ class H2Connection: public HioHandler, public BufferedOS int parseHeaders(char *pHeader, int ilength, int &NVPairCnt); H2Stream *getNewStream(uint8_t ubH2_Flags); - int decodeHeaders(unsigned char *src, int length, unsigned char iHeaderFlag); + int decodeHeaders(unsigned char *src, int length, + unsigned char iHeaderFlag); int processPriorityFrame(H2FrameHeader *pHeader); int processSettingFrame(H2FrameHeader *pHeader); int processHeadersFrame(H2FrameHeader *pHeader); @@ -144,13 +158,12 @@ class H2Connection: public HioHandler, public BufferedOS int processContinuationFrame(H2FrameHeader *pHeader); int processReqHeader(unsigned char iHeaderFlag); - + int sendPingFrame(uint8_t flags, uint8_t *pPayload); int sendSettingsFrame(); int sendGoAwayFrame(H2ErrorCode status); int doGoAway(H2ErrorCode status); - int appendCtrlFrameHeader(H2FrameType type, uint32_t len, unsigned char flags = 0, uint32_t uiStreamID = 0) { @@ -163,22 +176,26 @@ class H2Connection: public HioHandler, public BufferedOS uint32_t uiVal1, uint32_t uiVal2); int sendFrame4Bytes(H2FrameType type, uint32_t uiStreamId, uint32_t uiVal2); - int sendFrame0Bytes(H2FrameType type, uint8_t flags, uint32_t uiStreamId); + int sendFrame0Bytes(H2FrameType type, uint8_t flags, + uint32_t uiStreamId); void recycleStream(StreamMap::iterator it); - int appendReqHeaders(H2Stream *arg1, char *method = NULL, int methodLen = 0, + int appendReqHeaders(H2Stream *arg1, char *method = NULL, + int methodLen = 0, char *uri = NULL, int uriLen = 0); - int decodeData(unsigned char *pSrc, unsigned char *bufEnd, + int decodeData(unsigned char *pSrc, unsigned char *bufEnd, char *method, int *methodLen, char **uri, int *uriLen, - int *contentLen ); + int *contentLen); void skipRemainData(); int encodeHeaders(HttpRespHeaders *pRespHeaders, unsigned char *buf, - int maxSize); + int maxSize); int verifyClientPreface(); int parseFrame(); + + private: LoopBuf m_bufInput; AutoBuf m_bufInflate; @@ -189,14 +206,12 @@ class H2Connection: public HioHandler, public BufferedOS uint32_t m_tmLastFrameIn; struct timeval m_timevalPing; - //TODO: use array for m_dqueStreamRespon - //DLinkQueue m_dqueStreamRespon[H2_STREAM_PRIORITYS]; - DLinkQueue m_priQue; - + DLinkQueue m_priQue[H2_STREAM_PRIORITYS]; StreamMap m_mapStream; short m_iState; short m_iFlag; Priority_st m_priority; + char m_bVersion; int32_t m_iCurDataOutWindow; int32_t m_iCurInBytesToUpdate; @@ -210,7 +225,6 @@ class H2Connection: public HioHandler, public BufferedOS int32_t m_tmIdleBegin; int32_t m_iaH2HeaderMem[10]; H2FrameHeader *m_pCurH2Header; - private: Hpack m_hpack; diff --git a/src/spdy/h2protocol.h b/src/spdy/h2protocol.h index 05de33c92..19014dc04 100644 --- a/src/spdy/h2protocol.h +++ b/src/spdy/h2protocol.h @@ -52,7 +52,6 @@ enum H2ControlFlags { H2_CTRL_FLAG_NONE = 0, H2_CTRL_FLAG_FIN = 1, - H2_CTRL_FLAG_UNIDIRECTIONAL = 2 }; // Flags on the SETTINGS control frame. diff --git a/src/spdy/h2stream.cpp b/src/spdy/h2stream.cpp index 07bba65ba..7f05f9f5e 100644 --- a/src/spdy/h2stream.cpp +++ b/src/spdy/h2stream.cpp @@ -18,12 +18,12 @@ #include "h2stream.h" #include "h2connection.h" -#include "h2protocol.h" +#include #include #include -#include #include +#include "lsdef.h" H2Stream::H2Stream() : m_uiStreamID(0) @@ -57,27 +57,28 @@ int H2Stream::init(uint32_t StreamID, H2Connection *pH2Conn, uint8_t flags, clearLogId(); setState(HIOS_CONNECTED); - setFlag((flags & (H2_CTRL_FLAG_FIN | H2_CTRL_FLAG_UNIDIRECTIONAL)), 1); + setFlag(flags & H2_CTRL_FLAG_FIN, 1); m_bufIn.clear(); m_uiStreamID = StreamID; m_iWindowOut = pH2Conn->getStreamOutInitWindowSize(); m_iWindowIn = pH2Conn->getStreamInInitWindowSize(); -//We disable Priority right now. -// if (pPriority) -// { -// //FIXME:need an algrithem to compute the priority -// m_iPriority = pPriority->m_weight; -// } -// else -// m_iPriority = 0; + int pri = HIO_PRIORITY_HTML; + if (pPriority) + { + if (pPriority->m_weight <= 32) + pri = (32 - pPriority->m_weight) >> 2; + else + pri = (256 - pPriority->m_weight) >> 5; + } + setPriority(pri); m_pH2Conn = pH2Conn; if (D_ENABLED(DL_LESS)) { - LOG_D((getLogger(), "[%s] H2Stream::init(), id: %d. ", - getLogId(), StreamID)); + LOG_D((getLogger(), "[%s] H2Stream::init(), id: %d, priority: %d. ", + getLogId(), StreamID, pri)); } return 0; } @@ -91,7 +92,9 @@ int H2Stream::onInitConnected(bool bUpgraded) if (isWantRead()) getHandler()->onReadEx(); if (isWantWrite()) - getHandler()->onWriteEx(); + if (next() == NULL) + m_pH2Conn->add2PriorityQue(this); + //getHandler()->onWriteEx(); return 0; } @@ -111,9 +114,9 @@ int H2Stream::appendReqData(char *pData, int len, uint8_t flags) m_iWindowIn -= len; //Note: H2_CTRL_FLAG_FIN is directly mapped to HIO_FLAG_PEER_SHUTDOWN // H2_CTRL_FLAG_UNIDIRECTIONAL is directly mapped to HIO_FLAG_LOCAL_SHUTDOWN - if (flags & (H2_CTRL_FLAG_FIN | H2_CTRL_FLAG_UNIDIRECTIONAL)) + if (flags & H2_CTRL_FLAG_FIN) { - setFlag(flags & (H2_CTRL_FLAG_FIN | H2_CTRL_FLAG_UNIDIRECTIONAL), 1); + setFlag(H2_CTRL_FLAG_FIN, 1); if (m_iContentLen != -1 && m_iContentLen != m_iContentRead) return LS_FAIL; } @@ -184,6 +187,16 @@ void H2Stream::onTimer() } +uint16_t H2Stream::getEvents() const +{ + return m_pH2Conn->getEvents(); +} + + +int H2Stream::isFromLocalAddr() const +{ return m_pH2Conn->isFromLocalAddr(); } + + NtwkIOLink *H2Stream::getNtwkIoLink() { return m_pH2Conn->getNtwkIoLink(); @@ -221,7 +234,7 @@ int H2Stream::close() // getHandler()->recycle(); // setHandler( NULL ); //} - m_pH2Conn->recycleStream( m_uiStreamID ); + m_pH2Conn->recycleStream(m_uiStreamID); return 0; } @@ -229,9 +242,7 @@ int H2Stream::close() int H2Stream::flush() { if (D_ENABLED(DL_LESS)) - { LOG_D((getLogger(), "[%s] H2Stream::flush()", getLogId())); - } return LS_DONE; } @@ -351,9 +362,9 @@ int H2Stream::sendData(IOVec *pIov, int total) if (D_ENABLED(DL_LESS)) { LOG_D((getLogger(), "[%s] sent: %lld, current window: %d", - getLogId(), (uint64_t)getBytesSent(), m_iWindowOut)); + getLogId(), (uint64_t)getBytesSent(), m_iWindowOut)); } - + if (m_iWindowOut <= 0) setFlag(HIO_FLAG_BUFF_FULL, 1); } @@ -361,13 +372,27 @@ int H2Stream::sendData(IOVec *pIov, int total) } -int H2Stream::sendRespHeaders(HttpRespHeaders *pHeaders) +int H2Stream::sendRespHeaders(HttpRespHeaders *pHeaders, int isNoBody) { + uint8_t flag = H2_FLAG_END_HEADERS; if (getState() == HIOS_DISCONNECTED) return LS_FAIL; - - m_pH2Conn->add2PriorityQue(this); - return m_pH2Conn->sendRespHeaders(pHeaders, m_uiStreamID); + if (isNoBody) + { + if (D_ENABLED(DL_LESS)) + { + LOG_D((getLogger(), "[%s] No response body, set END_STREAM.", + getLogId())); + } + flag |= H2_FLAG_END_STREAM; + setState(HIOS_SHUTDOWN); + } + else + { + if (next() == NULL) + m_pH2Conn->add2PriorityQue(this); + } + return m_pH2Conn->sendRespHeaders(pHeaders, m_uiStreamID, flag); } diff --git a/src/spdy/h2stream.h b/src/spdy/h2stream.h index 6379c8668..358bd0455 100644 --- a/src/spdy/h2stream.h +++ b/src/spdy/h2stream.h @@ -59,7 +59,7 @@ class H2Stream: public DLinkedObj, public HioStream void switchWriteToRead() {}; int flush(); - int sendRespHeaders(HttpRespHeaders *pHeaders); + int sendRespHeaders(HttpRespHeaders *pHeaders, int isNoBody); void suspendRead() { setFlag(HIO_FLAG_WANT_READ, 0); } @@ -71,12 +71,14 @@ class H2Stream: public DLinkedObj, public HioStream void continueWrite(); void onTimer(); - + int isStuckOnRead() { return (isWantRead() && DateTime::s_curTime - getActiveTime() >= 5); } + uint16_t getEvents() const; + int isFromLocalAddr() const; virtual NtwkIOLink *getNtwkIoLink(); int shutdown(); @@ -112,7 +114,7 @@ class H2Stream: public DLinkedObj, public HioStream uint8_t getReqHeaderEnd() { return m_reqHeaderEnd; } void setReqHeaderEnd(uint8_t v) { m_reqHeaderEnd = v; } - void setContentlen( int32_t len ) { m_iContentLen = len; } + void setContentlen(int32_t len) { m_iContentLen = len; } private: bool operator==(const H2Stream &other) const; diff --git a/src/spdy/hpack.cpp b/src/spdy/hpack.cpp index ba50abb2a..5272bd5ec 100644 --- a/src/spdy/hpack.cpp +++ b/src/spdy/hpack.cpp @@ -16,7 +16,16 @@ * along with this program. If not, see http://www.gnu.org/licenses/. * *****************************************************************************/ #include "hpack.h" +#include #include +#include + +#if defined( __x86_64 )||defined( __x86_64__ ) +#define XXH XXH64 +#else +#define XXH XXH32 +#endif + #define LS_STR_TO_IOVEC(a) (a), (sizeof(a) -1) #define MAX_HEADER_LENGTH 4096 @@ -5220,7 +5229,7 @@ HpackHuffDecode_t HuffmanCode::m_HpackHuffDecode_t[256][16] = }; size_t HuffmanCode::calcHuffmanEncBufSize(const unsigned char *src, - const unsigned char *src_end) + const unsigned char *src_end) { size_t bufSizeBits = 0; while (src < src_end) @@ -5229,7 +5238,8 @@ size_t HuffmanCode::calcHuffmanEncBufSize(const unsigned char *src, } -int HuffmanCode::huffmanEnc(const unsigned char *src, const unsigned char *src_end, +int HuffmanCode::huffmanEnc(const unsigned char *src, + const unsigned char *src_end, unsigned char *dst, int dst_len) { unsigned char *p_src = (unsigned char *)src; @@ -5316,7 +5326,7 @@ int HuffmanCode::huffmanDec(unsigned char *src, int src_len, void DynTblEntry::init(char *name, uint32_t name_len, char *val, - uint32_t val_len, uint8_t stxTabId) + uint32_t val_len, uint8_t stxTabId) { if (m_valLen && m_val) delete []m_val; @@ -5361,8 +5371,9 @@ int HpackDynTbl::cmpName(const void *pVal1, const void *pVal2) { DynTblEntry *pEntry1 = (DynTblEntry *)pVal1; DynTblEntry *pEntry2 = (DynTblEntry *)pVal2; - if (pEntry1->getNameLen() == pEntry2->getNameLen() - && memcmp(pEntry1->getName(), pEntry2->getName(), pEntry1->getNameLen()) == 0) + if (pEntry1->getNameLen() == pEntry2->getNameLen() + && memcmp(pEntry1->getName(), pEntry2->getName(), + pEntry1->getNameLen()) == 0) return 0; else return 1; @@ -5374,9 +5385,10 @@ int HpackDynTbl::cmpNameVal(const void *pVal1, const void *pVal2) { DynTblEntry *pEntry1 = (DynTblEntry *)pVal1; DynTblEntry *pEntry2 = (DynTblEntry *)pVal2; - if (pEntry1->getValueLen() == pEntry2->getValueLen() - && memcmp(pEntry1->getValue(), pEntry2->getValue(), pEntry1->getValueLen()) == 0) - return 0; + if (pEntry1->getValueLen() == pEntry2->getValueLen() + && memcmp(pEntry1->getValue(), pEntry2->getValue(), + pEntry1->getValueLen()) == 0) + return 0; } return 1; } @@ -5388,7 +5400,8 @@ HpackDynTbl::HpackDynTbl() m_maxCapacity = INITIAL_DYNAMIC_TABLE_SIZE; m_nextFlowId = 0; m_pNameHashT = new GHash(15, HpackDynTbl::hfName, HpackDynTbl::cmpName); - m_pNameValueHashT = new GHash(15, HpackDynTbl::hfNameVal, HpackDynTbl::cmpNameVal); + m_pNameValueHashT = new GHash(15, HpackDynTbl::hfNameVal, + HpackDynTbl::cmpNameVal); } HpackDynTbl::~HpackDynTbl() @@ -5396,14 +5409,14 @@ HpackDynTbl::~HpackDynTbl() int count = getEntryCount(); for (int i = count - 1; i >= 0; --i) delete getEntryInternal(i); - + if (m_pNameHashT) { m_pNameHashT->clear(); delete m_pNameHashT; m_pNameHashT = NULL; } - if(m_pNameValueHashT) + if (m_pNameValueHashT) { m_pNameValueHashT->clear(); delete m_pNameValueHashT; @@ -5435,12 +5448,12 @@ void HpackDynTbl::reset() * return -1 for out of memory error */ int HpackDynTbl::getDynTabId(char *name, uint16_t name_len, char *value, - uint16_t value_len, int &val_matched, uint8_t stxTabId) + uint16_t value_len, int &val_matched, uint8_t stxTabId) { int id = 0; val_matched = 0; DynTblEntry *pTmpEntry = new DynTblEntry(name, name_len, - value, value_len, stxTabId); + value, value_len, stxTabId); if (pTmpEntry == NULL) return -1; @@ -5449,14 +5462,16 @@ int HpackDynTbl::getDynTabId(char *name, uint16_t name_len, char *value, if (iter != m_pNameValueHashT->end()) { val_matched = 1; - id = m_nextFlowId - (uint32_t)(long)iter->second() + HPACK_STATIC_TABLE_SIZE; + id = m_nextFlowId - (uint32_t)(long)iter->second() + + HPACK_STATIC_TABLE_SIZE; } else if (stxTabId == 0) //If have stxTabId, so needn't go further { //May have many entries, use the first matched one is all right iter = m_pNameHashT->find((void *)pTmpEntry); if (iter != m_pNameHashT->end()) - id = m_nextFlowId - (uint32_t)(long)iter->second() + HPACK_STATIC_TABLE_SIZE; + id = m_nextFlowId - (uint32_t)(long)iter->second() + + HPACK_STATIC_TABLE_SIZE; } delete pTmpEntry; @@ -5475,7 +5490,7 @@ void HpackDynTbl::removeNameHashTEntry(DynTblEntry *pEntry) { GHash::iterator iter; iter = m_pNameHashT->find((void *)pEntry); - if (iter != m_pNameHashT->end() + if (iter != m_pNameHashT->end() && (uint32_t)(long)iter->second() == m_nextFlowId - getEntryCount()) m_pNameHashT->erase(iter); } @@ -5493,11 +5508,12 @@ void HpackDynTbl::popEntry() //remove oldest /**** * the new one will be append to the end of the loopbuf, so the index need to be paied more attention. */ -void HpackDynTbl::pushEntry(char *name, uint16_t name_len, char *val, uint16_t val_len, - uint32_t nameIndex) +void HpackDynTbl::pushEntry(char *name, uint16_t name_len, char *val, + uint16_t val_len, + uint32_t nameIndex) { DynTblEntry *pEntry = new DynTblEntry(name, name_len, val, - val_len, nameIndex); + val_len, nameIndex); m_loopbuf.append((char *)(&pEntry), ENTRYPSIZE); m_curCapacity += pEntry->getEntrySize(); m_pNameHashT->update(pEntry, (void *)(long)m_nextFlowId); @@ -5517,7 +5533,7 @@ void HpackDynTbl::removeOverflowEntries() unsigned char *Hpack::encInt(unsigned char *dst, uint32_t value, uint32_t prefix_bits) { - if (value < (uint32_t)(1 << prefix_bits) -1) + if (value < (uint32_t)(1 << prefix_bits) - 1) *dst++ |= value; else { @@ -5536,7 +5552,7 @@ unsigned char *Hpack::encInt(unsigned char *dst, uint32_t value, //https://tools.ietf.org/html/draft-ietf-httpbis-header-compression-12#section-5.1 int Hpack::decInt(unsigned char *&src, const unsigned char *src_end, - uint32_t prefix_bits, uint32_t& value) + uint32_t prefix_bits, uint32_t &value) { uint32_t B, M; uint8_t prefix_max = (1 << prefix_bits) - 1; @@ -5558,7 +5574,8 @@ int Hpack::decInt(unsigned char *&src, const unsigned char *src_end, M += 7; if (M > 31) break; //Something wrong, the result will be more than 2 << 31; - } while ((B & 0x80) == 0x80); + } + while ((B & 0x80) == 0x80); return 0; } @@ -5570,8 +5587,6 @@ int Hpack::encStr(unsigned char *dst, size_t dst_len, unsigned char buf[MAX_HEADER_LENGTH]; int rc = HuffmanCode::huffmanEnc(str, str + str_len, buf, MAX_HEADER_LENGTH); - int realLen = -1; - bool useHuffmenCode; /* * Check if need huffman encodeing or not @@ -5580,30 +5595,19 @@ int Hpack::encStr(unsigned char *dst, size_t dst_len, */ if (rc > 0 && (size_t)rc < dst_len && (size_t)rc <= str_len) { - useHuffmenCode = true; *p_dst = 0x80; - realLen = rc; + str_len = rc; + str = buf; } else if (str_len < dst_len) - { - useHuffmenCode = false; *p_dst = 0x00; - realLen = str_len; - } - - if (realLen != -1) - { - unsigned char *tmp = encInt(p_dst, realLen, 7); - if (tmp - p_dst + realLen <= (int)dst_len) - { - p_dst = tmp; - memcpy(p_dst, (useHuffmenCode ? buf : str), realLen); - p_dst += realLen; - return p_dst - dst; - } - } + else + return LS_FAIL; //No enough space - return LS_FAIL; //No enough space + p_dst = encInt(p_dst, str_len, 7); + memcpy(p_dst, str, str_len); + p_dst += str_len; + return p_dst - dst; } @@ -5618,7 +5622,7 @@ int Hpack::decStr(unsigned char *dst, size_t dst_len, unsigned char *&src, uint32_t len; if (0 != decInt(src, src_end, 7, len)) return -2; //wrong int - + int ret = 0; if (src + len > src_end) return -2; //wrong int @@ -5631,7 +5635,7 @@ int Hpack::decStr(unsigned char *dst, size_t dst_len, unsigned char *&src, ret = HuffmanCode::huffmanDec(src, len, dst, dst_len, lowerCase); if (ret < 0) return -3; //Wrong code - + src += len; } else @@ -5643,7 +5647,7 @@ int Hpack::decStr(unsigned char *dst, size_t dst_len, unsigned char *&src, if (lowerCase) { unsigned char *psrc = src; - for (uint32_t i=0; i 0 && g_HpackStxTab[i].val_len == val_len + if (i > 0 && g_HpackStxTab[i].val_len == val_len && g_HpackStxTab[i].name_len == name_len && memcmp(val, g_HpackStxTab[i].val, val_len) == 0 && memcmp(name, g_HpackStxTab[i].name, name_len) == 0) @@ -5793,9 +5797,9 @@ uint8_t Hpack::getStxTabId(char *name, uint16_t name_len, char *val, i = 14; //accept-charset break; case 15: - if ( *(name + 7) == 'l') - i = 16; //accept-language, - else + if (*(name + 7) == 'l') + i = 16; //accept-language, + else i = 15;// accept-encoding break; case 27: @@ -5815,7 +5819,7 @@ uint8_t Hpack::getStxTabId(char *name, uint16_t name_len, char *val, i = 30; //content-type break; case 13: - if ( *(name + 1) == 'a') + if (*(name + 1) == 'a') i = 23; //cache-control else i = 29; //content-range @@ -5918,20 +5922,20 @@ uint8_t Hpack::getStxTabId(char *name, uint16_t name_len, char *val, case 'r': switch (*(name + 4)) { - case 'e': - if (name_len == 5) - i = 49; //range - else - i = 51; //refresh - break; - case 'r': - i = 50; //referer - break; - case 'y': - i = 52; //retry-after - break; - default: - break; + case 'e': + if (name_len == 5) + i = 49; //range + else + i = 51; //refresh + break; + case 'r': + i = 50; //referer + break; + case 'y': + i = 52; //retry-after + break; + default: + break; } break; case 's': @@ -5957,7 +5961,7 @@ uint8_t Hpack::getStxTabId(char *name, uint16_t name_len, char *val, i = 57; //user-agent break; case 'v': - if (name_len ==4) + if (name_len == 4) i = 58; else i = 59; @@ -5968,8 +5972,8 @@ uint8_t Hpack::getStxTabId(char *name, uint16_t name_len, char *val, default: break; } - - if (i >= 0 + + if (i >= 0 && g_HpackStxTab[i].name_len == name_len && memcmp(name, g_HpackStxTab[i].name, name_len) == 0) return i + 1; @@ -5988,7 +5992,7 @@ unsigned char *Hpack::encHeader(unsigned char *dst, unsigned char *dstEnd, int val_matched = 0; int rc; uint8_t stxTabId = getStxTabId(name, nameLen, value, valueLen, - val_matched); + val_matched); //If both name and value matched if (val_matched == 1) @@ -6000,7 +6004,7 @@ unsigned char *Hpack::encHeader(unsigned char *dst, unsigned char *dstEnd, val_matched = 0; int dynTblId = getRespDynTbl().getDynTabId(name, nameLen, - value, valueLen, val_matched, stxTabId); + value, valueLen, val_matched, stxTabId); if (val_matched == 1) { *dst = 0x80; @@ -6013,7 +6017,7 @@ unsigned char *Hpack::encHeader(unsigned char *dst, unsigned char *dstEnd, * we can use (stxTabId + dynTblId) to choose either value. */ assert(dynTblId == 0 || stxTabId == 0); - + //indexedType: 0, Add, 1,: without, 2: never char indexedPrefixNumber[] = {0x40, 0x00, 0x10}; if (stxTabId + dynTblId > 0) @@ -6037,7 +6041,7 @@ unsigned char *Hpack::encHeader(unsigned char *dst, unsigned char *dstEnd, if (indexedType == 0) getRespDynTbl().pushEntry(name, nameLen, value, valueLen, - stxTabId); + stxTabId); return dst; } @@ -6045,7 +6049,8 @@ unsigned char *Hpack::encHeader(unsigned char *dst, unsigned char *dstEnd, //src will be changed //return 1: OK, 0: end, -1: failed. -int Hpack::decHeader(unsigned char *&src, unsigned char *srcEnd, AutoBuf &nameValBuf, +int Hpack::decHeader(unsigned char *&src, unsigned char *srcEnd, + AutoBuf &nameValBuf, uint16_t &name_len, uint16_t &val_len) { if (src == srcEnd) @@ -6080,15 +6085,11 @@ int Hpack::decHeader(unsigned char *&src, unsigned char *srcEnd, AutoBuf &nameVa indexedType = 0; } else if (*src == 0x40) //custmized //0100 0000 - { indexedType = 0; - } //Never indexed else if (*src == 0x10) //00010000 - { indexedType = 2; - } else if ((*src & 0xf0) == 0x10) //0001 xxxx { @@ -6100,9 +6101,7 @@ int Hpack::decHeader(unsigned char *&src, unsigned char *srcEnd, AutoBuf &nameVa //without indexed else if (*src == 0x00) //0000 0000 - { indexedType = 1; - } else // 0000 xxxx { @@ -6112,14 +6111,14 @@ int Hpack::decHeader(unsigned char *&src, unsigned char *srcEnd, AutoBuf &nameVa indexedType = 1; } - //huffman encode at most compression ratio is 0.625, + //huffman encode at most compression ratio is 0.625, // add 30 to handle the longest static table name //So that in next dyn table checking, should re-chek int enoughSpaceLen = (srcEnd - src) * 2 + 30; if (nameValBuf.available() < enoughSpaceLen) nameValBuf.grow(enoughSpaceLen); nameValBuf.clear(); - + char *name = nameValBuf.begin(); if (index > 0) { @@ -6141,14 +6140,14 @@ int Hpack::decHeader(unsigned char *&src, unsigned char *srcEnd, AutoBuf &nameVa else { DynTblEntry *pRespEntry = getReqDynTbl().getEntry( - index); + index); if (pRespEntry == NULL) return LS_FAIL; - //If the dyn table have a long name and value, this may break the + //If the dyn table have a long name and value, this may break the //prevoius length checking, so need to check it again - enoughSpaceLen = (srcEnd - src) * 2 + pRespEntry->getNameLen() - + pRespEntry->getValueLen(); + enoughSpaceLen = (srcEnd - src) * 2 + pRespEntry->getNameLen() + + pRespEntry->getValueLen(); if (nameValBuf.available() < enoughSpaceLen) { nameValBuf.grow(enoughSpaceLen); @@ -6170,23 +6169,21 @@ int Hpack::decHeader(unsigned char *&src, unsigned char *srcEnd, AutoBuf &nameVa ++src; len = decStr((unsigned char *)name, nameValBuf.available(), src, srcEnd, true); - if ( len < 0) + if (len < 0) return len; //error name_len = len; } - len = decStr((unsigned char *)name + name_len, + len = decStr((unsigned char *)name + name_len, nameValBuf.available() - name_len, src, srcEnd, false); - if ( len < 0) + if (len < 0) return len; //error val_len = len; - + if (name_len == 10 && memcmp(name, "connection", 10) == 0) return LS_FAIL; if (indexedType == 0) - { getReqDynTbl().pushEntry(name, name_len, name + name_len, val_len, index); - } return 1; } diff --git a/src/spdy/hpack.h b/src/spdy/hpack.h index 8e178b7c3..b3d5ac389 100644 --- a/src/spdy/hpack.h +++ b/src/spdy/hpack.h @@ -72,7 +72,7 @@ class DynTblEntry { public: DynTblEntry(char *name, uint32_t name_len, char *val, - uint32_t val_len, uint8_t stxTabId) + uint32_t val_len, uint8_t stxTabId) { reset(); init(name, name_len, val, val_len, stxTabId); @@ -131,7 +131,7 @@ class HpackDynTbl } void reset(); - int getDynTabId(char *name, uint16_t name_len, char *value, + int getDynTabId(char *name, uint16_t name_len, char *value, uint16_t value_len, int &val_matched, uint8_t stxTabId); DynTblEntry *getEntry(uint32_t dynTblId) @@ -167,8 +167,8 @@ class HpackDynTbl int dynTblIdToInternalIndex(uint32_t dynTblId) { - assert(dynTblId >= HPACK_STATIC_TABLE_SIZE + 1 - && dynTblId <= HPACK_STATIC_TABLE_SIZE + getEntryCount()); + assert(dynTblId >= HPACK_STATIC_TABLE_SIZE + 1 + && dynTblId <= HPACK_STATIC_TABLE_SIZE + getEntryCount()); return getEntryCount() - (dynTblId - HPACK_STATIC_TABLE_SIZE); } @@ -202,11 +202,13 @@ class HuffmanCode ~HuffmanCode() {}; static size_t calcHuffmanEncBufSize(const unsigned char *src, - const unsigned char *src_end); - static int huffmanEnc(const unsigned char *src, const unsigned char *src_end, + const unsigned char *src_end); + static int huffmanEnc(const unsigned char *src, + const unsigned char *src_end, unsigned char *dst, int dst_len); - static unsigned char *huffmanDec4bits(uint8_t src_4bits, unsigned char *dst, - HpackHuffDecodeStatus_t &status, + static unsigned char *huffmanDec4bits(uint8_t src_4bits, + unsigned char *dst, + HpackHuffDecodeStatus_t &status, bool lowerCase); static int huffmanDec(unsigned char *src, int src_len, unsigned char *dst, int dst_len, bool lowerCase); @@ -228,22 +230,23 @@ class Hpack HpackDynTbl &getRespDynTbl() { return m_respDynTbl; } static uint8_t getStxTabId(char *name, uint16_t name_len, char *val, - uint16_t val_len, int &val_matched); + uint16_t val_len, int &val_matched); unsigned char *encInt(unsigned char *dst, uint32_t value, - uint32_t prefix_bits); + uint32_t prefix_bits); int decInt(unsigned char *&src, const unsigned char *src_end, - uint32_t prefix_bits, uint32_t& value); + uint32_t prefix_bits, uint32_t &value); int encStr(unsigned char *dst, size_t dst_len, - const unsigned char *str, uint16_t str_len); + const unsigned char *str, uint16_t str_len); int decStr(unsigned char *dst, size_t dst_len, unsigned char *&src, - const unsigned char *src_end, bool lowerCase); + const unsigned char *src_end, bool lowerCase); //indexedType: 0, Add, 1,: without, 2: never unsigned char *encHeader(unsigned char *dst, unsigned char *dstEnd, char *name, uint16_t nameLen, char *value, uint16_t valueLen, int indexedType = 0); - int decHeader(unsigned char *&src, unsigned char *srcEnd, AutoBuf &nameValBuf, + int decHeader(unsigned char *&src, unsigned char *srcEnd, + AutoBuf &nameValBuf, uint16_t &name_len, uint16_t &val_len); diff --git a/src/spdy/protocoldef.h b/src/spdy/protocoldef.h index 834030489..d448e8383 100644 --- a/src/spdy/protocoldef.h +++ b/src/spdy/protocoldef.h @@ -18,7 +18,7 @@ #ifndef SPDYPROTOCOLDEF_H #define SPDYPROTOCOLDEF_H -#include +#include typedef struct { diff --git a/src/spdy/spdyconnection.cpp b/src/spdy/spdyconnection.cpp index ee63dd167..47d20c82c 100644 --- a/src/spdy/spdyconnection.cpp +++ b/src/spdy/spdyconnection.cpp @@ -79,7 +79,15 @@ SpdyConnection::SpdyConnection() } -void SpdyConnection::init(HiosProtocol ver) +HioHandler *SpdyConnection::get(HiosProtocol proto) +{ + SpdyConnection *pConn = new SpdyConnection(); + pConn->init(proto); + return pConn; +} + + +int SpdyConnection::init(HiosProtocol ver) { if (ver == HIOS_PROTO_SPDY31) { @@ -95,14 +103,15 @@ void SpdyConnection::init(HiosProtocol ver) if (ver == HIOS_PROTO_SPDY3) m_iStreamOutInitWindowSize = SPDY_FCW_INIT_SIZE; else - //For SPDY2, there is no flow control, set it to a large value - m_iStreamOutInitWindowSize = 1024 * 1024 * 1024; + m_iStreamOutInitWindowSize = 1024 * 1024 * + 1024; //For SPDY2, there is no flow control, set it to a large value m_iServerMaxStreams = 500; m_iClientMaxStreams = 100; m_tmIdleBegin = 0; - m_iCurrentFrameRemain = -8; + m_iCurrentFrameRemain = -SPDY_FRAME_HEADER_SIZE; m_pcurrentSpdyHeader = (SpdyFrameHeader *)m_SpdyHeaderMem; + return 0; } @@ -129,6 +138,8 @@ SpdyConnection::~SpdyConnection() int SpdyConnection::onReadEx() { int ret = onReadEx2(); +// if ((m_flag & SPDY_CONN_FLAG_WAIT_PROCESS) != 0) +// onWriteEx(); if (!isEmpty()) flush(); return ret; @@ -144,6 +155,12 @@ int SpdyConnection::onReadEx2() m_bufInput.guarantee(1024); avaiLen = m_bufInput.contiguous(); n = getStream()->read(m_bufInput.end(), avaiLen); + //if ( D_ENABLED( DL_LESS ) ) + //{ + // LOG_D(( getLogger(), "[%s] getStream()->read(), availLen = %d, ret = %d", + // getLogId(), avaiLen, n )); + //} + if (n == -1) { // must start to close connection @@ -274,7 +291,7 @@ void SpdyConnection::printLogMsg(SpdyFrameHeader *pHeader) if (D_ENABLED(DL_LESS)) { LOG_D((getLogger(), "[%s] Received %s, size: %d, D0:%d, D1:%d\n", - getLogId(), getSpdyFrameName(pHeader->getType()), pHeader->getLength(), + getLogId(), getFrameName(pHeader->getType()), pHeader->getLength(), pHeader->getHboData(0), pHeader->getHboData(1))); } } @@ -334,9 +351,9 @@ int SpdyConnection::processSettingFrame(SpdyFrameHeader *pHeader) } m_iCurrentFrameRemain = 0; - if (m_iStreamInInitWindowSize == SPDY_FCW_INIT_SIZE ) + if (m_iStreamInInitWindowSize == SPDY_FCW_INIT_SIZE) m_iStreamInInitWindowSize = SPDY_FCW_INIT_SIZE * 2; - + sendSettings(m_iServerMaxStreams, m_iStreamInInitWindowSize); return 0; } @@ -664,20 +681,26 @@ int SpdyConnection::appendReqHeaders(SpdyStream *pStream, int NVPairCnt) pStream->appendInputData(m_NameValuePairListReqline[i].pValue, m_NameValuePairListReqline[i].ValueLen); if (i == 2) - pStream->appendInputData("\r\n", 2); + { + pStream->appendInputData('\r'); + pStream->appendInputData('\n'); + } else - pStream->appendInputData(" ", 1); + pStream->appendInputData(' '); } for (int i = 0; i < NVPairCnt; i++) { pStream->appendInputData(m_NameValuePairList[i].pName, m_NameValuePairList[i].nameLen); - pStream->appendInputData(": ", 2); + pStream->appendInputData(':'); + pStream->appendInputData(' '); pStream->appendInputData(m_NameValuePairList[i].pValue, m_NameValuePairList[i].ValueLen); - pStream->appendInputData("\r\n", 2); + pStream->appendInputData('\r'); + pStream->appendInputData('\n'); } - pStream->appendInputData("\r\n", 2); + pStream->appendInputData('\r'); + pStream->appendInputData('\n'); return 0; } @@ -691,11 +714,15 @@ SpdyStream *SpdyConnection::getNewStream(uint32_t uiStreamID, HioHandlerFactory::getHioHandler(HIOS_PROTO_HTTP); if (!pSession) return NULL; + pStream = new SpdyStream(); + //pStream = SpdyStreamPool::getSpdyStream(); m_mapStream.insert((void *)(long)uiStreamID, pStream); + if (m_tmIdleBegin) + m_tmIdleBegin = 0; if (D_ENABLED(DL_MORE)) { - LOG_D((getLogger(), "[%s] getNewStream(), ID: %d, stream map size: %d ", + LOG_D((getLogger(), "[%s-%d] getNewStream(), stream map size: %d ", getLogId(), uiStreamID, m_mapStream.size())); } pStream->init(uiStreamID, iPriority, this, ubSpdy_Flags, pSession); @@ -720,7 +747,7 @@ void SpdyConnection::recycleStream(StreamMap::iterator it) SpdyStream *pSpdyStream = it.second(); m_mapStream.erase(it); pSpdyStream->close(); - m_dqueStreamRespon[pSpdyStream->getPriority()].remove(pSpdyStream); + m_priQue[pSpdyStream->getPriority()].remove(pSpdyStream); if (pSpdyStream->getHandler()) pSpdyStream->getHandler()->recycle(); @@ -759,7 +786,7 @@ int SpdyConnection::sendFrame8Bytes(SpdyFrameType type, uint32_t uiVal1, if (D_ENABLED(DL_MORE)) { LOG_D((getLogger(), "[%s] send %s frame, stream: %d, value: %d" - , getLogId(), getSpdyFrameName(type), uiVal1, uiVal2)); + , getLogId(), getFrameName(type), uiVal1, uiVal2)); } return 0; } @@ -774,7 +801,7 @@ int SpdyConnection::sendFrame4Bytes(SpdyFrameType type, uint32_t uiVal1) if (D_ENABLED(DL_MORE)) { LOG_D((getLogger(), "[%s] send %s frame, value: %d" - , getLogId(), getSpdyFrameName(type), uiVal1)); + , getLogId(), getFrameName(type), uiVal1)); } return 0; } @@ -812,10 +839,12 @@ int SpdyConnection::sendSettings(uint32_t uiMaxStreamNum, uint32_t uiWindowSize) { static char cMaxStreamNumV2[8] = { 0x00, 0x00, 0x00, 0x01, - 0x04, 0x00, 0x00, 0x00 }; + 0x04, 0x00, 0x00, 0x00 + }; static char cMaxStreamNumV3[8] = { 0x00, 0x00, 0x00, 0x02, - 0x00, 0x00, 0x00, 0x04 }; - static char cWindowSizeV3[4] = { 0x00, 0x00, 0x00, 0x07 }; + 0x00, 0x00, 0x00, 0x04 + }; + static char cWindowSizeV3[4] = { 0x00, 0x00, 0x00, 0x07 }; getBuf()->guarantee(28); if (m_bVersion == 3) @@ -989,12 +1018,12 @@ int SpdyConnection::timerRoutine() if (m_mapStream.size() == 0) { if (m_tmIdleBegin == 0) - m_tmIdleBegin = time(NULL); - else + m_tmIdleBegin = DateTime::s_curTime; + else { int idle = DateTime::s_curTime - m_tmIdleBegin; if (idle > HttpServerConfig::getInstance().getSpdyKeepaliveTimeout()) - doGoAway( SPDY_GOAWAY_OK ); + doGoAway(SPDY_GOAWAY_OK); } } else @@ -1005,252 +1034,10 @@ int SpdyConnection::timerRoutine() void SpdyConnection::logDeflateInflateError(int n, int iDeflate) { - LOG_INFO((getLogger(), "[%s] Protocol Error, %s Error, Error code = %d, go away!" - , getLogId(), (iDeflate == 0 ? "Inflate" : "Deflate"), n)); -} - - -/* -//#define WRITE_TO_ZLIB_DIRECTLY -#define SPDY_TMP_HDR_BUFF_SIZE 4096 -int SpdyConnection::deflateToBuffer(char *hdrBuf, unsigned int& szHdrBuf, char* pSource, uint32_t length, LoopBuf* ploopbuf, int flush) -{ -#ifdef WRITE_TO_ZLIB_DIRECTLY - return m_deflator.compress(pSource, length, ploopbuf, flush); -#else - - //for small pieces of data, collect them and write to zlib later - int n = 0; - - if (length > 1024) - { - if (szHdrBuf > 0) - { - n += m_deflator.compress(hdrBuf, szHdrBuf, ploopbuf, 0); - szHdrBuf = 0; - } - - n += m_deflator.compress(pSource, length, ploopbuf, flush); - return n; - } - - int written = 0; - char *pSourceE = pSource + length; - while(pSource < pSourceE) - { - written = (SPDY_TMP_HDR_BUFF_SIZE - szHdrBuf >= pSourceE - pSource) ? (pSourceE - pSource) : (SPDY_TMP_HDR_BUFF_SIZE - szHdrBuf); - memcpy(hdrBuf + szHdrBuf, pSource, written); - pSource += written; - szHdrBuf += written; - - if (szHdrBuf == SPDY_TMP_HDR_BUFF_SIZE) - { - n += m_deflator.compress(hdrBuf, szHdrBuf, ploopbuf, (pSourceE > pSource) ? 0 : flush); - szHdrBuf = 0; - } - } - - if(szHdrBuf > 0 && flush == Z_SYNC_FLUSH) - { - n += m_deflator.compress(hdrBuf, szHdrBuf, ploopbuf, flush); - szHdrBuf = 0; - } - return n; -#endif //WRITE_TO_ZLIB_DIRECTLY -} - - -//This is only for SPDY case, a NUL will be added between two values -int SpdyConnection::addBufToGzip(char *hdrBuf, unsigned int& szHdrBuf, int iSpdyVer, struct iovec *iov, int iov_count, LoopBuf *buf, int &total, int flushWhenEnd) -{ - if (iov_count <= 0) - return 0; - - int i, flush = 0;//Z_SYNC_FLUSH; //no flush - int len = iov[0].iov_len; - for (i=1; isize(); - - getBuf()->guarantee( 28 ); - appendCtrlFrameHeader( SPDY_FRAME_SYN_REPLY, 0 ); - appendNbo4Bytes( getBuf(), uiStreamID ); - - total = 4; - - int iheaderCount = pRespHeaders->getHeadersCount(1) + 2;//Add 2, FOR spdy, need to add "version" and "status" - if ( m_bVersion == 2 ) - { - *((uint16_t*)pData) = 0; - getBuf()->append(pData, 2); - total = 6; - *((uint16_t*)pData) = htons(( uint16_t )iheaderCount ); - } - else - *((uint32_t*)pData) = htonl(( uint32_t )iheaderCount ); - - if ( D_ENABLED( DL_MORE ) ) - { - LOG_D(( getLogger(), "[%s] sendRespHeaders(), ID: %d, headerCount: %d" - , getLogId(), uiStreamID, iheaderCount ) ); - } - - n = deflateToBuffer( hdrBuf, szHdrBuf, pData, 8-total, getBuf() ,0 ); - - if( n < 0 ) - { - logDeflateInflateError( n, 1); - return LS_FAIL; - } - total += n; - -// it = vector.begin(); -// for ( ; it != vector.end(); it++ ) -// { -// if( ( it->iov_len == 0)&&(it->iov_base == NULL) ) -// continue; -// n = m_deflator.deflate(( char* )( it->iov_base ), -// it->iov_len, getBuf(), ( it + 1 == vector.end() )? Z_SYNC_FLUSH : 0); -// //assert( n >= 0 ); -// if( n < 0 ) -// { -// logDeflateInflateError( n, 1); -// return LS_FAIL; -// } -// total += n; -// } - -#define MAX_LINE_COUNT_OF_MULTILINE_HEADER 10 - iovec iov[MAX_LINE_COUNT_OF_MULTILINE_HEADER]; - int count; - char *key; - int keyLen; - - //Add "version" and "status" here - const StatusLineString& statusLine = HttpStatusLine::getStatusLine( pRespHeaders->getHttpVersion(), pRespHeaders->getHttpCode()); - if (m_bVersion == 2 && addBufToGzip(hdrBuf, szHdrBuf, m_bVersion, "version", 7, getBuf(), total) != 0) - return LS_FAIL; - else if (addBufToGzip(hdrBuf, szHdrBuf, m_bVersion, ":version", 8, getBuf(), total) != 0) - return LS_FAIL; - - if (addBufToGzip(hdrBuf, szHdrBuf, m_bVersion, statusLine.get(), 8, getBuf(), total) != 0) - return LS_FAIL; - --iheaderCount; - - if (m_bVersion == 2 && addBufToGzip(hdrBuf, szHdrBuf, m_bVersion, "status", 6, getBuf(), total) != 0) - return LS_FAIL; - else if (addBufToGzip(hdrBuf, szHdrBuf, m_bVersion, ":status", 7, getBuf(), total) != 0) - return LS_FAIL; - - if (addBufToGzip(hdrBuf, szHdrBuf, m_bVersion, statusLine.get() + 9, 3, getBuf(), total) != 0) - return LS_FAIL; - --iheaderCount; - - for (int pos=pRespHeaders->HeaderBeginPos(); pos != pRespHeaders->HeaderEndPos(); pos = pRespHeaders->nextHeaderPos(pos)) - { - count = pRespHeaders->getHeader(pos, &key, &keyLen, iov, MAX_LINE_COUNT_OF_MULTILINE_HEADER); - - if (count >= 1) - { - --iheaderCount; - //to lowercase - for (int k=0; kupdate(( headerOffset + 4 ), (char*)&temp32, 4 ); //Length - return total; + static const char *cErroMsg[2] = { "Inflate Error, Error code =", "Deflate Error, Error code =" }; + LOG_INFO((getLogger(), "[%s] Protocol Error, %s %d, go away!" + , getLogId(), cErroMsg[iDeflate], n)); } -*/ #define SPDY_TMP_HDR_BUFF_SIZE 2048 #define MAX_LINE_COUNT_OF_MULTILINE_HEADER 100 @@ -1274,7 +1061,7 @@ int SpdyConnection::compressHeaders(HttpRespHeaders *pRespHeaders) char *key; int keyLen; int valLen; - count = pRespHeaders->getHeadersCount(1) + + count = pRespHeaders->getUniqueCnt() + 2;//Add 2, FOR spdy, need to add "version" and "status" if (m_bVersion == 2) { @@ -1297,8 +1084,8 @@ int SpdyConnection::compressHeaders(HttpRespHeaders *pRespHeaders) pCur += sizeof(s_achSpdy3StatusLine) - 1; } const char *p = - HttpStatusCode::getInstance().getCodeString( - pRespHeaders->getHttpCode()) + 1; + HttpStatusCode::getInstance().getCodeString( + pRespHeaders->getHttpCode()) + 1; *pCur++ = *p++; *pCur++ = *p++; *pCur++ = *p++; @@ -1319,14 +1106,14 @@ int SpdyConnection::compressHeaders(HttpRespHeaders *pRespHeaders) pCur = achHdrBuf; } - char *pKeyEnd = key + keyLen; - //to lowercase if (m_bVersion == 2) pCur = beWriteUint16(pCur, keyLen); else pCur = beWriteUint32(pCur, keyLen); + char *pKeyEnd = key + keyLen; + //to lowercase while (key < pKeyEnd) - *pCur++ = (*key++) | 0x20; + *pCur++ = tolower(*key++); pIov = iov; pIovEnd = &iov[count]; @@ -1344,7 +1131,7 @@ int SpdyConnection::compressHeaders(HttpRespHeaders *pRespHeaders) { if (pIov != iov) *pCur++ = '\0'; - if ((pIov->iov_len >= 512) || (size_t)(pBufEnd - pCur) < pIov->iov_len) + if ((pIov->iov_len >= 512) || pBufEnd - pCur < (int)pIov->iov_len) { if (m_deflator.compress(achHdrBuf, pCur - achHdrBuf, getBuf(), 0) == -1) return LS_FAIL; @@ -1369,7 +1156,7 @@ int SpdyConnection::compressHeaders(HttpRespHeaders *pRespHeaders) int SpdyConnection::sendRespHeaders(HttpRespHeaders *pRespHeaders, - uint32_t uiStreamID) + uint32_t uiStreamID, int isNoBody) { int total; uint32_t temp32; @@ -1377,7 +1164,7 @@ int SpdyConnection::sendRespHeaders(HttpRespHeaders *pRespHeaders, if (D_ENABLED(DL_MORE)) { - LOG_D((getLogger(), "[%s] sendRespHeaders(), ID: %d" + LOG_D((getLogger(), "[%s-%d] sendRespHeaders()" , getLogId(), uiStreamID)); } @@ -1388,14 +1175,20 @@ int SpdyConnection::sendRespHeaders(HttpRespHeaders *pRespHeaders, total = getBuf()->size() - headerOffset - 8; temp32 = htonl(total); - getBuf()->update((headerOffset + 4), (char *)&temp32, 4); + if (isNoBody) + *((char *)&temp32) = 0x01; + getBuf()->update((headerOffset + 4), (char *)&temp32, 4); //Length return total; } -void SpdyConnection::move2ReponQue(SpdyStream *pSpdyStream) +void SpdyConnection::add2PriorityQue(SpdyStream *pSpdyStream) { - m_dqueStreamRespon[pSpdyStream->getPriority()].append(pSpdyStream); + if (pSpdyStream->next()) + pSpdyStream->remove(); + m_priQue[pSpdyStream->getPriority()].append(pSpdyStream); + m_flag |= SPDY_CONN_FLAG_WAIT_PROCESS; + } @@ -1418,14 +1211,14 @@ int SpdyConnection::onWriteEx() for (int i = 0; i < SPDY_STREAM_PRIORITYS && m_iCurDataOutWindow > 0; ++i) { - if (m_dqueStreamRespon[i].empty()) + if (m_priQue[i].empty()) continue; - DLinkedObj *it = m_dqueStreamRespon[i].begin();//SpdyStream* - DLinkedObj *itn; - for (; it != m_dqueStreamRespon[i].end() && m_iCurDataOutWindow > 0;) + SpdyStream *it = m_priQue[i].begin();//SpdyStream* + SpdyStream *itn; + for (; it != m_priQue[i].end() && m_iCurDataOutWindow > 0;) { - pSpdyStream = (SpdyStream *)it; - itn = it->next(); + pSpdyStream = it; + itn = (SpdyStream *)it->next(); if (pSpdyStream->isWantWrite()) { pSpdyStream->onWrite(); @@ -1442,9 +1235,10 @@ int SpdyConnection::onWriteEx() if (!isEmpty()) flush(); - + if ((wantWrite == 0 || m_iCurDataOutWindow <= 0) && isEmpty()) getStream()->suspendWrite(); + return 0; } @@ -1456,7 +1250,7 @@ void SpdyConnection::recycle() LOG_D((getLogger(), "[%s] SpdyConnection::recycle()", getLogId())); } - if ( m_mapStream.size() > 0 ) + if (m_mapStream.size() > 0) releaseAllStream(); detachStream(); delete this; diff --git a/src/spdy/spdyconnection.h b/src/spdy/spdyconnection.h index 62e3c2b99..2058b8c94 100644 --- a/src/spdy/spdyconnection.h +++ b/src/spdy/spdyconnection.h @@ -34,6 +34,7 @@ #define SPDY_CONN_FLAG_GOAWAY (1<<0) #define SPDY_CONN_FLAG_FLOW_CTRL (1<<1) +#define SPDY_CONN_FLAG_WAIT_PROCESS (1<<2) #define SPDY_STREAM_PRIORITYS 8 @@ -44,15 +45,15 @@ class SpdyConnection: public HioHandler, public BufferedOS public: SpdyConnection(); virtual ~SpdyConnection(); + + static HioHandler *get(HiosProtocol proto); + int onReadEx(); int onReadEx2(); int onWriteEx(); int isOutBufFull() const - { - return ((m_iCurDataOutWindow <= 0) - || (getBuf()->size() >= SPDY_MAX_DATAFRAM_SIZE)); - } + { return ((m_iCurDataOutWindow <= 0) || (getBuf()->size() >= SPDY_MAX_DATAFRAM_SIZE)); } int flush(); @@ -63,11 +64,11 @@ class SpdyConnection: public HioHandler, public BufferedOS //Following functions are just placeholder //Placeholder - void init(HiosProtocol ver); + int init(HiosProtocol ver); int onInitConnected(); int onTimerEx(); - void move2ReponQue(SpdyStream *pSpdyStream); + void add2PriorityQue(SpdyStream *pSpdyStream); int timerRoutine(); void continueWrite() @@ -85,12 +86,12 @@ class SpdyConnection: public HioHandler, public BufferedOS int appendPing(uint32_t uiStreamID) { return sendFrame4Bytes(SPDY_FRAME_PING, uiStreamID); } - int addBufToGzip(char *hdrBuf, unsigned int &szHdrBuf, int iSpdyVer, - struct iovec *iov, int iov_count, LoopBuf *buf, int &total, - int flushWhenEnd = 0); - int addBufToGzip(char *hdrBuf, unsigned int &szHdrBuf, int iSpdyVer, - const char *s, int len, LoopBuf *buf, int &total); - int sendRespHeaders(HttpRespHeaders *pRespHeaders, uint32_t uiStreamID); + int addBufToGzip(int iSpdyVer, struct iovec *iov, int iov_count, + LoopBuf *buf, int &total, int flushWhenEnd = 0); + int addBufToGzip(int iSpdyVer, const char *s, int len, LoopBuf *buf, + int &total); + int sendRespHeaders(HttpRespHeaders *pRespHeaders, uint32_t uiStreamID, + int isNoBody); int sendWindowUpdateFrame(uint32_t id, int32_t delta) { @@ -125,6 +126,10 @@ class SpdyConnection: public HioHandler, public BufferedOS void recycleStream(uint32_t uiStreamID); static void replaceZero(char *pValue, int ilength); + uint16_t getEvents() + { return getStream()->getEvents(); } + int isFromLocalAddr() const + { return getStream()->isFromLocalAddr(); } NtwkIOLink *getNtwkIoLink(); @@ -173,8 +178,7 @@ class SpdyConnection: public HioHandler, public BufferedOS void skipRemainData(); int compressHeaders(HttpRespHeaders *pRespHeaders); - int deflateToBuffer(char *hdrBuf, unsigned int &szHdrBuf, char *pSource, - uint32_t length, LoopBuf *ploopbuf, int flush); + static int getKeepaliveTimeout(); private: LoopBuf m_bufInput; @@ -189,7 +193,7 @@ class SpdyConnection: public HioHandler, public BufferedOS struct timeval m_timevalPing; NameValuePair m_NameValuePairList[100]; NameValuePair m_NameValuePairListReqline[3]; - DLinkQueue m_dqueStreamRespon[SPDY_STREAM_PRIORITYS]; + TDLinkQueue m_priQue[SPDY_STREAM_PRIORITYS]; StreamMap m_mapStream; short m_state; short m_flag; diff --git a/src/spdy/spdydebug.h b/src/spdy/spdydebug.h index a77953643..f06b8cd21 100644 --- a/src/spdy/spdydebug.h +++ b/src/spdy/spdydebug.h @@ -20,4 +20,4 @@ void printbuff(unsigned char *buff, int length); int printheader(unsigned char *buff, int length); void printbuffstr(char *buff, int length); -#endif // SPDYDEBUG_H +#endif // SPDYDEBUG_H \ No newline at end of file diff --git a/src/spdy/spdyprotocol.cpp b/src/spdy/spdyprotocol.cpp index 9e7b9a7a5..270db04f5 100644 --- a/src/spdy/spdyprotocol.cpp +++ b/src/spdy/spdyprotocol.cpp @@ -17,7 +17,7 @@ *****************************************************************************/ #include "spdyprotocol.h" -static const char *s_sSpdyFrameName[] = +static const char *s_sFrameName[] = { "DATA", "SYN_STREAM", @@ -32,11 +32,10 @@ static const char *s_sSpdyFrameName[] = "CREDENTIAL" }; - -const char *getSpdyFrameName(unsigned char bframeType) +const char *getFrameName(unsigned char bframeType) { if (bframeType <= SPDY_FRAME_LAST_CONTROL_TYPE) - return s_sSpdyFrameName[bframeType]; + return s_sFrameName[bframeType]; return "UNKONWN"; } diff --git a/src/spdy/spdyprotocol.h b/src/spdy/spdyprotocol.h index c78c3e229..9520494a7 100644 --- a/src/spdy/spdyprotocol.h +++ b/src/spdy/spdyprotocol.h @@ -17,11 +17,9 @@ *****************************************************************************/ #ifndef SPDYPROTOCOL_H #define SPDYPROTOCOL_H - -#include - -#include +#include #include +#include // Types of SPDY frames. enum SpdyFrameType @@ -139,11 +137,7 @@ class SpdyFrameHeader ~SpdyFrameHeader() {} int isControlFrame() const { return m_un.m_ctl.m_b80 == 0x80; } - unsigned char getType() const - { - return (m_un.m_ctl.m_b80 == 0x80) ? (m_un.m_ctl.m_bType) : (0); - } - + unsigned char getType() const { return (m_un.m_ctl.m_b80 == 0x80) ? (m_un.m_ctl.m_bType) : (0); } unsigned char getFlags() const { return m_bFlags; } unsigned char getVersion() const { return m_un.m_ctl.m_bVer; } @@ -165,12 +159,10 @@ class SpdyFrameHeader } uint32_t getData(int n) const { return m_data[n]; } uint32_t getHboData(int n) const { return ntohl(m_data[n]); } - - LS_NO_COPY_ASSIGN(SpdyFrameHeader); }; -const char *getSpdyFrameName(unsigned char bframeType); +const char *getFrameName(unsigned char bframeType); class SpdySettingPairs { @@ -196,7 +188,6 @@ class SpdySettingPairs unsigned char getFlags() const { return m_unFlagId.m_b[0]; } uint32_t getValue() const { return ntohl(m_uiValue); } uint32_t getID() const { return (ntohl(m_unFlagId.m_ui) & 0xFFFFFF); } - }; #define SPDY_MAX_DATAFRAM_SIZE 65536 diff --git a/src/spdy/spdystream.cpp b/src/spdy/spdystream.cpp index 0e1f5c108..9a9d281fc 100644 --- a/src/spdy/spdystream.cpp +++ b/src/spdy/spdystream.cpp @@ -25,7 +25,6 @@ SpdyStream::SpdyStream() : m_uiStreamID(0) - , m_iPriority(0) , m_pSpdyConn(NULL) { } @@ -43,8 +42,9 @@ const char *SpdyStream::buildLogId() } -int SpdyStream::init(uint32_t StreamID, int Priority, SpdyConnection *pSpdyConn, - uint8_t flags, HioHandler *pHandler) +int SpdyStream::init(uint32_t StreamID, + int Priority, SpdyConnection *pSpdyConn, uint8_t flags, + HioHandler *pHandler) { HioStream::reset(DateTime::s_curTime); pHandler->attachStream(this); @@ -57,11 +57,11 @@ int SpdyStream::init(uint32_t StreamID, int Priority, SpdyConnection *pSpdyConn, m_uiStreamID = StreamID; m_iWindowOut = pSpdyConn->getStreamOutInitWindowSize(); m_iWindowIn = pSpdyConn->getStreamInInitWindowSize(); - m_iPriority = Priority; + setPriority(Priority); m_pSpdyConn = pSpdyConn; if (D_ENABLED(DL_LESS)) { - LOG_D((getLogger(), "[%s] SpdyStream::init(), id: %d.", + LOG_D((getLogger(), "[%s] SpdyStream::init(), id: %d. ", getLogId(), StreamID)); } return 0; @@ -148,7 +148,7 @@ void SpdyStream:: continueWrite() } setFlag(HIO_FLAG_WANT_WRITE, 1); if (next() == NULL) - m_pSpdyConn->move2ReponQue(this); + m_pSpdyConn->add2PriorityQue(this); m_pSpdyConn->continueWrite(); } @@ -158,12 +158,21 @@ void SpdyStream::onTimer() getHandler()->onTimerEx(); } -NtwkIOLink *SpdyStream::getNtwkIoLink() + +uint16_t SpdyStream::getEvents() const { - return m_pSpdyConn->getNtwkIoLink(); + return m_pSpdyConn->getEvents(); } +int SpdyStream::isFromLocalAddr() const +{ return m_pSpdyConn->isFromLocalAddr(); } + + +NtwkIOLink *SpdyStream::getNtwkIoLink() +{ return m_pSpdyConn->getNtwkIoLink(); } + + int SpdyStream::shutdown() { if (getState() == HIOS_SHUTDOWN) @@ -177,7 +186,7 @@ int SpdyStream::shutdown() getLogId())); } m_pSpdyConn->sendFinFrame(m_uiStreamID); - m_pSpdyConn->flush(); + //m_pSpdyConn->flush(); return 0; } @@ -197,7 +206,7 @@ int SpdyStream::close() // getHandler()->recycle(); // setHandler( NULL ); //} - m_pSpdyConn->recycleStream( m_uiStreamID ); + m_pSpdyConn->recycleStream(m_uiStreamID); return 0; } @@ -206,7 +215,8 @@ int SpdyStream::flush() { if (D_ENABLED(DL_LESS)) { - LOG_D((getLogger(), "[%s] SpdyStream::flush()", getLogId())); + LOG_D((getLogger(), "[%s] SpdyStream::flush()", + getLogId())); } return LS_DONE; } @@ -340,13 +350,25 @@ int SpdyStream::sendData(IOVec *pIov, int total) } -int SpdyStream::sendRespHeaders(HttpRespHeaders *pHeaders) +int SpdyStream::sendRespHeaders(HttpRespHeaders *pHeaders, int isNoBody) { if (getState() == HIOS_DISCONNECTED) return LS_FAIL; - - m_pSpdyConn->move2ReponQue(this); - return m_pSpdyConn->sendRespHeaders(pHeaders, m_uiStreamID); + if (isNoBody) + { + if (D_ENABLED(DL_LESS)) + { + LOG_D((getLogger(), "[%s] No response body, set FLAG_FIN.", + getLogId())); + } + setState(HIOS_SHUTDOWN); + } + else + { + if (next() == NULL) + m_pSpdyConn->add2PriorityQue(this); + } + return m_pSpdyConn->sendRespHeaders(pHeaders, m_uiStreamID, isNoBody); } int SpdyStream::adjWindowOut(int32_t n) diff --git a/src/spdy/spdystream.h b/src/spdy/spdystream.h index 875aeb8ba..7db9d12b9 100644 --- a/src/spdy/spdystream.h +++ b/src/spdy/spdystream.h @@ -35,13 +35,11 @@ class SpdyStream: public DLinkedObj, public HioStream SpdyStream(); ~SpdyStream(); - int init(uint32_t StreamID, int Priority, SpdyConnection *pSpdyConn, - uint8_t Spdy_Flags, HioHandler *pHandler); + int init(uint32_t StreamID, + int Priority, SpdyConnection *pSpdyConn, uint8_t Spdy_Flags, + HioHandler *pHandler); int onInitConnected(); - int getPriority() const - { return m_iPriority; } - int appendReqData(char *pData, int len, uint8_t Spdy_Flags); int read(char *buf, int len); @@ -59,18 +57,23 @@ class SpdyStream: public DLinkedObj, public HioStream void switchWriteToRead() {}; int flush(); - int sendRespHeaders(HttpRespHeaders *pHeaders); + int sendRespHeaders(HttpRespHeaders *pHeaders, int isNoBody); - void suspendRead() { setFlag(HIO_FLAG_WANT_READ, 0); } - void suspendWrite() { setFlag(HIO_FLAG_WANT_WRITE, 0); } + void suspendRead() + { setFlag(HIO_FLAG_WANT_READ, 0); } + void suspendWrite() + { setFlag(HIO_FLAG_WANT_WRITE, 0); } void continueRead(); void continueWrite(); + uint16_t getEvents() const; + int isFromLocalAddr() const; + virtual NtwkIOLink *getNtwkIoLink(); + + void onTimer(); - virtual NtwkIOLink *getNtwkIoLink(); - int shutdown(); int close(); @@ -95,7 +98,10 @@ class SpdyStream: public DLinkedObj, public HioStream int getDataFrameSize(int wanted); - void appendInputData(char ch) { return m_bufIn.append(ch); } + void appendInputData(char ch) + { + return m_bufIn.append(ch); + } private: @@ -105,12 +111,12 @@ class SpdyStream: public DLinkedObj, public HioStream int sendData(IOVec *pIov, int total); + protected: virtual const char *buildLogId(); private: uint32_t m_uiStreamID; - int m_iPriority; int32_t m_iWindowOut; int32_t m_iWindowIn; SpdyConnection *m_pSpdyConn; @@ -120,4 +126,7 @@ class SpdyStream: public DLinkedObj, public HioStream }; + + + #endif // SPDYSTREAM_H diff --git a/src/spdy/spdystreampool.h b/src/spdy/spdystreampool.h index 85a0356e0..e0e8ebaeb 100644 --- a/src/spdy/spdystreampool.h +++ b/src/spdy/spdystreampool.h @@ -28,13 +28,13 @@ class SpdyStreamPool : public ObjPool static Pool s_pool; SpdyStreamPool(); ~SpdyStreamPool(); - + public: static void recycle(SpdyStream *pStream); static SpdyStream *getSpdyStream(); static void recycle(SpdyStream **pStream, int n); static int getSpdyStreams(SpdyStream **pStream, int n); - + LS_NO_COPY_ASSIGN(SpdyStreamPool); }; diff --git a/src/spdy/spdyzlibfilter.cpp b/src/spdy/spdyzlibfilter.cpp index 088a7cfaa..d0a0584fb 100644 --- a/src/spdy/spdyzlibfilter.cpp +++ b/src/spdy/spdyzlibfilter.cpp @@ -223,8 +223,8 @@ static const unsigned char s_spdyV3Dictionary[] = }; static const unsigned char *s_dicts[] = { NULL, s_spdyV2Dictionary, s_spdyV3Dictionary }; -static int s_dictsLen[] = { 0, sizeof(s_spdyV2Dictionary), sizeof(s_spdyV3Dictionary) }; - +static int s_dictsLen[] = +{ 0, sizeof(s_spdyV2Dictionary), sizeof(s_spdyV3Dictionary) }; SpdyZlibFilter::SpdyZlibFilter() : m_iVersion(2) @@ -278,8 +278,8 @@ int SpdyZlibFilter::release() return 0; } - -int SpdyZlibFilter::decompress(char *pSource, uint32_t length, AutoBuf &bufInflate) +int SpdyZlibFilter::decompress(char *pSource, uint32_t length, + AutoBuf &bufInflate) { int ret; @@ -296,6 +296,7 @@ int SpdyZlibFilter::decompress(char *pSource, uint32_t length, AutoBuf &bufInfla switch (ret) { + case Z_NEED_DICT: /* Setting the dictionary for the SPDY zlib compression. */ ret = inflateSetDictionary(&m_stream, s_dicts[ m_iVersion ], @@ -347,7 +348,7 @@ int SpdyZlibFilter::compress(char *pSource, uint32_t length, m_stream.next_out = (unsigned char *)ploopbuf->end(); while (m_stream.avail_in) { - ret = ::deflate(&m_stream, flush); + ret = deflate(&m_stream, flush); if ((ret == Z_OK) || (ret == Z_STREAM_END)) { diff --git a/src/spdy/spdyzlibfilter.h b/src/spdy/spdyzlibfilter.h index c3932c733..77f1cb8b8 100644 --- a/src/spdy/spdyzlibfilter.h +++ b/src/spdy/spdyzlibfilter.h @@ -27,8 +27,6 @@ #include /* basic system data types */ #include -#include - /** * Context for zlib deflating and inflating. * Allows to use the same zlib stream on multiple frames. (Needed @@ -40,21 +38,19 @@ class LoopBuf; class SpdyZlibFilter { + +private: + z_stream m_stream; + short m_iVersion; + short m_isInflator; + public: SpdyZlibFilter(); ~SpdyZlibFilter(); int init(int isInflator, int verSpdy); int release(); int decompress(char *pSource, uint32_t length, AutoBuf &bufInflate); - int compress(char *pSource, uint32_t length, LoopBuf *pBuf, int flush); - -private: - bool operator==(const SpdyZlibFilter &other) const; - -private: - z_stream m_stream; - short m_iVersion; - short m_isInflator; + int compress(char *pSource, uint32_t length, LoopBuf *ploopbuf, int flush); LS_NO_COPY_ASSIGN(SpdyZlibFilter); }; diff --git a/src/ssi/ssiengine.cpp b/src/ssi/ssiengine.cpp index 8093115f4..e47d5113c 100644 --- a/src/ssi/ssiengine.cpp +++ b/src/ssi/ssiengine.cpp @@ -34,8 +34,8 @@ #include SSIEngine::SSIEngine() + : HttpHandler(HandlerType::HT_SSI) { - setHandlerType(HandlerType::HT_SSI); } diff --git a/src/sslpp/sslconnection.cpp b/src/sslpp/sslconnection.cpp index 5e301f9ce..21159f7f2 100644 --- a/src/sslpp/sslconnection.cpp +++ b/src/sslpp/sslconnection.cpp @@ -231,6 +231,13 @@ int SSLConnection::writev(const struct iovec *vect, int count, } +int SSLConnection::wpending() +{ + BIO * pBIO = SSL_get_wbio( m_ssl ); + return BIO_wpending(pBIO); +} + + int SSLConnection::flush() { BIO *pBIO = SSL_get_wbio(m_ssl); diff --git a/src/sslpp/sslconnection.h b/src/sslpp/sslconnection.h index 45a2bb2ec..4d8c54684 100644 --- a/src/sslpp/sslconnection.h +++ b/src/sslpp/sslconnection.h @@ -76,6 +76,7 @@ class SSLConnection int accept(); int connect(); int read(char *pBuf, int len); + int wpending(); int write(const char *pBuf, int len); int writev(const struct iovec *vect, int count, int *finished); int flush(); diff --git a/src/test/http/httpheadertest.cpp b/src/test/http/httpheadertest.cpp index 3e577852c..ae69af805 100644 --- a/src/test/http/httpheadertest.cpp +++ b/src/test/http/httpheadertest.cpp @@ -501,11 +501,11 @@ TEST (respHeadersCrash) strlen("Thu, 16 May 2013 20:32:23 GMT")); h.add(HttpRespHeaders::H_X_POWERED_BY, "PHP/5.3.24", strlen("PHP/5.3.24")); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\ndate: Thu, 16 May 2013 20:32:23 GMT\r\nx-powered-by: PHP/5.3.24\r\nconnection: close\r\n\r\n"); CheckIoHeader(io, sTestHdr); - CHECK(h.getHeadersCount(0) == + CHECK(h.getCount() == 5); //Will add connection: close automatically h.reset(); @@ -517,11 +517,11 @@ TEST (respHeadersCrash) h.addStatusLine(0, SC_304, 1); //when ver is 0 and keepalive is 1, Will NOT add connection: close automatically h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); strcpy(sTestHdr, "HTTP/1.1 304 Not Modified\r\n" "server: My_Server\r\naccept-ranges: bytes\r\ndate: Thu, 16 May 2013 20:32:23 GMT\r\nx-powered-by: PHP/5.3.24\r\n\r\n"); CheckIoHeader(io, sTestHdr); - CHECK(h.getHeadersCount(0) == 4); + CHECK(h.getCount() == 4); h.reset(); h.add(HttpRespHeaders::H_SERVER, "My_Server", 9); @@ -533,28 +533,28 @@ TEST (respHeadersCrash) h.add(HttpRespHeaders::H_DATE, "XXXX", 4, LSI_HEADER_MERGE); h.add(HttpRespHeaders::H_X_POWERED_BY, "PHP/5.3.24", strlen("PHP/5.3.24")); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\ndate: Thu, 16 May 2013 20:32:23 GMT,Thu, 16 ,XXXX\r\nx-powered-by: PHP/5.3.24\r\nconnection: close\r\n\r\n"); CheckIoHeader(io, sTestHdr); h.add(HttpRespHeaders::H_DATE, "NEWDATE", 7, LSI_HEADER_ADD); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\ndate: Thu, 16 May 2013 20:32:23 GMT,Thu, 16 ,XXXX\r\nx-powered-by: PHP/5.3.24\r\nconnection: close\r\ndate: NEWDATE\r\n\r\n"); CheckIoHeader(io, sTestHdr); h.add(HttpRespHeaders::H_DATE, "NEWDATE2", 8, LSI_HEADER_ADD); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\ndate: Thu, 16 May 2013 20:32:23 GMT,Thu, 16 ,XXXX\r\nx-powered-by: PHP/5.3.24\r\nconnection: close\r\ndate: NEWDATE\r\ndate: NEWDATE2\r\n\r\n"); CheckIoHeader(io, sTestHdr); h.add(HttpRespHeaders::H_DATE, "NEWDATE3", 8, LSI_HEADER_ADD); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\ndate: Thu, 16 May 2013 20:32:23 GMT,Thu, 16 ,XXXX\r\nx-powered-by: PHP/5.3.24\r\nconnection: close\r\ndate: NEWDATE\r\ndate: NEWDATE2\r\ndate: NEWDATE3\r\n\r\n"); CheckIoHeader(io, sTestHdr); @@ -562,8 +562,8 @@ TEST (respHeadersCrash) h.del(HttpRespHeaders::H_DATE); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); - CHECK(h.getHeadersCount(0) == 4); + DisplayBothHeader(io, kk, h.getCount(), &h); + CHECK(h.getCount() == 4); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\nx-powered-by: PHP/5.3.24\r\nconnection: close\r\n\r\n"); CheckIoHeader(io, sTestHdr); @@ -571,16 +571,16 @@ TEST (respHeadersCrash) h.del("X-Powered-By", strlen("X-Powered-By")); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); - CHECK(h.getHeadersCount(0) == 3); + DisplayBothHeader(io, kk, h.getCount(), &h); + CHECK(h.getCount() == 3); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\nconnection: close\r\n\r\n"); CheckIoHeader(io, sTestHdr); h.add(HttpRespHeaders::H_SERVER, "YY_Server", 9); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); - CHECK(h.getHeadersCount(0) == 3); + DisplayBothHeader(io, kk, h.getCount(), &h); + CHECK(h.getCount() == 3); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: YY_Server\r\naccept-ranges: bytes\r\nconnection: close\r\n\r\n"); CheckIoHeader(io, sTestHdr); @@ -588,8 +588,8 @@ TEST (respHeadersCrash) h.add(HttpRespHeaders::H_SERVER, "XServer", 7); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); - CHECK(h.getHeadersCount(0) == 3); + DisplayBothHeader(io, kk, h.getCount(), &h); + CHECK(h.getCount() == 3); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: XServer \r\naccept-ranges: bytes\r\nconnection: close\r\n\r\n"); CheckIoHeader(io, sTestHdr); @@ -598,8 +598,8 @@ TEST (respHeadersCrash) strlen("Thu, 16 May 2013 20:32:23 GMT")); h.add(HttpRespHeaders::H_X_POWERED_BY, "PHP/9.9.99", strlen("PHP/5.3.24")); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); - CHECK(h.getHeadersCount(0) == 5); + DisplayBothHeader(io, kk, h.getCount(), &h); + CHECK(h.getCount() == 5); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: XServer \r\naccept-ranges: bytes\r\nconnection: close\r\ndate: Thu, 16 May 2099 20:32:23 GMT\r\nx-powered-by: PHP/9.9.99\r\n\r\n"); CheckIoHeader(io, sTestHdr); @@ -609,8 +609,8 @@ TEST (respHeadersCrash) h.appendLastVal("; .zip; .rar", strlen("; .zip; .rar")); h.appendLastVal("; .exe; .flv", strlen("; .zip; .rar")); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); - CHECK(h.getHeadersCount(0) == 6); + DisplayBothHeader(io, kk, h.getCount(), &h); + CHECK(h.getCount() == 6); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: XServer \r\naccept-ranges: bytes\r\nconnection: close\r\ndate: Thu, 16 May 2099 20:32:23 GMT\r\nx-powered-by: PHP/9.9.99\r\nallow: *.*; .zip; .rar; .exe; .flv\r\n\r\n"); CheckIoHeader(io, sTestHdr); @@ -633,9 +633,9 @@ TEST (respHeadersCrash) strlen("lsws_uid=c; expires=Mon, 13 May 2013 14:10:51 GMT; path=/"), LSI_HEADER_ADD); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); - CHECK(h.getHeadersCount(1) == 8); - CHECK(h.getHeadersCount(0) == 10); + DisplayBothHeader(io, kk, h.getCount(), &h); + CHECK(h.getUniqueCnt() == 8); + CHECK(h.getCount() == 10); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: XServer \r\naccept-ranges: bytes\r\nconnection: close\r\ndate: Thu, 16 May 2099 20:32:23 GMT\r\nx-powered-by: PHP/9.9.99\r\nallow: *.*; .zip; .rar; .exe; .flv\r\n"); strcat(sTestHdr, @@ -652,8 +652,8 @@ TEST (respHeadersCrash) h.parseAdd("MytestHeader: TTTTTTTTTTTT\r\nMyTestHeaderii: IIIIIIIIIIIIIIIIIIIII\r\n", strlen("MytestHeader: TTTTTTTTTTTT\r\nMyTestHeaderii: IIIIIIIIIIIIIIIIIIIII\r\n")); - CHECK(h.getHeadersCount(1) == 10); - CHECK(h.getHeadersCount(0) == 12); + CHECK(h.getUniqueCnt() == 10); + CHECK(h.getCount() == 12); h.getFirstHeader("MytestHeader", strlen("MytestHeader"), &pVal, valLen); CHECK(memcmp(pVal, "TTTTTTTTTTTT", valLen) == 0); @@ -661,8 +661,8 @@ TEST (respHeadersCrash) h.parseAdd("MytestHeader : TTTTTTTTTTTT3\r\n", strlen("MytestHeader : TTTTTTTTTTTT3\r\n")); - CHECK(h.getHeadersCount(1) == 10); - CHECK(h.getHeadersCount(0) == 12); + CHECK(h.getUniqueCnt() == 10); + CHECK(h.getCount() == 12); h.getFirstHeader("MytestHeader", strlen("MytestHeader"), &pVal, valLen); CHECK(memcmp(pVal, "TTTTTTTTTTTT3", valLen) == 0); @@ -676,7 +676,7 @@ TEST (respHeadersCrash) h.parseAdd("Content-Encoding2 : GZIP\r\n", strlen("Content-Encoding2 : GZIP\r\n"), LSI_HEADER_MERGE); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); strcpy(sTestHdr, "HTTP/1.1 404 Not Found\r\nserver: XServer \r\naccept-ranges: bytes\r\nconnection: close\r\ndate: Thu, 16 May 2099 20:32:23 GMT\r\nx-powered-by: PHP/9.9.99\r\nallow: *.*; .zip; .rar; .exe; .flv\r\n"); strcat(sTestHdr, @@ -688,7 +688,7 @@ TEST (respHeadersCrash) h.parseAdd("MytestHeader: XXX\r\n", strlen("MytestHeader: XXX\r\n"), LSI_HEADER_MERGE); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); strcpy(sTestHdr, "HTTP/1.1 404 Not Found\r\nserver: XServer \r\naccept-ranges: bytes\r\nconnection: close\r\ndate: Thu, 16 May 2099 20:32:23 GMT\r\nx-powered-by: PHP/9.9.99\r\nallow: *.*; .zip; .rar; .exe; .flv\r\n"); strcat(sTestHdr, @@ -700,7 +700,7 @@ TEST (respHeadersCrash) h.parseAdd("MytestHeader: XXX\r\n", strlen("MytestHeader: XXX\r\n"), LSI_HEADER_APPEND); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); strcpy(sTestHdr, "HTTP/1.1 404 Not Found\r\nserver: XServer \r\naccept-ranges: bytes\r\nconnection: close\r\ndate: Thu, 16 May 2099 20:32:23 GMT\r\nx-powered-by: PHP/9.9.99\r\nallow: *.*; .zip; .rar; .exe; .flv\r\n"); strcat(sTestHdr, @@ -718,7 +718,7 @@ TEST (respHeadersCrash) h.add(HttpRespHeaders::H_DATE, "AAAA", 4, LSI_HEADER_MERGE); h.add(HttpRespHeaders::H_X_POWERED_BY, "PHP/5.3.24", strlen("PHP/5.3.24")); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\ndate: Thu, 16 May 2013 20:32:23 GMT,AAAA\r\nx-powered-by: PHP/5.3.24\r\nconnection: close\r\n\r\n"); CheckIoHeader(io, sTestHdr); @@ -726,19 +726,19 @@ TEST (respHeadersCrash) strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\ndate: Thu, 16 May 2013 20:32:23 GMT,AAAA,AAA\r\nx-powered-by: PHP/5.3.24\r\nconnection: close\r\n\r\n"); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); CheckIoHeader(io, sTestHdr); h.add(HttpRespHeaders::H_DATE, "AAA", 3, LSI_HEADER_MERGE); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\ndate: Thu, 16 May 2013 20:32:23 GMT,AAAA,AAA\r\nx-powered-by: PHP/5.3.24\r\nconnection: close\r\n\r\n"); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); CheckIoHeader(io, sTestHdr); h.add(HttpRespHeaders::H_DATE, "AAA", 3, LSI_HEADER_APPEND); strcpy(sTestHdr, "HTTP/1.1 200 OK\r\nserver: My_Server\r\naccept-ranges: bytes\r\ndate: Thu, 16 May 2013 20:32:23 GMT,AAAA,AAA,AAA\r\nx-powered-by: PHP/5.3.24\r\nconnection: close\r\n\r\n"); h.outputNonSpdyHeaders(&io); - DisplayBothHeader(io, kk, h.getHeadersCount(0), &h); + DisplayBothHeader(io, kk, h.getCount(), &h); CheckIoHeader(io, sTestHdr); ls_xpool_destroy(&pool); @@ -856,7 +856,7 @@ TEST (respHeadersCrash) h.reset(); //add using array add and check contents temp = h.add(headerArray1, 26); - CHECK(h.getHeadersCount(0) == 26); + CHECK(h.getCount() == 26); CHECK(temp == 0); for ( i=h.HeaderBeginPos(); i!=h.HeaderEndPos(); i=h.nextHeaderPos(i) ) { @@ -871,9 +871,9 @@ TEST (respHeadersCrash) { temp = h.add((const HttpRespHeaders::HEADERINDEX)(i), s_pHeaders[i+1], strlen(s_pHeaders[i+1]), s_pHeaderVals[i+1], strlen(s_pHeaderVals[i+1])); CHECK(temp == 0); - temp = h.getHeadersCount(0); + temp = h.getCount(); temp = h.getTotalCount(); - CHECK(h.getHeadersCount(0) == i+2);//start at 1 and add 1 for connection close + CHECK(h.getCount() == i+2);//start at 1 and add 1 for connection close CHECK(h.getTotalCount() == i+2); temp = h.getHeader(s_pHeaders[i+1], strlen(s_pHeaders[i+1]), &pVal, valLen); @@ -910,10 +910,10 @@ TEST (respHeadersCrash) h.reset(); temp = h.add(headerArray1, 26); - CHECK(h.getHeadersCount(0) == 26); + CHECK(h.getCount() == 26); CHECK(temp == 0); //check del index - int count = h.getHeadersCount(0);; + int count = h.getCount();; for (i=HttpRespHeaders::H_UNKNOWN; igetEntrySize(), pEntry->getName(), pEntry->getValue()); } - printf("\tTable size: %d\n", dynTab.getTotalTableSize()); + printf("\tTable size: %lu\n", dynTab.getTotalTableSize()); } TEST(hapck_test_1) @@ -51,7 +51,7 @@ TEST(hapck_test_1) HpackDynTbl dynTable; dynTable.updateMaxCapacity(256); - printf( "size of DynTblEntry is %d\n", sizeof( DynTblEntry )); + printf( "size of DynTblEntry is %lu\n", sizeof( DynTblEntry )); addEntry(dynTable, ":authority", "www.example.com", 1); printTable(dynTable); diff --git a/src/util/dlinkqueue.h b/src/util/dlinkqueue.h index 4169f52b8..fd6847b93 100644 --- a/src/util/dlinkqueue.h +++ b/src/util/dlinkqueue.h @@ -134,4 +134,45 @@ class DLinkQueue }; + +template< typename T> +class TDLinkQueue : public DLinkQueue +{ +public: + TDLinkQueue() {} + ~TDLinkQueue() {} + + void release_objects() + { + T * p; + while( (p = pop_front()) != NULL ) + { + delete p; + } + } + + void append( T * pReq ) + { DLinkQueue::append( pReq ); } + + void push_front( T * pReq ) + { DLinkQueue::push_front( pReq ); } + + void remove( T * pReq ) + { DLinkQueue::remove( pReq ); } + + T * next( const T * pObj ) + { return ( T * )pObj->next(); } + + T * pop_front() + { return ( T * )DLinkQueue::pop_front(); } + + T * begin() + { return ( T * )DLinkQueue::begin(); } + + T * end() + { return ( T * )DLinkQueue::end(); } + +}; + + #endif