/* Web Polygraph http://www.web-polygraph.org/ * (C) 2003-2006 The Measurement Factory * Licensed under the Apache License, Version 2.0 */ #ifndef POLYGRAPH__RUNTIME_CONNECTION_H #define POLYGRAPH__RUNTIME_CONNECTION_H #include "xstd/Queue.h" #include "xstd/NetAddr.h" #include "xstd/Socket.h" #include "xstd/FileScanner.h" #include "base/ConnCloseStat.h" #include "runtime/IOBuf.h" class ConnMgr; class PortMgr; class SslCtx; class SslSession; class Ssl; // bi-directional connection based on a socket with I/O buffers class Connection: public QueueItem { public: typedef ConnCloseStat::CloseKind CloseKind; typedef Size (Connection::*IoMethod)(); class HalfPipe { public: HalfPipe(Connection &aConn, IOBuf &aBuf, IODir aDir): theConn(aConn), theBuf(aBuf), theDir(aDir) { reset(); } void reset(); void start(FileScanUser *u); void start(FileScanUser *u, Time timeout); void stop(FileScanUser *u); void changeUser(FileScanUser *uOld, FileScanUser *uNew); public: Connection &theConn; IOBuf &theBuf; IODir theDir; FileScanReserv theReserv; int theIOCnt; bool isReady; }; friend class HalfPipe; public: Connection(); ~Connection() { if (theSock) closeNow(); } void reset(); int seqId() const { return theSeqId; } Socket &sock() { return theSock; } int fd() const { return theSock.fd(); } const NetAddr &raddr() const { return theAddr; } NetAddr laddr() const; int lport() const { return theLocPort; } int rport() const; ConnMgr *mgr() const { return theMgr; } int logCat() const { return theLogCat; } bool exhausted() const { return isAtEof && !theRdBuf.contSize(); } bool atEof() const { return isAtEof; } bool bad() const { return isBad; } CloseKind closeKind() const { return theCloseKind; } bool sslConfigured() const { return theSslCtx != 0; } const Ssl *sslActive() const { return theSsl; } bool sslActivate(); SslSession *sslSession(); void sslSessionForget(); bool connect(const NetAddr &addr, const SockOpt &opt, PortMgr *aPortMgr); bool accept(Socket &s, const SockOpt &opt, bool &fatal); Size read(); Size write(); bool closing() const { return theCloseKind != ConnCloseStat::ckNone; } bool closeNow(); // closes everything // initiates SSL close, returns true if done; does not close raw sock bool closeAsync(FileScanUser *u, bool &fatal); void mgr(ConnMgr *aMgr) { theMgr = aMgr; } void logCat(int aLogCat) { theLogCat = aLogCat; } void useSsl(const SslCtx *aCtx, SslSession *aSess); bool pipelineable() const; bool reusable() const; void useCountLimit(int aLimit) { theUseCountLmt = aLimit; } void useLevelLimit(int aLimit) { theUseLevelLmt = aLimit; } int useCnt() const { return theUseCnt; } int useLevel() const { return theUseLvl; } void startUse(); void finishUse(); bool inUse() const { return theUseLvl > 0; } Time useStart() const { return theUseStart; } bool isIdle() const { return theUseLvl == 0; } int useLevelMax() const { return theUseLvlMax; } bool tunneling() const { return theTunnel.known() && theTunnel != raddr(); } const NetAddr &tunnelEnd() const { return theTunnel; } void tunnelEnd(const NetAddr &addr) { theTunnel = addr; } Time openTime() const { return theOpenTime; } int ioCnt() const { return theRd.theIOCnt + theWr.theIOCnt; } void bad(bool be) { isBad = be; } void lastUse(bool be) { isLastUse = be; } void closeKind(CloseKind aKind) { theCloseKind = aKind; } void decMaxIoSize(Size aMax); void maxIoSize(Size aMax) { theMaxIoSize = aMax; } protected: void sslStart(int role); bool sslAccept(); bool sslConnect(); Size sslRead(Size ioSz); Size sslWrite(Size ioSz); bool sslCloseNow(); bool sslCloseAsync(FileScanUser *u, bool &fatal); void sslForget(); void sslError(int err, const char *operation); Size rawRead(Size ioSz); Size rawWrite(Size ioSz); bool rawCloseNow(); void rawError(const char *operation); bool setSockOpt(const SockOpt &opt); bool preIo(HalfPipe &ioPipe, const char *operation); void reportErrorLoc(); public: RdBuf theRdBuf; WrBuf theWrBuf; HalfPipe theRd; // these refer to bufs; must go after them! HalfPipe theWr; protected: Socket theSock; NetAddr theAddr; mutable ConnMgr *theMgr; PortMgr *thePortMgr; // used to pass address to bind call const SslCtx *theSslCtx; // set by owner to request ssl encription SslSession *theSslSession; // set by owner if resumption is needed NetAddr theTunnel; // the other end of the tunnel if tunneling int theLocPort; mutable int theRemPort; // used as a cache for sock().rport() Time theOpenTime; Time theUseStart; // start of the current/last "use" int theUseCountLmt; // maximum total number of uses allowed int theUseLevelLmt; // maximum total number of uses allowed int theUseCnt; // number of "uses" since open() int theUseLvl; // number of current concurrent "uses" int theUseLvlMax; // maximum use level since open() CloseKind theCloseKind; // how the connection was closed Size theMaxIoSize; // per-io limit, reset after each IO int theLogCat; // log entry category bool isBad; bool isAtEof; bool isLastUse; // this must be the last use of the conn private: static int TheLastSeqId; int theSeqId; Ssl *theSsl; // created internally if needed }; #endif