|
1 /** @file |
|
2 * Copyright (c) 2007 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: Handles upload of one file |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 // User include files |
|
20 #include "httpuploadworker.h" |
|
21 |
|
22 // Constants |
|
23 _LIT8( KModuleName, "HttpTransfer" ); |
|
24 _LIT8( KAllowedData, "*/*" ); |
|
25 _LIT8( KContentTypeName, "Content-Type" ); |
|
26 _LIT8( KDefaultContentType, "text/plain" ); |
|
27 _LIT8( KExpect, "Expect" ); |
|
28 _LIT8( K100Continue, "100-continue" ); |
|
29 |
|
30 const TUint KDefaultBufferSize = 64*KKilo; |
|
31 const TUint KMaxBufferSize = 128*KKilo; |
|
32 |
|
33 // Time to wait for response after sending 100 continue post request. |
|
34 // Value in microseconds. |
|
35 const TInt K100ContinueResponseWaitTime = 3000000; // 3 seconds |
|
36 |
|
37 // ======== MEMBER FUNCTIONS ======== |
|
38 |
|
39 // -------------------------------------------------------------------------- |
|
40 // CHttpUploadWorker::CHttpUploadWorker() |
|
41 // (See comments in header file) |
|
42 // -------------------------------------------------------------------------- |
|
43 // |
|
44 CHttpUploadWorker::CHttpUploadWorker( MHttpTransferObserver& aObserver, |
|
45 TUint /*aIAPId*/, |
|
46 TUint aBufferSize, |
|
47 MHttpWorkerObserver& aCallback ) |
|
48 { |
|
49 iObserver = &aObserver; |
|
50 iCallback = &aCallback; |
|
51 |
|
52 iProcessState = EHttpTransactionIdle; |
|
53 |
|
54 // Check that size of the buffer is between boundaries |
|
55 if ( aBufferSize <= 0 ) |
|
56 { |
|
57 iBufferSize = KDefaultBufferSize; |
|
58 } |
|
59 else if ( aBufferSize > KMaxBufferSize ) |
|
60 { |
|
61 iBufferSize = KMaxBufferSize; |
|
62 } |
|
63 else |
|
64 { |
|
65 iBufferSize = aBufferSize; |
|
66 } |
|
67 |
|
68 iSendDataCount = 0; |
|
69 iBodyFileOffset = 0; |
|
70 iHttpStatus = 0; |
|
71 iMoreToCome = EFalse; |
|
72 iAlreadyDone = EFalse; |
|
73 } |
|
74 |
|
75 // -------------------------------------------------------------------------- |
|
76 // CHttpUploadWorker::ConstructL() |
|
77 // (See comments in header file) |
|
78 // -------------------------------------------------------------------------- |
|
79 // |
|
80 void CHttpUploadWorker::ConstructL() |
|
81 { |
|
82 CHttpTransferWorker::ConstructL(); |
|
83 ConnectL(); |
|
84 iSessionTimer = CHttpNotifyTimer::NewL( this ); |
|
85 } |
|
86 |
|
87 // -------------------------------------------------------------------------- |
|
88 // CHttpUploadWorker::NewL() |
|
89 // (See comments in header file) |
|
90 // -------------------------------------------------------------------------- |
|
91 // |
|
92 CHttpUploadWorker* CHttpUploadWorker::NewL( |
|
93 MHttpTransferObserver& aObserver, |
|
94 TUint aIAPId, |
|
95 TUint aBufferSize, |
|
96 MHttpWorkerObserver& aCallback ) |
|
97 { |
|
98 CHttpUploadWorker* self = CHttpUploadWorker::NewLC( aObserver, |
|
99 aIAPId, |
|
100 aBufferSize, |
|
101 aCallback ); |
|
102 CleanupStack::Pop( self ); |
|
103 return self; |
|
104 } |
|
105 |
|
106 // -------------------------------------------------------------------------- |
|
107 // CHttpUploadWorker::NewLC() |
|
108 // (See comments in header file) |
|
109 // -------------------------------------------------------------------------- |
|
110 // |
|
111 CHttpUploadWorker* CHttpUploadWorker::NewLC( |
|
112 MHttpTransferObserver& aObserver, |
|
113 TUint aIAPId, |
|
114 TUint aBufferSize, |
|
115 MHttpWorkerObserver& aCallback ) |
|
116 { |
|
117 CHttpUploadWorker* self = new( ELeave ) CHttpUploadWorker( aObserver, |
|
118 aIAPId, |
|
119 aBufferSize, |
|
120 aCallback ); |
|
121 CleanupStack::PushL( self ); |
|
122 self->ConstructL(); |
|
123 return self; |
|
124 } |
|
125 |
|
126 // -------------------------------------------------------------------------- |
|
127 // CHttpUploadWorker::~CHttpUploadWorker() |
|
128 // (See comments in header file) |
|
129 // -------------------------------------------------------------------------- |
|
130 // |
|
131 CHttpUploadWorker::~CHttpUploadWorker() |
|
132 { |
|
133 delete iRequestBodyBuffer; |
|
134 delete iSessionTimer; |
|
135 |
|
136 // Destroy the 100 continue timer if it exists. |
|
137 Destroy100ContinueTimer(); |
|
138 } |
|
139 |
|
140 // -------------------------------------------------------------------------- |
|
141 // CHttpUploadWorker::CancelTransfer() |
|
142 // (See comments in header file) |
|
143 // -------------------------------------------------------------------------- |
|
144 // |
|
145 void CHttpUploadWorker::CancelTransfer() |
|
146 { |
|
147 iSessionTimer->Cancel(); |
|
148 |
|
149 // Destroy the 100 continue response wait timer if it exists. |
|
150 Destroy100ContinueTimer(); |
|
151 |
|
152 if ( iProcessState == EHttpWaitingForStart ) |
|
153 { |
|
154 delete iProcessedFile; |
|
155 iProcessedFile = NULL; |
|
156 iProcessState = EHttpTransactionIdle; |
|
157 iCallback->WorkerCompleted(); |
|
158 } |
|
159 // if process is finished do nothing |
|
160 else if ( iProcessState != EHttpTransactionIdle ) |
|
161 { |
|
162 iHttpTransaction.Cancel(); |
|
163 |
|
164 delete iRequestBodyBuffer; |
|
165 iRequestBodyBuffer = NULL; |
|
166 |
|
167 iProcessState = EHttpTransactionIdle; |
|
168 iHttpTransaction.Close(); |
|
169 |
|
170 // call reset so that this worker can be used for the next download |
|
171 Reset(); |
|
172 |
|
173 delete iProcessedFile; |
|
174 iProcessedFile = NULL; |
|
175 |
|
176 iOverallDataSize = 0; |
|
177 iFile.Close(); |
|
178 |
|
179 // inform the worker observer |
|
180 iCallback->WorkerCompleted(); |
|
181 } |
|
182 } |
|
183 |
|
184 // -------------------------------------------------------------------------- |
|
185 // CHttpUploadWorker::MapPostTransactionError() |
|
186 // (See comments in header file) |
|
187 // -------------------------------------------------------------------------- |
|
188 // |
|
189 TInt CHttpUploadWorker::MapPostTransactionError( TInt aError ) const |
|
190 { |
|
191 TInt error = KErrNone; |
|
192 switch (aError) |
|
193 { |
|
194 case HTTPStatus::EForbidden: |
|
195 { |
|
196 error = KErrAccessDenied; |
|
197 break; |
|
198 } |
|
199 |
|
200 case HTTPStatus::EMethodNotAllowed: |
|
201 { |
|
202 error = KErrAccessDenied; |
|
203 break; |
|
204 } |
|
205 |
|
206 case HTTPStatus::EConflict: |
|
207 { |
|
208 // resource already exists . |
|
209 error = KErrAlreadyExists; |
|
210 break; |
|
211 } |
|
212 |
|
213 case HTTPStatus::EUnsupportedMediaType: |
|
214 { |
|
215 error = KErrNotSupported; |
|
216 break; |
|
217 } |
|
218 |
|
219 case HTTPStatus::EInternalServerError: |
|
220 { |
|
221 error = KErrNotSupported; |
|
222 break; |
|
223 } |
|
224 |
|
225 case HTTPStatus::EMovedPermanently: |
|
226 { |
|
227 // fall through |
|
228 } |
|
229 |
|
230 case HTTPStatus::ETemporaryRedirect: |
|
231 { |
|
232 // It is not allowed to write a file with the same name |
|
233 // as an existing directory. |
|
234 error = KErrGeneral; |
|
235 break; |
|
236 } |
|
237 |
|
238 default: |
|
239 { |
|
240 if ( HTTPStatus::IsServerError( aError ) ) |
|
241 { |
|
242 error = KErrNotSupported; |
|
243 } |
|
244 else if ( HTTPStatus::IsClientError( aError ) ) |
|
245 { |
|
246 error = KErrAccessDenied; |
|
247 } |
|
248 else if ( HTTPStatus::IsRedirection( aError ) ) |
|
249 { |
|
250 error = KErrNotFound; |
|
251 } |
|
252 else |
|
253 { |
|
254 if ( aError > 0 ) |
|
255 { |
|
256 // An arbitrary choice for error codes that |
|
257 // should not occur |
|
258 error = KErrAccessDenied; |
|
259 } |
|
260 } |
|
261 break; |
|
262 } |
|
263 } |
|
264 |
|
265 return error; |
|
266 } |
|
267 |
|
268 // -------------------------------------------------------------------------- |
|
269 // CHttpUploadWorker::CompleteAndNotify() |
|
270 // (See comments in header file) |
|
271 // -------------------------------------------------------------------------- |
|
272 // |
|
273 void CHttpUploadWorker::CompleteAndNotify( TInt aError ) |
|
274 { |
|
275 iSessionTimer->Cancel(); |
|
276 |
|
277 iProcessState = EHttpTransactionIdle; |
|
278 iHttpTransaction.Cancel(); |
|
279 iHttpTransaction.Close(); |
|
280 |
|
281 delete iRequestBodyBuffer; |
|
282 iRequestBodyBuffer = NULL; |
|
283 |
|
284 // call reset so that this worker can be used for the next download |
|
285 Reset(); |
|
286 if ( iProcessedFile ) |
|
287 { |
|
288 iObserver->TransferCompleted( iProcessedFile->Key(), aError ); |
|
289 } |
|
290 |
|
291 delete iProcessedFile; |
|
292 iProcessedFile = NULL; |
|
293 |
|
294 iOverallDataSize = 0; |
|
295 iFile.Close(); |
|
296 |
|
297 // inform the worker observer |
|
298 iCallback->WorkerCompleted(); |
|
299 } |
|
300 |
|
301 // -------------------------------------------------------------------------- |
|
302 // CHttpUploadWorker::StartProcessL() |
|
303 // (See comments in header file) |
|
304 // -------------------------------------------------------------------------- |
|
305 // |
|
306 void CHttpUploadWorker::StartProcessL() |
|
307 { |
|
308 CHttpTransferWorker::StartProcessL(); |
|
309 |
|
310 SendL(); |
|
311 } |
|
312 |
|
313 // -------------------------------------------------------------------------- |
|
314 // CHttpUploadWorker::SendL() |
|
315 // (See comments in header file) |
|
316 // -------------------------------------------------------------------------- |
|
317 // |
|
318 void CHttpUploadWorker::SendL() |
|
319 { |
|
320 // iAlreadyDone need to be reset |
|
321 iSendDataCount = 0; |
|
322 iBodyFileOffset = 0; |
|
323 iHttpStatus = 0; |
|
324 iMoreToCome = EFalse; |
|
325 iAlreadyDone = EFalse; |
|
326 // Open the file in the file system |
|
327 User::LeaveIfError( iFile.Open( iFsSession, |
|
328 *(iProcessedFile->Path()), |
|
329 EFileShareReadersOnly | EFileRead ) ); |
|
330 |
|
331 User::LeaveIfError( iFile.Size( iOverallDataSize ) ); |
|
332 |
|
333 // get read buffer size from the Central Repository |
|
334 iRequestBodyBuffer = HBufC8::NewL( iBufferSize ); |
|
335 |
|
336 InvokeHttpMethodL(); |
|
337 |
|
338 // Change state of the state machine |
|
339 iProcessState = EHttpPostSent; |
|
340 } |
|
341 |
|
342 // -------------------------------------------------------------------------- |
|
343 // CHttpUploadWorker::InvokeHttpMethodL() |
|
344 // (See comments in header file) |
|
345 // -------------------------------------------------------------------------- |
|
346 // |
|
347 void CHttpUploadWorker::InvokeHttpMethodL() |
|
348 { |
|
349 // This actually creates the transaction, sets the headers and body |
|
350 // and then starts the transaction. |
|
351 TBool contentTypeExists = EFalse; |
|
352 |
|
353 // open HTTP transaction |
|
354 TUriParser8 uri; |
|
355 User::LeaveIfError( uri.Parse( *( iProcessedFile->Uri() ) ) ); |
|
356 |
|
357 // POST HTTP method |
|
358 RStringF method = iStringPool.StringF( HTTP::EPOST, |
|
359 RHTTPSession::GetTable() ); |
|
360 CleanupClosePushL( method ); |
|
361 |
|
362 iHttpTransaction = iSession.OpenTransactionL( uri, *this, method ); |
|
363 |
|
364 RHTTPHeaders hdr = iHttpTransaction.Request().GetHeaderCollection(); |
|
365 |
|
366 SetHeaderL( hdr, HTTP::EUserAgent, KModuleName ); |
|
367 SetHeaderL( hdr, HTTP::EAccept, KAllowedData ); |
|
368 |
|
369 //Set the property of upnphttptransfer to ENotifyOnDisconnect |
|
370 //Set the property of HTTP Transaction to EEnableDisconnectNotification |
|
371 //The MHFRunL can get the really http error. |
|
372 iHttpTransaction.PropertySet().SetPropertyL( |
|
373 iSession.StringPool().StringF( |
|
374 HTTP::ENotifyOnDisconnect,RHTTPSession::GetTable() ), |
|
375 iSession.StringPool().StringF( |
|
376 HTTP::EEnableDisconnectNotification, |
|
377 RHTTPSession::GetTable() ) ); |
|
378 // Add arbitrary Http headers |
|
379 RPointerArray<CHttpHeader> headerArray = iProcessedFile->Headers(); |
|
380 TBool expect100ContinueFound = EFalse; |
|
381 for ( TInt i = 0; i < headerArray.Count(); i++ ) |
|
382 { |
|
383 const TDesC8& headerName = headerArray[i]->FieldName(); |
|
384 const TDesC8& headerValue = headerArray[i]->FieldValue(); |
|
385 |
|
386 SetHeaderL( hdr, |
|
387 headerName, |
|
388 headerValue ); |
|
389 if ( headerName == KContentTypeName() ) |
|
390 { |
|
391 contentTypeExists = ETrue; |
|
392 } |
|
393 if ( headerName == KExpect() ) |
|
394 { |
|
395 if ( headerValue == K100Continue() ) |
|
396 { |
|
397 // Wait for 100 continue before sending the body in case of |
|
398 // "Expect: 100-Continue" header. |
|
399 RHTTPTransactionPropertySet propSet = |
|
400 iHttpTransaction.PropertySet(); |
|
401 RStringF notifyContinue = |
|
402 iStringPool.StringF( |
|
403 HTTP::ENotify100Continue, |
|
404 RHTTPSession::GetTable() ); |
|
405 RStringF enableNotification = |
|
406 iStringPool.StringF( |
|
407 HTTP::EEnableNotification, |
|
408 RHTTPSession::GetTable() ); |
|
409 THTTPHdrVal val( enableNotification ); |
|
410 propSet.SetPropertyL( notifyContinue, val ); |
|
411 |
|
412 // we found "Expect: 100-continue"-header |
|
413 expect100ContinueFound = ETrue; |
|
414 |
|
415 // Need to start a timer when sending the headers that waits |
|
416 // for some time and if no response during that time, sends |
|
417 // this event to continue with the body. |
|
418 i100ContinueTimer = CPeriodic::NewL( CActive::EPriorityStandard ); |
|
419 i100ContinueTimer->Start( |
|
420 K100ContinueResponseWaitTime, // time to cancel waiting |
|
421 K100ContinueResponseWaitTime, // this is not actually used |
|
422 TCallBack( Cancel100ContinueWaitL, this ) ); |
|
423 } |
|
424 } |
|
425 } |
|
426 |
|
427 if ( contentTypeExists == EFalse ) |
|
428 { |
|
429 SetHeaderL( hdr, HTTP::EContentType, KDefaultContentType ); |
|
430 } |
|
431 |
|
432 if ( !expect100ContinueFound ) |
|
433 { |
|
434 // "Expect: 100-continue" header not found. Do not wait for |
|
435 // 100-continue. This might not be needed but it is added here to |
|
436 // avoid possible regression by not changing the previous behaviour |
|
437 // too much. |
|
438 RHTTPTransactionPropertySet propSet = iHttpTransaction.PropertySet(); |
|
439 RStringF notifyContinue = |
|
440 iStringPool.StringF( |
|
441 HTTP::ENotify100Continue, |
|
442 RHTTPSession::GetTable() ); |
|
443 RStringF disableNotification = |
|
444 iStringPool.StringF( |
|
445 HTTP::EDisableNotification, |
|
446 RHTTPSession::GetTable() ); |
|
447 THTTPHdrVal val( disableNotification ); |
|
448 propSet.SetPropertyL( notifyContinue, val ); |
|
449 } |
|
450 |
|
451 // Set Body data |
|
452 MHTTPDataSupplier* dataSupplier = this; |
|
453 iHttpTransaction.Request().SetBody( *dataSupplier ); |
|
454 |
|
455 // submit the request |
|
456 iHttpTransaction.SubmitL(); |
|
457 |
|
458 //set timer |
|
459 iSessionTimer->Cancel(); |
|
460 iSessionTimer->AfterSeconds( KSessionTimeout ); |
|
461 CleanupStack::PopAndDestroy( &method ); |
|
462 } |
|
463 |
|
464 // -------------------------------------------------------------------------- |
|
465 // CHttpUploadWorker::MHFRunL() |
|
466 // (See comments in header file) |
|
467 // -------------------------------------------------------------------------- |
|
468 void CHttpUploadWorker::MHFRunL( RHTTPTransaction aTransaction, |
|
469 const THTTPEvent& aEvent ) |
|
470 { |
|
471 iSessionTimer->Cancel(); |
|
472 |
|
473 // HTTP status code |
|
474 RHTTPResponse response = aTransaction.Response(); |
|
475 iHttpStatus = response.StatusCode(); |
|
476 |
|
477 // If HTTP status is not what we expected, better to quit |
|
478 // status 0 will be handled in switch case default |
|
479 |
|
480 if ( !( iHttpStatus == HTTPStatus::EOk || |
|
481 iHttpStatus == HTTPStatus::ECreated || |
|
482 iHttpStatus == HTTPStatus::ENoContent || |
|
483 iHttpStatus == HTTPStatus::EContinue || |
|
484 iHttpStatus == 0 ) ) |
|
485 { |
|
486 CompleteAndNotify( |
|
487 MapPostTransactionError( iHttpStatus ) ); |
|
488 } |
|
489 else |
|
490 { |
|
491 |
|
492 switch ( aEvent.iStatus ) |
|
493 { |
|
494 // process the headers |
|
495 case THTTPEvent::EGotResponseHeaders: |
|
496 { |
|
497 // POST response headers |
|
498 // according to the RFC, location header is here if |
|
499 // the entity was created |
|
500 if( !iMoreToCome ) |
|
501 { |
|
502 // Everything has been sent, no need to wait ESucceeded |
|
503 |
|
504 if ( ( iHttpStatus == HTTPStatus::EOk ) || |
|
505 ( iHttpStatus == HTTPStatus::ECreated ) || |
|
506 ( iHttpStatus == HTTPStatus::ENoContent ) ) |
|
507 { |
|
508 CompleteAndNotify( KErrNone ); |
|
509 } |
|
510 else |
|
511 { |
|
512 CompleteAndNotify( |
|
513 MapPostTransactionError( iHttpStatus ) ); |
|
514 } |
|
515 } |
|
516 break; |
|
517 } |
|
518 case THTTPEvent::EGotResponseBodyData: |
|
519 { |
|
520 // discard the body data |
|
521 MHTTPDataSupplier* responseBody = |
|
522 aTransaction.Response().Body(); |
|
523 ASSERT( responseBody ); |
|
524 // Done with that bit of body data |
|
525 responseBody->ReleaseData(); |
|
526 break; |
|
527 } |
|
528 case THTTPEvent::EResponseComplete: |
|
529 { |
|
530 // The transaction's response is complete |
|
531 break; |
|
532 } |
|
533 case THTTPEvent::ESucceeded: |
|
534 { |
|
535 // check the status code and decide whether we |
|
536 // actually succeeded or not |
|
537 |
|
538 // inform observers |
|
539 // according to the RFC we expect 200 OK, |
|
540 // 204 NO CONTENT or |
|
541 // 201 CREATED |
|
542 if ( ( iHttpStatus == HTTPStatus::EOk ) || |
|
543 ( iHttpStatus == HTTPStatus::ECreated ) || |
|
544 ( iHttpStatus == HTTPStatus::ENoContent ) ) |
|
545 { |
|
546 CompleteAndNotify( KErrNone ); |
|
547 } |
|
548 else |
|
549 { |
|
550 CompleteAndNotify( |
|
551 MapPostTransactionError( iHttpStatus ) ); |
|
552 } |
|
553 break; |
|
554 } |
|
555 case THTTPEvent::EFailed: |
|
556 { |
|
557 // This is not supposed to do if transaction is finished |
|
558 // happens when cancel is done |
|
559 if ( iProcessState != EHttpTransactionIdle ) |
|
560 { |
|
561 CompleteAndNotify( |
|
562 MapPostTransactionError( iHttpStatus ) ); |
|
563 } |
|
564 |
|
565 break; |
|
566 } |
|
567 case THTTPEvent::EReceived100Continue: |
|
568 { |
|
569 // The server responded with a 100-Continue status code. |
|
570 // HTTP FW continues with sending the body. |
|
571 Destroy100ContinueTimer(); |
|
572 break; |
|
573 } |
|
574 default: |
|
575 { |
|
576 if ( aEvent.iStatus < 0 ) |
|
577 { |
|
578 CompleteAndNotify( aEvent.iStatus ); |
|
579 } |
|
580 else |
|
581 { |
|
582 CompleteAndNotify( KErrGeneral ); |
|
583 } |
|
584 break; |
|
585 } |
|
586 } |
|
587 } |
|
588 } |
|
589 // -------------------------------------------------------------------------- |
|
590 // CHttpUploadWorker::MHFRunError() |
|
591 // (See comments in header file) |
|
592 // -------------------------------------------------------------------------- |
|
593 TInt CHttpUploadWorker::MHFRunError( TInt /*aError*/, |
|
594 RHTTPTransaction /*aTransaction*/, |
|
595 const THTTPEvent& /* aEvent*/ ) |
|
596 { |
|
597 // Just notify the client about the failure and return KErrNone to |
|
598 // the stack indicating that we handled this error. |
|
599 if ( iProcessState != EHttpTransactionIdle ) |
|
600 { |
|
601 CompleteAndNotify( MapPostTransactionError( iHttpStatus ) ); |
|
602 } |
|
603 |
|
604 return KErrNone; |
|
605 } |
|
606 |
|
607 // -------------------------------------------------------------------------- |
|
608 // CHttpUploadWorker::GetNextDataPart() |
|
609 // (See comments in header file) |
|
610 // -------------------------------------------------------------------------- |
|
611 // |
|
612 TBool CHttpUploadWorker::GetNextDataPart( TPtrC8& aDataPart ) |
|
613 { |
|
614 if ( !iAlreadyDone )// Note: this is zero only when new part is requested |
|
615 { |
|
616 if ( iSendDataCount == 0 ) |
|
617 { |
|
618 // first run |
|
619 TInt pos = iBodyFileOffset; |
|
620 iFile.Seek( ESeekStart, pos ); |
|
621 } |
|
622 |
|
623 // We read data that will be given to the stack next time, |
|
624 // or we will find out that there is no more data... |
|
625 TInt readLength; |
|
626 if ( ( iOverallDataSize - iSendDataCount ) >= iBufferSize ) |
|
627 { |
|
628 readLength = iBufferSize; |
|
629 } |
|
630 else |
|
631 { |
|
632 readLength = iOverallDataSize - iSendDataCount; |
|
633 } |
|
634 |
|
635 TPtr8 requestBodyBufferPtr = iRequestBodyBuffer->Des(); |
|
636 |
|
637 TInt err = iFile.Read( requestBodyBufferPtr, readLength ); |
|
638 iSendDataCount = iSendDataCount + iRequestBodyBuffer->Length(); |
|
639 if ( err == KErrNone ) |
|
640 { |
|
641 if ( ( iSendDataCount < iOverallDataSize ) && |
|
642 ( iRequestBodyBuffer->Length() > 0 ) ) |
|
643 { |
|
644 iMoreToCome = ETrue; |
|
645 } |
|
646 } |
|
647 iAlreadyDone = ETrue; |
|
648 } // on first call, allocate the current part |
|
649 |
|
650 aDataPart.Set( *iRequestBodyBuffer ); // .. otherwise, just re-use it |
|
651 |
|
652 //set timer |
|
653 iSessionTimer->Cancel(); |
|
654 iSessionTimer->AfterSeconds( KSessionTimeout ); |
|
655 |
|
656 return !iMoreToCome; |
|
657 } |
|
658 |
|
659 // -------------------------------------------------------------------------- |
|
660 // CHttpUploadWorker::ReleaseData() |
|
661 // (See comments in header file) |
|
662 // -------------------------------------------------------------------------- |
|
663 // |
|
664 void CHttpUploadWorker::ReleaseData() |
|
665 { |
|
666 // HTTP client is ready with the current data |
|
667 // notify observer if notifications are required |
|
668 // and tell stack whether we have more data coming |
|
669 // when done, close file etc. |
|
670 |
|
671 // notify iObserver if iTrackProgress flag is on |
|
672 if ( iProcessedFile->TrackingOn() ) |
|
673 { |
|
674 iObserver->TransferProgress( iProcessedFile->Key(), |
|
675 iSendDataCount, |
|
676 iOverallDataSize ); |
|
677 } |
|
678 |
|
679 if ( iMoreToCome ) |
|
680 { |
|
681 TRAP_IGNORE( iHttpTransaction.NotifyNewRequestBodyPartL() ); |
|
682 iMoreToCome = EFalse; |
|
683 } |
|
684 |
|
685 iAlreadyDone = EFalse; |
|
686 } |
|
687 |
|
688 // -------------------------------------------------------------------------- |
|
689 // CHttpUploadWorker::OverallDataSize() |
|
690 // (See comments in header file) |
|
691 // -------------------------------------------------------------------------- |
|
692 // |
|
693 TInt CHttpUploadWorker::OverallDataSize() |
|
694 { |
|
695 return iOverallDataSize; |
|
696 } |
|
697 |
|
698 // -------------------------------------------------------------------------- |
|
699 // CHttpUploadWorker::Reset() |
|
700 // (See comments in header file) |
|
701 // -------------------------------------------------------------------------- |
|
702 // |
|
703 TInt CHttpUploadWorker::Reset() |
|
704 { |
|
705 // Reset send data count and buffer. This will cause GetNextDataPart() |
|
706 // to start from the beginning. |
|
707 iSendDataCount = 0; |
|
708 |
|
709 // Destroy the 100 continue response wait timer if it exists. |
|
710 Destroy100ContinueTimer(); |
|
711 |
|
712 return KErrNone; |
|
713 } |
|
714 |
|
715 // -------------------------------------------------------------------------- |
|
716 // CHttpUploadWorker::Destroy100ContinueTimer() |
|
717 // (See comments in header file) |
|
718 // -------------------------------------------------------------------------- |
|
719 // |
|
720 void CHttpUploadWorker::Destroy100ContinueTimer() |
|
721 { |
|
722 if ( i100ContinueTimer ) |
|
723 { |
|
724 i100ContinueTimer->Cancel(); |
|
725 delete i100ContinueTimer; |
|
726 i100ContinueTimer = NULL; |
|
727 } |
|
728 } |
|
729 |
|
730 // -------------------------------------------------------------------------- |
|
731 // CHttpUploadWorker::Cancel100ContinueWaitL() |
|
732 // (See comments in header file) |
|
733 // -------------------------------------------------------------------------- |
|
734 // |
|
735 TInt CHttpUploadWorker::Cancel100ContinueWaitL( TAny* aParam ) |
|
736 { |
|
737 CHttpUploadWorker* self = |
|
738 (static_cast<CHttpUploadWorker*>( aParam )); |
|
739 |
|
740 // Destroy the timer. We don't need subsequent events. |
|
741 self->Destroy100ContinueTimer(); |
|
742 |
|
743 // Cancel waiting for 100 continue. As the server did not respond, |
|
744 // continue with sending the body. |
|
745 self->iHttpTransaction.SendEventL( |
|
746 THTTPEvent::ECancelWaitFor100Continue, |
|
747 THTTPEvent::EOutgoing, |
|
748 THTTPFilterHandle( THTTPFilterHandle::EClient) ); |
|
749 |
|
750 return KErrNone; |
|
751 } |
|
752 |
|
753 // ----------------------------------------------------------------------------- |
|
754 // CHttpUploadWorker::TimerEventL |
|
755 // Disconnect connection |
|
756 // ----------------------------------------------------------------------------- |
|
757 // |
|
758 void CHttpUploadWorker::TimerEventL( CHttpNotifyTimer* /*aTimer*/ ) |
|
759 { |
|
760 CompleteAndNotify( KErrTimedOut ); |
|
761 } |
|
762 |
|
763 // End of File |