|
1 // Copyright (c) 2001-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // $Workfile: obexSendOp_debug.cpp $ |
|
15 // $Author: Stevep $ |
|
16 // $Revision: 22 $ |
|
17 // $Date: 25/03/02 10:52 $ |
|
18 // |
|
19 // |
|
20 |
|
21 //class include |
|
22 #include <obexsendop.h> |
|
23 |
|
24 #ifdef __OBEX_SEND_OP_FILE_DEBUG_MODE__ |
|
25 #pragma message ("//") |
|
26 #pragma message ("// //") |
|
27 #pragma message ("// FILE DEBUG MODE //") |
|
28 #pragma message ("// //") |
|
29 #pragma message ("//") |
|
30 |
|
31 //System includes |
|
32 #include <msvids.h> |
|
33 #include <msventry.h> //CMsvServerEntry |
|
34 #include <btmsgtypeuid.h> //KUidMsgTypeBt |
|
35 #include <irmsgtypeuid.h> //KUidMsgTypeIr |
|
36 //#include <obexpindlguid.h> //KObexPinNotifierUid |
|
37 |
|
38 //user includes |
|
39 // Following are named KErrIrObexClientXXXXX because they are using the irobex.dll (which |
|
40 // should really be called obex.dll now that it supports more than IR) |
|
41 const TInt KErrIrObexClientPutPeerCannotHandleObject = -5504; |
|
42 const TInt KErrIrObexClientFirstPutFailed = -5510; |
|
43 const TInt KErrIrObexClientSubsequentPutFailed = -5511; |
|
44 |
|
45 _LIT(KObexFileDebugIRServiceFolder, "c:\\system\\obexdebug\\IRservice\\output"); |
|
46 _LIT(KObexFileDebugBTServiceFolder, "c:\\system\\obexdebug\\BTservice\\output"); |
|
47 _LIT(KObexFileDebugUSBServiceFolder, "c:\\system\\obexdebug\\USBservice\\output"); |
|
48 _LIT(KOutputFileFormatString, "%S\\%d.obex"); |
|
49 |
|
50 |
|
51 // |
|
52 // CObexServerSendOperation.... CMsvOperation derived op that is intended to be owned by a CMsvReporterOperation or similar. |
|
53 // When this completes, the CMsvReporterOperation completes too |
|
54 // |
|
55 |
|
56 void CObexServerSendOperation::BuildSpecificConstructL() |
|
57 /** |
|
58 Debug second phase constructor. Sets the service path as appropriate to the MTM. |
|
59 */ |
|
60 { |
|
61 //Connect to the file store |
|
62 User::LeaveIfError(iServiceFs.Connect()); |
|
63 |
|
64 //select the output directory dependent upon the MTM being used |
|
65 if (iMtm == KUidMsgTypeBt) |
|
66 { |
|
67 iServicePath = KObexFileDebugBTServiceFolder; |
|
68 } |
|
69 if (iMtm == KUidMsgTypeIrUID) |
|
70 { |
|
71 iServicePath = KObexFileDebugIRServiceFolder; |
|
72 } |
|
73 } |
|
74 |
|
75 void CObexServerSendOperation::BuildSpecificDestructor() |
|
76 /** |
|
77 * Destructor. Cancel()s, deletes owned objects and Close()s the connection to the FileServer. |
|
78 */ |
|
79 { |
|
80 iServiceFs.Close(); |
|
81 } |
|
82 |
|
83 EXPORT_C const TDesC8& CObexServerSendOperation::ProgressL() |
|
84 /** |
|
85 Returns current progress information. |
|
86 |
|
87 @return A reference to a TPckgC<TObexMtmProgress> package pointer descriptor containing progress information on this send operation. |
|
88 @leave KErrXXX system wide error codes |
|
89 */ |
|
90 { |
|
91 // State operation type (and progress). |
|
92 TObexMtmProgress progress; |
|
93 |
|
94 if (progress.iSendState != EInitialsed) |
|
95 progress.iSendState=iSendState; |
|
96 else |
|
97 progress.iSendState = EInitialise; |
|
98 |
|
99 progress.iTotalEntryCount = iAttachmentEntryCount + iFileNameEntryCount; |
|
100 progress.iEntriesDone = progress.iTotalEntryCount - (iNextAttachment+1) - (iFileNameList? iFileNameList->Count() : 0); |
|
101 progress.iCurrentEntrySize = 0; |
|
102 progress.iCurrentBytesTrans = 0; |
|
103 progress.iError = iStatus.Int(); |
|
104 |
|
105 // prepate package buffer for return value, we copy it to a data member so progress |
|
106 // data isn't destroyed when we go out of scope |
|
107 TPckgC<TObexMtmProgress> progressDes(progress); |
|
108 iProgressPckg.Copy(progressDes); //important to use copy() not set(), set() just points to our local descriptor |
|
109 return iProgressPckg; |
|
110 } |
|
111 |
|
112 TInt CObexServerSendOperation::PutObexObjectToServiceFileL() |
|
113 /** |
|
114 * Output the obex object to a file in the service folder |
|
115 * |
|
116 * @leave KErrXXX system wide error codes |
|
117 */ |
|
118 { |
|
119 //count the number of entries already in the folder |
|
120 CDir* serviceDirectoryList = 0; |
|
121 TFileName servicePath = iServicePath; |
|
122 _LIT(KSlash, "\\"); |
|
123 servicePath.Append(KSlash); |
|
124 |
|
125 //Close the file by Reset()ing the obex object--otherwise it can't be copied |
|
126 iObexObject->Reset(); |
|
127 |
|
128 //copy a file to the service folder |
|
129 CFileMan* fileMan = CFileMan::NewL(iServiceFs); |
|
130 TInt err = fileMan->Copy(iSendFile, iServicePath); |
|
131 |
|
132 //count the number of files |
|
133 err = iServiceFs.GetDir(servicePath, KEntryAttNormal, ESortByName, serviceDirectoryList); |
|
134 if (err != KErrNone) |
|
135 { |
|
136 ActivateRunLWithError(err); |
|
137 } |
|
138 |
|
139 //Create a new filename consisting of the service path followed by the new file number .obex |
|
140 TFileName newFileName = iServicePath; |
|
141 newFileName.Format(KOutputFileFormatString, &iServicePath, serviceDirectoryList->Count()); |
|
142 |
|
143 //No longer need serviceDirectoryList |
|
144 delete serviceDirectoryList; |
|
145 |
|
146 //Write the iObexObject member to the file |
|
147 //err = iObexObject->WriteToFile(newFileName); |
|
148 |
|
149 |
|
150 //Now rename it the file |
|
151 //first make the original filename |
|
152 TParse parser; |
|
153 parser.Set(iSendFile, 0, 0); |
|
154 servicePath.Append(parser.NameAndExt()); //servicePath now contains the full path and filename |
|
155 //now actually rename it |
|
156 err = fileMan->Rename(servicePath, newFileName); |
|
157 |
|
158 delete fileMan; |
|
159 return err; |
|
160 } |
|
161 |
|
162 void CObexServerSendOperation::RealRunL() |
|
163 /** |
|
164 Implementation of the send operation state machine. Progresses as: |
|
165 |
|
166 Initialise-->Connect-->ConnectAttemptComplete-->SendObject-->(SendNextObject-->)SendComplete-->Disconnected |
|
167 |
|
168 The SendNextObject state is repeated for each attachment in excess of one. |
|
169 |
|
170 Also handles UserCancelled and SendError states by CompleteObserver()ing with appropriate error codes. |
|
171 |
|
172 Leaves will be passed back to RunL and handled there. |
|
173 |
|
174 @leave Leaves if insufficient memory. |
|
175 @leave Leaves if there is a file error when loading an object from a file |
|
176 */ |
|
177 { |
|
178 const TInt status=iStatus.Int(); |
|
179 |
|
180 switch(iSendState) |
|
181 { |
|
182 case TObexMtmProgress::EInitialise://state 1 |
|
183 { |
|
184 // Timeout for repeatedly trying to connect to remote OBEX device |
|
185 iTimeoutTimer->After(iConnectTimeout); |
|
186 |
|
187 iSendState = TObexMtmProgress::EConnect; |
|
188 SetActive(); |
|
189 CompleteSelf(KErrNone); |
|
190 break; |
|
191 } |
|
192 |
|
193 case TObexMtmProgress::EConnect://state 2 |
|
194 { |
|
195 iSendState=TObexMtmProgress::EConnectAttemptComplete; |
|
196 iStatus=KRequestPending; |
|
197 SetActive(); |
|
198 CompleteSelf(KErrNone); |
|
199 break; |
|
200 } |
|
201 |
|
202 case TObexMtmProgress::EConnectAttemptComplete://state 3 |
|
203 { |
|
204 // A connection _attempt_ has completed - see if it was sucessful. |
|
205 if (status == KErrNone) |
|
206 { |
|
207 // Ok - remote Obex device found and connected to |
|
208 iTimeoutTimer->Cancel(); //cancel connect timeout |
|
209 iSendState=TObexMtmProgress::ESendObject; //Go to send state |
|
210 CompleteSelf(KErrNone); |
|
211 } |
|
212 else if( (status == KErrNotFound) || (status == KErrTimedOut) || (status == KErrIrObexClientNoDevicesFound) ) |
|
213 { |
|
214 // Connect failed. No remote device was found so we try again. |
|
215 // (KErrIrObexClientNoDevicesFound is an OBEX specific error) |
|
216 iSendState=TObexMtmProgress::EConnect; //return to connect state above |
|
217 CompleteSelf(KErrNone); |
|
218 } |
|
219 else |
|
220 { |
|
221 // KErrDisconnected = Found obex machine but had "Obex" IAS query failure. |
|
222 // status>0 means that 'status' obex machines have been found. |
|
223 // IAS Query is where the class of transport is not supported. |
|
224 iTimeoutTimer->Cancel(); |
|
225 iSendState=TObexMtmProgress::ESendError; |
|
226 CompleteSelf(status); |
|
227 } |
|
228 SetActive(); |
|
229 break; |
|
230 } |
|
231 |
|
232 case TObexMtmProgress::ESendObject://state 4 |
|
233 case TObexMtmProgress::ESendNextObject: //state 5: Multiple object support. |
|
234 { |
|
235 iTimeoutTimer->Cancel(); // Cancel last timeout. |
|
236 |
|
237 // For multiObject, check success of previous put. (Single objects won't be affected). |
|
238 if(!CheckStatusOfLastObject (status, iSendState)) |
|
239 { |
|
240 //Last message failed - CheckStatusOfLastObject has taken the necessary steps to notify |
|
241 break; |
|
242 } |
|
243 |
|
244 //Get the next object ready to send |
|
245 TInt err = PrepareCurrentObjectAndSetStateL(); |
|
246 |
|
247 SetActive(); |
|
248 |
|
249 //Check the status of preparation |
|
250 if (err == KErrNone) |
|
251 { |
|
252 //Successful, so try to "send" it |
|
253 iTimeoutTimer->After(iPutTimeout); // Start a new one. |
|
254 CompleteSelf(PutObexObjectToServiceFileL()); |
|
255 } |
|
256 else |
|
257 { |
|
258 //Unsuccessful--report the error |
|
259 iTimeoutTimer->After(iPutTimeout); // Start a new one. |
|
260 CompleteSelf(err); |
|
261 } |
|
262 |
|
263 break; |
|
264 } |
|
265 |
|
266 case TObexMtmProgress::ESendComplete://state 6 |
|
267 { |
|
268 iTimeoutTimer->Cancel(); //cancel iPutTimeout |
|
269 |
|
270 // Object "send(s)" have completed but latest might have completed with an error |
|
271 if(!CheckStatusOfLastObject (status, iSendState)) |
|
272 { |
|
273 //Last message failed - CheckStatusOfLastObject has taken the necessary steps to notify |
|
274 break; |
|
275 } |
|
276 |
|
277 //Now attempt to move the successfully sent message to the sent folder |
|
278 MoveToSentAndSetActiveL(); |
|
279 break; |
|
280 } |
|
281 |
|
282 case TObexMtmProgress::EMovedToSent://state 7 |
|
283 { |
|
284 //Release the lock on the Sent folder, and mark the message as complete |
|
285 CleanupAfterMovedToSent(); |
|
286 |
|
287 iSendState=TObexMtmProgress::EDisconnected; |
|
288 SetActive(); |
|
289 CompleteSelf(KErrNone); |
|
290 |
|
291 // Unfortunately, it is possible for this call to never complete if you send |
|
292 // a file that the peer does not understand. This occurs because some peers |
|
293 // (i.e. Palm) don't seem able to handle this scenario correctly and don't |
|
294 // drop the transport when they should. So we restart the 'put' timeout to |
|
295 // catch this error |
|
296 iTimeoutTimer->After(iPutTimeout); |
|
297 } |
|
298 break; |
|
299 |
|
300 case TObexMtmProgress::EDisconnected://state 8 |
|
301 { |
|
302 iTimeoutTimer->Cancel(); |
|
303 if(status != KErrNone) |
|
304 { |
|
305 // Pass error code onto the owner of this messaging operation |
|
306 iSendState=TObexMtmProgress::ESendError; |
|
307 SetActive(); |
|
308 CompleteSelf(status); |
|
309 } |
|
310 else |
|
311 { |
|
312 // Completed OK - |
|
313 // Signal MS that the CMsvOperation has ended, and clean up. |
|
314 TObexMtmProgress& progress = iProgressPckg(); |
|
315 progress.iError = KErrNone; |
|
316 CompleteObserver(); |
|
317 } |
|
318 break; |
|
319 } |
|
320 |
|
321 case TObexMtmProgress::EUserCancelled://state 9 |
|
322 { |
|
323 // Signal that the CMsvOperation has been cancelled by the user. |
|
324 TObexMtmProgress& progress = iProgressPckg(); |
|
325 progress.iError = KErrCancel; |
|
326 iTimeoutTimer->Cancel(); |
|
327 CompleteObserver(); |
|
328 break; |
|
329 } |
|
330 |
|
331 case TObexMtmProgress::ESendError://state 10 |
|
332 { |
|
333 // General error handling stage. |
|
334 TObexMtmProgress& progress = iProgressPckg(); |
|
335 progress.iError = status; |
|
336 iTimeoutTimer->Cancel(); |
|
337 CompleteObserver(); |
|
338 break; |
|
339 } |
|
340 |
|
341 default: |
|
342 Panic(EObexSendOperationUnknownSendState); |
|
343 } |
|
344 } |
|
345 |
|
346 #endif //__OBEX_SEND_OP_FILE_DEBUG_MODE__ |