1 : /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
2 : /* ***** BEGIN LICENSE BLOCK *****
3 : * Version: MPL 1.1/GPL 2.0/LGPL 2.1
4 : *
5 : * The contents of this file are subject to the Mozilla Public License Version
6 : * 1.1 (the "License"); you may not use this file except in compliance with
7 : * the License. You may obtain a copy of the License at
8 : * http://www.mozilla.org/MPL/
9 : *
10 : * Software distributed under the License is distributed on an "AS IS" basis,
11 : * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
12 : * for the specific language governing rights and limitations under the
13 : * License.
14 : *
15 : * The Original Code is Mozilla.
16 : *
17 : * The Initial Developer of the Original Code is
18 : * Netscape Communications.
19 : * Portions created by the Initial Developer are Copyright (C) 2001
20 : * the Initial Developer. All Rights Reserved.
21 : *
22 : * Contributor(s):
23 : * Darin Fisher <darin@netscape.com> (original author)
24 : *
25 : * Alternatively, the contents of this file may be used under the terms of
26 : * either the GNU General Public License Version 2 or later (the "GPL"), or
27 : * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 : * in which case the provisions of the GPL or the LGPL are applicable instead
29 : * of those above. If you wish to allow use of your version of this file only
30 : * under the terms of either the GPL or the LGPL, and not to allow others to
31 : * use your version of this file under the terms of the MPL, indicate your
32 : * decision by deleting the provisions above and replace them with the notice
33 : * and other provisions required by the GPL or the LGPL. If you do not delete
34 : * the provisions above, a recipient may use your version of this file under
35 : * the terms of any one of the MPL, the GPL or the LGPL.
36 : *
37 : * ***** END LICENSE BLOCK ***** */
38 :
39 : #ifndef nsHttpTransaction_h__
40 : #define nsHttpTransaction_h__
41 :
42 : #include "nsHttp.h"
43 : #include "nsHttpHeaderArray.h"
44 : #include "nsAHttpTransaction.h"
45 : #include "nsAHttpConnection.h"
46 : #include "nsCOMPtr.h"
47 :
48 : #include "nsIPipe.h"
49 : #include "nsIInputStream.h"
50 : #include "nsIOutputStream.h"
51 : #include "nsIInterfaceRequestor.h"
52 : #include "nsISocketTransportService.h"
53 : #include "nsITransport.h"
54 : #include "nsIEventTarget.h"
55 : #include "TimingStruct.h"
56 :
57 : //-----------------------------------------------------------------------------
58 :
59 : class nsHttpTransaction;
60 : class nsHttpRequestHead;
61 : class nsHttpResponseHead;
62 : class nsHttpChunkedDecoder;
63 : class nsIHttpActivityObserver;
64 :
65 : //-----------------------------------------------------------------------------
66 : // nsHttpTransaction represents a single HTTP transaction. It is thread-safe,
67 : // intended to run on the socket thread.
68 : //-----------------------------------------------------------------------------
69 :
70 : class nsHttpTransaction : public nsAHttpTransaction
71 : , public nsIInputStreamCallback
72 : , public nsIOutputStreamCallback
73 : {
74 : public:
75 : NS_DECL_ISUPPORTS
76 : NS_DECL_NSAHTTPTRANSACTION
77 : NS_DECL_NSIINPUTSTREAMCALLBACK
78 : NS_DECL_NSIOUTPUTSTREAMCALLBACK
79 :
80 : nsHttpTransaction();
81 : virtual ~nsHttpTransaction();
82 :
83 : //
84 : // called to initialize the transaction
85 : //
86 : // @param caps
87 : // the transaction capabilities (see nsHttp.h)
88 : // @param connInfo
89 : // the connection type for this transaction.
90 : // @param reqHeaders
91 : // the request header struct
92 : // @param reqBody
93 : // the request body (POST or PUT data stream)
94 : // @param reqBodyIncludesHeaders
95 : // fun stuff to support NPAPI plugins.
96 : // @param target
97 : // the dispatch target were notifications should be sent.
98 : // @param callbacks
99 : // the notification callbacks to be given to PSM.
100 : // @param responseBody
101 : // the input stream that will contain the response data. async
102 : // wait on this input stream for data. on first notification,
103 : // headers should be available (check transaction status).
104 : //
105 : nsresult Init(PRUint8 caps,
106 : nsHttpConnectionInfo *connInfo,
107 : nsHttpRequestHead *reqHeaders,
108 : nsIInputStream *reqBody,
109 : bool reqBodyIncludesHeaders,
110 : nsIEventTarget *consumerTarget,
111 : nsIInterfaceRequestor *callbacks,
112 : nsITransportEventSink *eventsink,
113 : nsIAsyncInputStream **responseBody);
114 :
115 : // attributes
116 17944 : PRUint8 Caps() { return mCaps; }
117 3130 : nsHttpConnectionInfo *ConnectionInfo() { return mConnInfo; }
118 : nsHttpResponseHead *ResponseHead() { return mHaveAllHeaders ? mResponseHead : nsnull; }
119 2977 : nsISupports *SecurityInfo() { return mSecurityInfo; }
120 :
121 : nsIInterfaceRequestor *Callbacks() { return mCallbacks; }
122 : nsIEventTarget *ConsumerTarget() { return mConsumerTarget; }
123 :
124 : // Called to take ownership of the response headers; the transaction
125 : // will drop any reference to the response headers after this call.
126 : nsHttpResponseHead *TakeResponseHead();
127 :
128 : // Called to find out if the transaction generated a complete response.
129 : bool ResponseIsComplete() { return mResponseIsComplete; }
130 :
131 2876 : bool SSLConnectFailed() { return mSSLConnectFailed; }
132 :
133 : // SetPriority() may only be used by the connection manager.
134 2977 : void SetPriority(PRInt32 priority) { mPriority = priority; }
135 3191 : PRInt32 Priority() { return mPriority; }
136 :
137 2977 : const TimingStruct& Timings() const { return mTimings; }
138 :
139 : private:
140 : nsresult Restart();
141 : char *LocateHttpStart(char *buf, PRUint32 len,
142 : bool aAllowPartialMatch);
143 : nsresult ParseLine(char *line);
144 : nsresult ParseLineSegment(char *seg, PRUint32 len);
145 : nsresult ParseHead(char *, PRUint32 count, PRUint32 *countRead);
146 : nsresult HandleContentStart();
147 : nsresult HandleContent(char *, PRUint32 count, PRUint32 *contentRead, PRUint32 *contentRemaining);
148 : nsresult ProcessData(char *, PRUint32, PRUint32 *);
149 : void DeleteSelfOnConsumerThread();
150 :
151 : static NS_METHOD ReadRequestSegment(nsIInputStream *, void *, const char *,
152 : PRUint32, PRUint32, PRUint32 *);
153 : static NS_METHOD WritePipeSegment(nsIOutputStream *, void *, char *,
154 : PRUint32, PRUint32, PRUint32 *);
155 :
156 37423 : bool TimingEnabled() const { return mCaps & NS_HTTP_TIMING_ENABLED; }
157 :
158 : private:
159 : nsCOMPtr<nsIInterfaceRequestor> mCallbacks;
160 : nsCOMPtr<nsITransportEventSink> mTransportSink;
161 : nsCOMPtr<nsIEventTarget> mConsumerTarget;
162 : nsCOMPtr<nsISupports> mSecurityInfo;
163 : nsCOMPtr<nsIAsyncInputStream> mPipeIn;
164 : nsCOMPtr<nsIAsyncOutputStream> mPipeOut;
165 :
166 : nsCOMPtr<nsISupports> mChannel;
167 : nsCOMPtr<nsIHttpActivityObserver> mActivityDistributor;
168 :
169 : nsCString mReqHeaderBuf; // flattened request headers
170 : nsCOMPtr<nsIInputStream> mRequestStream;
171 : PRUint32 mRequestSize;
172 :
173 : nsAHttpConnection *mConnection; // hard ref
174 : nsHttpConnectionInfo *mConnInfo; // hard ref
175 : nsHttpRequestHead *mRequestHead; // weak ref
176 : nsHttpResponseHead *mResponseHead; // hard ref
177 :
178 : nsAHttpSegmentReader *mReader;
179 : nsAHttpSegmentWriter *mWriter;
180 :
181 : nsCString mLineBuf; // may contain a partial line
182 :
183 : PRInt64 mContentLength; // equals -1 if unknown
184 : PRInt64 mContentRead; // count of consumed content bytes
185 :
186 : // After a 304/204 or other "no-content" style response we will skip over
187 : // up to MAX_INVALID_RESPONSE_BODY_SZ bytes when looking for the next
188 : // response header to deal with servers that actually sent a response
189 : // body where they should not have. This member tracks how many bytes have
190 : // so far been skipped.
191 : PRUint32 mInvalidResponseBytesRead;
192 :
193 : nsHttpChunkedDecoder *mChunkedDecoder;
194 :
195 : TimingStruct mTimings;
196 :
197 : nsresult mStatus;
198 :
199 : PRInt16 mPriority;
200 :
201 : PRUint16 mRestartCount; // the number of times this transaction has been restarted
202 : PRUint8 mCaps;
203 :
204 : // state flags, all logically boolean, but not packed together into a
205 : // bitfield so as to avoid bitfield-induced races. See bug 560579.
206 : bool mClosed;
207 : bool mConnected;
208 : bool mHaveStatusLine;
209 : bool mHaveAllHeaders;
210 : bool mTransactionDone;
211 : bool mResponseIsComplete;
212 : bool mDidContentStart;
213 : bool mNoContent; // expecting an empty entity body
214 : bool mSentData;
215 : bool mReceivedData;
216 : bool mStatusEventPending;
217 : bool mHasRequestBody;
218 : bool mSSLConnectFailed;
219 : bool mHttpResponseMatched;
220 : bool mPreserveStream;
221 :
222 : // mClosed := transaction has been explicitly closed
223 : // mTransactionDone := transaction ran to completion or was interrupted
224 : // mResponseComplete := transaction ran to completion
225 : };
226 :
227 : #endif // nsHttpTransaction_h__
|