From: Amos Jeffries Date: Sun, 31 Jan 2016 12:05:30 +0000 (+1300) Subject: SourceLayout: rename ClientSocketContext to Http::Stream X-Git-Tag: SQUID_4_0_5~14 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=898d1a09e1d9e8f39de5d34df6793197c0fc8dc4;p=thirdparty%2Fsquid.git SourceLayout: rename ClientSocketContext to Http::Stream ... and provided through http/libsquid-http.la. The name is chosen to match the RFC7540 HTTP/2 "stream" terminology. Which defines a stream as a bi-directional transaction, including request, reply and all related 1xx informational and/or control messages. That same word "stream" is also used in RFC7230 briefly to describe the same "transaction" scope and details. But not formalized until RFC7540. Http::Stream's may be initiated by a client HTTP request, Squid internally, or in HTTP/2 a server PUSH_PROMISE frame. There are no logic changes in this. Just symbol renaming and move. --- 898d1a09e1d9e8f39de5d34df6793197c0fc8dc4 diff --cc src/http/Stream.h index 0000000000,f467cbe129..946ff6337b mode 000000,100644..100644 --- a/src/http/Stream.h +++ b/src/http/Stream.h @@@ -1,0 -1,165 +1,166 @@@ + /* + * Copyright (C) 1996-2016 The Squid Software Foundation and contributors + * + * Squid software is distributed under GPLv2+ license and includes + * contributions from numerous individuals and organizations. + * Please see the COPYING and CONTRIBUTORS files for details. + */ + + #ifndef SQUID_SRC_HTTP_STREAM_H + #define SQUID_SRC_HTTP_STREAM_H + + #include "http/forward.h" + #include "mem/forward.h" + #include "StoreIOBuffer.h" + + class clientStreamNode; + class ClientHttpRequest; + + namespace Http + { + + /** + * The processing context for a single HTTP transaction (stream). + * - * A context lifetime extends from directly after a request has been parsed ++ * A stream lifetime extends from directly after a request has been parsed + * off the client connection buffer, until the last byte of both request - * and reply payload (if any) have been written. ++ * and reply payload (if any) have been written, or it is otherwise ++ * explicitly terminated. + * - * Contexts self-register with the Http::Server Pipeline being managed by the ++ * Streams self-register with the Http::Server Pipeline being managed by the + * Server for the connection on which the request was received. + * + * The socket level management and I/O is done by a Server which owns us. + * The scope of this objects control over a socket consists of the data + * buffer received from the Server with an initially unknown length. + * When that length is known it sets the end boundary of our access to the + * buffer. + * + * The individual processing actions are done by other Jobs which we start. + * - * When a context is completed the finished() method needs to be called which ++ * When a stream is completed the finished() method needs to be called which + * will perform all cleanup and deregistration operations. If the reason for + * finishing is an error, then notifyIoError() needs to be called prior to + * the finished() method. + * The caller should follow finished() with a call to ConnStateData::kick() + * to resume processing of other transactions or I/O on the connection. + * + * Alternatively the initiateClose() method can be called to terminate the - * whole client connection and all other pending contexts. ++ * whole client connection and all other pending streams. + * + * HTTP/1.x: + * + * When HTTP/1 pipeline is operating there may be multiple transactions using - * the client connection. Only the back() context may read from the connection, - * and only the front() context may write to it. A context which needs to read ++ * the client connection. Only the back() stream may read from the connection, ++ * and only the front() stream may write to it. A stream which needs to read + * or write to the connection but does not meet those criteria must be shifted + * to the deferred state. + * + * + * XXX: If an async call ends the ClientHttpRequest job, Http::Stream + * (and ConnStateData) may not know about it, leading to segfaults and + * assertions. This is difficult to fix + * because ClientHttpRequest lacks a good way to communicate its ongoing + * destruction back to the Http::Stream which pretends to "own" *http. + */ + class Stream : public RefCountable + { + MEMPROXY_CLASS(Stream); + + public: + /// construct with HTTP/1.x details + Stream(const Comm::ConnectionPointer &aConn, ClientHttpRequest *aReq); + ~Stream(); + + /// register this stream with the Server + void registerWithConn(); + + /// whether the reply has started being sent + bool startOfOutput() const; + + /// update stream state after a write, may initiate more I/O + void writeComplete(size_t size); + + /// get more data to send + void pullData(); + + /// \return true if the HTTP request is for multiple ranges + bool multipartRangeRequest() const; + + int64_t getNextRangeOffset() const; + bool canPackMoreRanges() const; + size_t lengthToSend(Range const &available) const; + + clientStream_status_t socketState(); + + /// send an HTTP reply message headers and maybe some initial payload + void sendStartOfMessage(HttpReply *, StoreIOBuffer bodyData); + /// send some HTTP reply message payload + void sendBody(StoreIOBuffer bodyData); + /// update stream state when N bytes are being sent. + /// NP: Http1Server bytes actually not sent yet, just packed into a MemBuf ready + void noteSentBodyBytes(size_t); + + /// add Range headers (if any) to the given HTTP reply message + void buildRangeHeader(HttpReply *); + + clientStreamNode * getTail() const; + clientStreamNode * getClientReplyContext() const; + + ConnStateData *getConn() const; + + /// update state to reflect I/O error + void noteIoError(const int xerrno); + + /// cleanup when the transaction has finished. may destroy 'this' + void finished(); + + /// terminate due to a send/write error (may continue reading) + void initiateClose(const char *reason); + + void deferRecipientForLater(clientStreamNode *, HttpReply *, StoreIOBuffer receivedData); + + public: // HTTP/1.x state data + + Comm::ConnectionPointer clientConnection; ///< details about the client connection socket + ClientHttpRequest *http; /* we pretend to own that Job */ + HttpReply *reply; + char reqbuf[HTTP_REQBUF_SZ]; + struct { + unsigned deferred:1; ///< This is a pipelined request waiting for the current object to complete + unsigned parsed_ok:1; ///< Was this parsed correctly? + } flags; + + bool mayUseConnection() const {return mayUseConnection_;} + + void mayUseConnection(bool aBool) { + mayUseConnection_ = aBool; + debugs(33, 3, "This " << this << " marked " << aBool); + } + + class DeferredParams + { + + public: + clientStreamNode *node; + HttpReply *rep; + StoreIOBuffer queuedBuffer; + }; + + DeferredParams deferredparams; + int64_t writtenToSocket; + + private: + void prepareReply(HttpReply *); + void packChunk(const StoreIOBuffer &bodyData, MemBuf &); + void packRange(StoreIOBuffer const &, MemBuf *); + void doClose(); + + bool mayUseConnection_; /* This request may use the connection. Don't read anymore requests for now */ + bool connRegistered_; + }; + + } // namespace Http + + #endif /* SQUID_SRC_HTTP_STREAM_H */ + diff --cc src/servers/FtpServer.h index d3ea1d5aec,8ec9435d6b..0ca4204f39 --- a/src/servers/FtpServer.h +++ b/src/servers/FtpServer.h @@@ -119,17 -110,9 +119,17 @@@ protected bool createDataConnection(Ip::Address cltAddr); void closeDataConnection(); + /// Called after data trasfer on client-to-squid data connection is + /// finished. + void userDataCompletionCheckpoint(int finalStatusCode); + + /// Writes the data-transfer status reply to the FTP client and + /// closes the data connection. + void completeDataExchange(); + void calcUri(const SBuf *file); void changeState(const Ftp::ServerState newState, const char *reason); - ClientSocketContext *handleUserRequest(const SBuf &cmd, SBuf ¶ms); + Http::Stream *handleUserRequest(const SBuf &cmd, SBuf ¶ms); bool checkDataConnPost() const; void replyDataWritingCheckpoint(); void maybeReadUploadData();