|
1 /** @file |
|
2 * Copyright (c) 2005-2006 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: CUpnpHttpChunkFileTransferReader is a class responsible for |
|
15 * asynchronous TCP reading and controlling data |
|
16 * |
|
17 */ |
|
18 |
|
19 |
|
20 |
|
21 #include "upnphttpsession.h" |
|
22 #define KLogFile _L("DLNAWebServer.txt") |
|
23 #include "upnpcustomlog.h" |
|
24 #include "upnphttpfiletransferreader.h" |
|
25 #include "upnphttpchunkfiletransferreader.h" |
|
26 #include "upnphttpchunkparser.h" |
|
27 #include "upnphttpfileaccess.h" |
|
28 #include "inet6err.h" |
|
29 |
|
30 // ======== MEMBER FUNCTIONS ======== |
|
31 |
|
32 // --------------------------------------------------------------------------- |
|
33 // CUpnpHttpChunkFileTransferReader::NewL |
|
34 // Factory method. |
|
35 // --------------------------------------------------------------------------- |
|
36 // |
|
37 CUpnpHttpChunkFileTransferReader* CUpnpHttpChunkFileTransferReader::NewL( |
|
38 CUpnpTcpSession& aSession, |
|
39 RSocket& aSocket, |
|
40 TThreadPriority aPriority, |
|
41 TInt aReadPortion, |
|
42 TInt aBufferSize) |
|
43 { |
|
44 CUpnpHttpChunkFileTransferReader* self = new ( ELeave ) |
|
45 CUpnpHttpChunkFileTransferReader( aSession, aSocket, |
|
46 aPriority, aReadPortion, aBufferSize); |
|
47 CleanupStack::PushL( self ); |
|
48 self->ConstructL(); |
|
49 CleanupStack::Pop( self ); |
|
50 return self; |
|
51 } |
|
52 |
|
53 // --------------------------------------------------------------------------- |
|
54 // CUpnpHttpChunkFileTransferReader::CUpnpHttpChunkFileTransferReader |
|
55 // C++ constructor. |
|
56 // --------------------------------------------------------------------------- |
|
57 // |
|
58 CUpnpHttpChunkFileTransferReader::CUpnpHttpChunkFileTransferReader( CUpnpTcpSession& aSession, |
|
59 RSocket& aSocket, |
|
60 TThreadPriority aPriority, |
|
61 TInt aReadPortion, |
|
62 TInt aBufferSize) |
|
63 :CUpnpHttpFileTransferReader( aSession, aSocket, |
|
64 aPriority, aReadPortion, aBufferSize + aReadPortion), |
|
65 iDecoded(0) |
|
66 { |
|
67 } |
|
68 |
|
69 // --------------------------------------------------------------------------- |
|
70 // CUpnpHttpChunkFileTransferReader::ConstructL |
|
71 // Two-phased constructor |
|
72 // constructor that can leave. Used from derived classes. |
|
73 // --------------------------------------------------------------------------- |
|
74 // |
|
75 void CUpnpHttpChunkFileTransferReader::ConstructL() |
|
76 { |
|
77 BaseConstructL(); |
|
78 |
|
79 iParser = CUpnpHttpChunkParser::NewL(); |
|
80 } |
|
81 // --------------------------------------------------------------------------- |
|
82 // CUpnpHttpChunkFileTransferReader::~CUpnpHttpChunkFileTransferReader |
|
83 // Destructor. |
|
84 // --------------------------------------------------------------------------- |
|
85 // |
|
86 CUpnpHttpChunkFileTransferReader::~CUpnpHttpChunkFileTransferReader() |
|
87 { |
|
88 delete iParser; |
|
89 } |
|
90 |
|
91 // --------------------------------------------------------------------------- |
|
92 // CUpnpHttpChunkFileTransferReader::RemainingBytes |
|
93 // Returns the remaining numbers of bytes to read |
|
94 // --------------------------------------------------------------------------- |
|
95 // |
|
96 TInt CUpnpHttpChunkFileTransferReader::RemainingBytes() |
|
97 { |
|
98 if( !iSession.FileAccess() ) |
|
99 return KErrNone; |
|
100 |
|
101 return ( iSession.FileAccess()->TransferTotal()-iSession.FileAccess()->BytesWritten() ); |
|
102 } |
|
103 |
|
104 // --------------------------------------------------------------------------- |
|
105 // CUpnpHttpFileTransferReader::Start |
|
106 // Starts reading. |
|
107 // --------------------------------------------------------------------------- |
|
108 // |
|
109 void CUpnpHttpChunkFileTransferReader::StartL() |
|
110 { |
|
111 LOGS1( "%i, CUpnpHttpFileTransferReader::Start", iSession.Id() ); |
|
112 |
|
113 // Initiate a new read from socket into iBuffer |
|
114 if ( !IsActive() ) |
|
115 { |
|
116 |
|
117 //checks buffer buffer is not empty |
|
118 if(iCacheBuffer.Length() > 0) |
|
119 { |
|
120 //check buffer session should be finished |
|
121 iIsFinished = HandleL(); |
|
122 if(iIsFinished) |
|
123 { |
|
124 Finish(); |
|
125 |
|
126 if( iSession.FileAccess() ) |
|
127 iSession.FileAccess()->SetChunkCompleted( iIsFinished ); |
|
128 } |
|
129 //if not issue reading |
|
130 else |
|
131 { |
|
132 IssueRead(); |
|
133 iSession.StartTimeoutTimer(ETrue); |
|
134 } |
|
135 |
|
136 } |
|
137 else |
|
138 { |
|
139 IssueRead(); |
|
140 } |
|
141 |
|
142 } |
|
143 } |
|
144 |
|
145 // --------------------------------------------------------------------------- |
|
146 // CUpnpHttpChunkFileTransferReader::ReadBufferSize |
|
147 // Returns the maximum size of bytes to read for once |
|
148 // --------------------------------------------------------------------------- |
|
149 // |
|
150 TInt CUpnpHttpChunkFileTransferReader::ReadBufferSize() |
|
151 { |
|
152 return(AvailableSpace()); |
|
153 } |
|
154 |
|
155 // ----------------------------------------------------------------------------- |
|
156 // CUpnpHttpChunkParser::Parse |
|
157 // Decoding the chunked-encoded buffer |
|
158 // ----------------------------------------------------------------------------- |
|
159 // |
|
160 TInt CUpnpHttpChunkFileTransferReader::Parse( TDes8& aBuffer, TInt& aPos ) |
|
161 { |
|
162 if( aPos >= aBuffer.Length() ) |
|
163 { |
|
164 iParser->SetErrorState(); |
|
165 return ETrue; |
|
166 } |
|
167 return iParser->Parse( aBuffer, aPos ); |
|
168 } |
|
169 |
|
170 // --------------------------------------------------------------------------- |
|
171 // CUpnpHttpChunkFileTransferReader::HandleL |
|
172 // Handles data in buffer, returns if file transfer has finished |
|
173 // --------------------------------------------------------------------------- |
|
174 // |
|
175 TBool CUpnpHttpChunkFileTransferReader::HandleL() |
|
176 { |
|
177 TInt error = KErrGeneral; |
|
178 |
|
179 error = Parse(iCacheBuffer, iDecoded); |
|
180 |
|
181 if( error == KErrNone && iSession.FileAccess() ) |
|
182 { |
|
183 if ( iSession.FileAccess()->TransferTotal() == KErrNotFound ) |
|
184 { |
|
185 iSession.FileAccess()->SetTransferTotal( 0 ); |
|
186 } |
|
187 //parser finished decoding - writing all bytes |
|
188 if ( iParser->IsFinished() ) |
|
189 { |
|
190 error = HandleReadDataL( iDecoded ); |
|
191 } |
|
192 //buffer almost full - writing a fixed block of decoded data |
|
193 else if ( iBufferSize - iDecoded <= iReadBufferSize ) |
|
194 { |
|
195 error = HandleReadDataL( iBufferSize - iReadBufferSize ); |
|
196 } |
|
197 } |
|
198 iCacheBuffer.ReAllocL( iBufferSize ); |
|
199 |
|
200 if( error != KErrNone ) |
|
201 { |
|
202 iSession.FileTransferReaderErrorL( error ); |
|
203 return ETrue; |
|
204 } |
|
205 else if( iParser->IsFinished() ) |
|
206 { |
|
207 if ( iSession.FileAccess() ) |
|
208 { |
|
209 iSession.FileAccess()->SetChunkCompleted( ETrue ); |
|
210 } |
|
211 iSession.FileTransferReaderDoneL(); |
|
212 return ETrue; |
|
213 } |
|
214 |
|
215 return EFalse; |
|
216 } |
|
217 |
|
218 // --------------------------------------------------------------------------- |
|
219 // CUpnpHttpChunkFileTransferReader::HandleReadDataL |
|
220 // Handles read data - trims the buffer and save data to file |
|
221 // --------------------------------------------------------------------------- |
|
222 // |
|
223 TInt CUpnpHttpChunkFileTransferReader::HandleReadDataL( TInt aPieceToRead ) |
|
224 { |
|
225 //reads decoded data |
|
226 TPtr8 ptr = iCacheBuffer.LeftTPtr( aPieceToRead ); |
|
227 |
|
228 //saves decoded data |
|
229 TInt error = iSession.FileAccess()->SaveL( ptr ); |
|
230 iSession.FileAccess()->SetTransferTotal( |
|
231 iSession.FileAccess()->TransferTotal() + aPieceToRead ); |
|
232 |
|
233 //saved data are cut from buffer |
|
234 iCacheBuffer.Delete( 0, aPieceToRead ); |
|
235 |
|
236 //position adjusted to the number of still encoded bytes |
|
237 iDecoded -= aPieceToRead; |
|
238 |
|
239 return error; |
|
240 } |
|
241 |
|
242 // --------------------------------------------------------------------------- |
|
243 // CUpnpHttpChunkFileTransferReader::Finish |
|
244 // On finishing the file transfer |
|
245 // --------------------------------------------------------------------------- |
|
246 // |
|
247 void CUpnpHttpChunkFileTransferReader::Finish() |
|
248 { |
|
249 CUpnpHttpFileTransferReader::Finish(); |
|
250 } |
|
251 |
|
252 // --------------------------------------------------------------------------- |
|
253 // CUpnpHttpChunkFileTransferReader::RunL |
|
254 // From class CActive. |
|
255 // Function is called as a callback when the issued reading is completed. |
|
256 // --------------------------------------------------------------------------- |
|
257 // |
|
258 void CUpnpHttpChunkFileTransferReader::RunL() |
|
259 { |
|
260 LOGS2( "%i, CUpnpHttpChunkFileTransferReader::RunL(), iStatus %i", |
|
261 iSession.Id(), iStatus.Int() ); |
|
262 |
|
263 // Active object request complete handler |
|
264 switch ( iStatus.Int() ) |
|
265 { |
|
266 case KErrNone: |
|
267 iRetryErrorCount = 0; |
|
268 iCancelTimer->Cancel(); |
|
269 |
|
270 iSession.TimerCancel(); |
|
271 iCacheBuffer.SetLength( iCacheBuffer.Length() + iLen() ); |
|
272 iIsFinished = HandleL(); |
|
273 |
|
274 if(!iIsFinished) |
|
275 { |
|
276 IssueRead(); |
|
277 iSession.StartTimeoutTimer(ETrue); |
|
278 } |
|
279 else |
|
280 Finish(); |
|
281 break; |
|
282 |
|
283 case KErrCancel: |
|
284 if(iCancelFromTimer) |
|
285 { |
|
286 IssueRead(); |
|
287 iCancelFromTimer = EFalse; |
|
288 } |
|
289 break; |
|
290 case KErrEof: |
|
291 iSession.TimerCancel(); |
|
292 iCacheBuffer.SetLength( iLen() ); |
|
293 iIsFinished = HandleL(); |
|
294 |
|
295 if(iIsFinished) |
|
296 { |
|
297 iSession.HandleErrorL( iStatus.Int() ); |
|
298 break; |
|
299 } |
|
300 case KErrNoMemory: |
|
301 case KErrNotReady: |
|
302 case KErrInet6AddressExpired: |
|
303 if( iRetryErrorCount < KMaxRetryErrors ) |
|
304 { |
|
305 iRetryTimer->Cancel(); |
|
306 iRetryTimer->After( KRetryWaitTime * ++iRetryErrorCount, EFalse ); |
|
307 break; |
|
308 } |
|
309 |
|
310 default: |
|
311 iIsFinished = ETrue; |
|
312 iIsActivated = EFalse; |
|
313 iSession.HandleErrorL( iStatus.Int() ); |
|
314 break; |
|
315 } |
|
316 if( iSession.FileAccess() ) |
|
317 iSession.FileAccess()->SetChunkCompleted( iIsFinished ); |
|
318 } |
|
319 |
|
320 // ----------------------------------------------------------------------------- |
|
321 // CUpnpHttpChunkFileTransferReader::RunError |
|
322 // From CActive. |
|
323 // Invoked when RunL leaves. |
|
324 // ----------------------------------------------------------------------------- |
|
325 // |
|
326 TInt CUpnpHttpChunkFileTransferReader::RunError( TInt aErr ) |
|
327 { |
|
328 LOGS1("CUpnpHttpChunkFileTransferReader::RunError(%d)", aErr); |
|
329 return KErrNone; |
|
330 } |
|
331 |
|
332 // --------------------------------------------------------------------------- |
|
333 // CUpnpHttpChunkFileTransferReader::Reset |
|
334 // Makes reader ready to start reading new content |
|
335 // --------------------------------------------------------------------------- |
|
336 // |
|
337 void CUpnpHttpChunkFileTransferReader::Reset() |
|
338 { |
|
339 iCacheBuffer.SetLength(0); |
|
340 iDecoded = 0; |
|
341 iParser->Reset(); |
|
342 } |
|
343 |
|
344 // --------------------------------------------------------------------------- |
|
345 // CUpnpHttpChunkFileTransferReader::ReadFromSocket |
|
346 // Reads from the socket |
|
347 // --------------------------------------------------------------------------- |
|
348 // |
|
349 void CUpnpHttpChunkFileTransferReader::ReadFromSocket() |
|
350 { |
|
351 Deque(); |
|
352 CActiveScheduler::Add(this); |
|
353 |
|
354 iReceivePtr.Set( (TUint8*)iCacheBuffer.RightTPtr( 0 ).Ptr(), ReadBufferSize(), ReadBufferSize() ); |
|
355 StartCancelTimer(); |
|
356 iSocket.RecvOneOrMore( iReceivePtr,0,iStatus,iLen); |
|
357 SetActive(); |
|
358 } |
|
359 |
|
360 // End of File |