]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1996-2017 The Squid Software Foundation and contributors | |
3 | * | |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
9 | #ifndef SQUID_ESICONTEXT_H | |
10 | #define SQUID_ESICONTEXT_H | |
11 | ||
12 | #include "clientStream.h" | |
13 | #include "err_type.h" | |
14 | #include "esi/Element.h" | |
15 | #include "esi/Parser.h" | |
16 | #include "http/forward.h" | |
17 | #include "http/StatusCode.h" | |
18 | ||
19 | class ESIVarState; | |
20 | class ClientHttpRequest; | |
21 | ||
22 | /* ESIContext */ | |
23 | ||
24 | class ESIContext : public esiTreeParent, public ESIParserClient | |
25 | { | |
26 | CBDATA_CLASS(ESIContext); | |
27 | ||
28 | public: | |
29 | typedef RefCount<ESIContext> Pointer; | |
30 | ESIContext() : | |
31 | thisNode(NULL), | |
32 | http(NULL), | |
33 | errorpage(ERR_NONE), | |
34 | errorstatus(Http::scNone), | |
35 | errormessage(NULL), | |
36 | rep(NULL), | |
37 | outbound_offset(0), | |
38 | readpos(0), | |
39 | pos(0), | |
40 | varState(NULL), | |
41 | cachedASTInUse(false), | |
42 | reading_(true), | |
43 | processing(false) { | |
44 | memset(&flags, 0, sizeof(flags)); | |
45 | } | |
46 | ||
47 | ~ESIContext(); | |
48 | ||
49 | enum esiKick_t { | |
50 | ESI_KICK_FAILED, | |
51 | ESI_KICK_PENDING, | |
52 | ESI_KICK_SENT, | |
53 | ESI_KICK_INPROGRESS | |
54 | }; | |
55 | ||
56 | /* when esi processing completes */ | |
57 | void provideData(ESISegment::Pointer, ESIElement *source); | |
58 | void fail (ESIElement *source, char const*anError = NULL); | |
59 | void startRead(); | |
60 | void finishRead(); | |
61 | bool reading() const; | |
62 | void setError(); | |
63 | void setErrorMessage(char const *); | |
64 | ||
65 | void addStackElement (ESIElement::Pointer element); | |
66 | void addLiteral (const char *s, int len); | |
67 | ||
68 | void finishChildren (); | |
69 | ||
70 | clientStreamNode *thisNode; /* our stream node */ | |
71 | /* the request we are processing. HMM: cbdataReferencing this will result | |
72 | * in a circular reference, so we don't. Note: we are automatically freed | |
73 | * when it is, so thats ok. */ | |
74 | ClientHttpRequest *http; | |
75 | ||
76 | struct { | |
77 | int passthrough:1; | |
78 | int oktosend:1; | |
79 | int finished:1; | |
80 | ||
81 | /* an error has occured, send full body replies | |
82 | * regardless. Note that we don't fail midstream | |
83 | * because we buffer until we can not fail | |
84 | */ | |
85 | int error:1; | |
86 | ||
87 | int finishedtemplate:1; /* we've read the entire template */ | |
88 | int clientwantsdata:1; /* we need to satisfy a read request */ | |
89 | int kicked:1; /* note on reentering the kick routine */ | |
90 | int detached:1; /* our downstream has detached */ | |
91 | } flags; | |
92 | ||
93 | err_type errorpage; /* if we error what page to use */ | |
94 | Http::StatusCode errorstatus; /* if we error, what code to return */ | |
95 | char *errormessage; /* error to pass to error page */ | |
96 | HttpReplyPointer rep; /* buffered until we pass data downstream */ | |
97 | ESISegment::Pointer buffered; /* unprocessed data - for whatever reason */ | |
98 | ESISegment::Pointer incoming; | |
99 | /* processed data we are waiting to send, or for | |
100 | * potential errors to be resolved | |
101 | */ | |
102 | ESISegment::Pointer outbound; | |
103 | ESISegment::Pointer outboundtail; /* our write segment */ | |
104 | /* the offset to the next character to send - | |
105 | * non zero if we haven't sent the entire segment | |
106 | * for some reason | |
107 | */ | |
108 | size_t outbound_offset; | |
109 | int64_t readpos; /* the logical position we are reading from */ | |
110 | int64_t pos; /* the logical position of outbound_offset in the data stream */ | |
111 | ||
112 | class ParserState | |
113 | { | |
114 | ||
115 | public: | |
116 | ESIElement::Pointer stack[10]; /* a stack of esi elements that are open */ | |
117 | int stackdepth; /* self explanatory */ | |
118 | ESIParser::Pointer theParser; | |
119 | ESIElement::Pointer top(); | |
120 | void init (ESIParserClient *); | |
121 | bool inited() const; | |
122 | ParserState(); | |
123 | void freeResources(); | |
124 | void popAll(); | |
125 | int parsing:1; /* libexpat is not reentrant on the same context */ | |
126 | ||
127 | private: | |
128 | bool inited_; | |
129 | } | |
130 | ||
131 | parserState; /* todo factor this off somewhere else; */ | |
132 | ESIVarState *varState; | |
133 | ESIElement::Pointer tree; | |
134 | ||
135 | esiKick_t kick (); | |
136 | RefCount<ESIContext> cbdataLocker; | |
137 | bool failed() const {return flags.error != 0;} | |
138 | ||
139 | bool cachedASTInUse; | |
140 | ||
141 | private: | |
142 | void fail (); | |
143 | void freeResources(); | |
144 | void fixupOutboundTail(); | |
145 | void trimBlanks(); | |
146 | size_t send (); | |
147 | bool reading_; | |
148 | void appendOutboundData(ESISegment::Pointer theData); | |
149 | esiProcessResult_t process (); | |
150 | void parse(); | |
151 | void parseOneBuffer(); | |
152 | void updateCachedAST(); | |
153 | bool hasCachedAST() const; | |
154 | void getCachedAST(); | |
155 | virtual void start(const char *el, const char **attr, size_t attrCount); | |
156 | virtual void end(const char *el); | |
157 | virtual void parserDefault (const char *s, int len); | |
158 | virtual void parserComment (const char *s); | |
159 | bool processing; | |
160 | }; | |
161 | ||
162 | #endif /* SQUID_ESICONTEXT_H */ | |
163 |